From 7f1e24984944f35d2a9eb0fa92fba40eff5cd4e6 Mon Sep 17 00:00:00 2001 From: maziggy Date: Sat, 8 Aug 2026 13:36:54 +0200 Subject: [PATCH] chore(deps): clear every npm audit and pip-audit finding Frontend: - react-router/-dom 7.18.1 -> 7.18.2. The RSC-mode CSRF advisory was carried as a documented exception in the audit gate because its only fix was the 8.3.0 major; upstream backported it, so the exemption lapsed on its own -- an entry only holds while fixAvailable.isSemVerMajor is true. The allowlist is now empty; the machinery stays for the next one. - dompurify 3.4.12 -> 3.4.13. Ships in the app, but the path is unreachable: no hooks registered, IN_PLACE never used. - js-yaml override ^4.3.0 -> ^5.2.3 (fix not backported below 5.x, so a major) and nanoid override ^3.3.18. Both dev-only, via eslint and postcss. eslintrc calls only load(), on the legacy .eslintrc.yml path this repo does not use; eslint, vite build and 2861 frontend tests pass on it. Backend: - cryptography >=48.0.1 -> >=50.0.0, aiohttp >=3.14.0 -> >=3.14.3, pyopenssl >=26.3.0 -> >=26.4.0. CI resolves from scratch and was already installing the fixed releases; the floors cover the case CI does not, an existing venv where >= is satisfied and `pip install -r` upgrades nothing. pyOpenSSL has to move with cryptography -- each release caps it to a narrow window, so a stale pyOpenSSL pins cryptography below its own fix line. --- .github/workflows/ci.yml | 15 ++-- CHANGELOG.md | 6 ++ frontend/package-lock.json | 43 +++++---- frontend/package.json | 9 +- requirements.txt | 33 +++---- .../{index-DPZgvI9N.js => index-DjrhopFm.js} | 88 +++++++++---------- static/index.html | 2 +- 7 files changed, 101 insertions(+), 95 deletions(-) rename static/assets/{index-DPZgvI9N.js => index-DjrhopFm.js} (75%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index efb92b9a1..7f2b9cc8b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -203,15 +203,12 @@ jobs: vulns = data.get('vulnerabilities', {}) # Documented advisory exceptions: high/critical findings whose only offered # 'fix' is a semver-major change and which do not apply to how Bambuddy ships. - # Keyed by GHSA id; RE-REVIEW ON EVERY react-router BUMP. - # GHSA-qwww-vcr4-c8h2 - React Router RSC-mode CSRF. Bambuddy is a Vite SPA - # using BrowserRouter with no RSC runtime (@react-router/server is NOT - # installed), so the vulnerable code path is unreachable. No non-major fix - # exists (7.18.1 is the most-patched 7.x - it clears 14 other advisories that - # older 7.x carry - and the RSC fix landed only in the 8.3.0 major). react-router - # /-dom are pinned to 7.18.1 in package.json. If a non-major fix ships, this stops - # being exempt (major-only guard below) and the gate fails until we take it. - ALLOWLIST = {'GHSA-qwww-vcr4-c8h2'} + # Keyed by GHSA id. An entry only holds while the fix stays major-only (see + # fix_is_major below) - once upstream backports, the gate fails until we take + # the patch. That is what retired the one entry this list used to carry: + # GHSA-qwww-vcr4-c8h2 (React Router RSC-mode CSRF) shipped in 7.18.2, so the + # pin moved rather than the exception staying. + ALLOWLIST = set() def advisory_ids(name, seen=None): seen = seen if seen is not None else set() if name in seen: diff --git a/CHANGELOG.md b/CHANGELOG.md index c1e52b968..b9453c0be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,12 @@ All notable changes to Bambuddy will be documented in this file. - **Ukrainian was listed above Russian in the language picker** — Locales appear in the picker in the order they were added, but `uk` had been inserted ahead of `ru` in the import block, the resources map and the list the picker renders. Moved to the end of all three; the alphabetically sorted supported-language list already had it in the right place. Frontend-only, with no behaviour change beyond the row order. - **Setting Spoolman options over the API with a true/false value returned a server error** — `PUT /settings/spoolman` accepts a free-form body, and sending the natural JSON form for a switch — `{"spoolman_enabled": true}` rather than `{"spoolman_enabled": "true"}` — came back as a 500 with nothing useful in it. The shipped UI always sends strings, so this only affected people driving Bambuddy from a script or a Home Assistant `rest_command`, which is exactly where a real boolean is the obvious thing to send. **Root cause.** Settings are stored as text and every reader compares them as text, but the submitted value went in untouched. Deciding whether Spoolman had just been switched on called a string operation on it, which a boolean does not have; and the raw boolean was also written straight to a text column, which SQLite quietly turns into 1/0 while PostgreSQL refuses it outright — so the stored result depended on which database the install used. **Fix.** Boolean-ish settings are now converted to a canonical `true`/`false` on the way in, accepting real booleans, `1`/`0`, and the usual spellings (`True`, `yes`, `on`) case-insensitively, since this is a documented API that scripts talk to. A value with no sensible reading, such as `"banana"`, now returns a 400 naming the field instead of being stored as-is and silently treated as off. Two details are preserved deliberately: a blank value still means "use the default" for the two options that default to on, and reading a stored value stays as strict as it has always been elsewhere in the codebase, so no existing row changes meaning. Text options are checked too, so a JSON object can no longer be stored as its own printed form. One incidental improvement: a value stored as `True` by an earlier API call showed as off in the UI, which compares case-sensitively, while the backend treated it as on — canonical storage removes that disagreement. Covered by tests across the accepted spellings, the rejected values, the blank-means-default behaviour, and the read path. +### Security +- **Patched the build-time frontend dependencies flagged by `npm audit` (GHSA-rgw5-rvv9-x895, GHSA-5p4m-2wfm-xmqj, GHSA-2v37-7h3g-55p8)** — Three transitive dependencies of `eslint` and `postcss`, bumped through the existing `overrides` block. `brace-expansion` goes `^5.0.8` → `^5.0.9` for a denial-of-service via unbounded expansion: the first advisory was answered in 5.0.8 by capping the length of the combined result, but that cap covered only the accumulator the results are merged into and not the two intermediate arrays that feed it, so a small brace pattern could still exhaust the heap — fatally, and beyond the reach of a `try`/`catch` — or stall the event loop for minutes. 5.0.9 bounds both arrays as they are built. `js-yaml` goes `^4.3.0` → `^5.2.3` for quadratic CPU consumption while resolving `!!omap`; that fix was deliberately not backported to 3.x or 4.x, which is what makes this a major, so it was checked rather than assumed — `@eslint/eslintrc` calls exactly one js-yaml API, `load()`, and only on the legacy `.eslintrc.yml` path this repo does not use, and `eslint`, `vite build` and the full frontend test suite all pass on it. `nanoid` is newly pinned at `^3.3.18`, where a custom generator asked for size zero loops forever; the patch stays inside 3.x. All three are build and lint-time tooling — none is part of the shipped app, so no running Bambuddy install was exposed. The pins are needed because `npm audit fix` cannot lift a transitive of `eslint` or `postcss` on its own. +- **Took the backported React Router fix and retired the audit exception (GHSA-qwww-vcr4-c8h2)** — `react-router`/`react-router-dom` move from 7.18.1 to **7.18.2**. The RSC-mode CSRF advisory noted in 1.2.5.1 was carried as a documented, fail-closed exception in the CI audit gate, because at the time its only fix was the 8.3.0 major and `react-router-dom` has no 8.x — adopting it would have meant migrating every import to `react-router` plus a React peer bump. Upstream has since backported the patch to the 7.x line, so the pin moves and the exception is gone, leaving the gate's allowlist empty. That happened on its own rather than by anyone remembering to check: an entry only holds while the offered fix is semver-major, so the gate failed the moment the backport shipped instead of quietly carrying a now-fixable advisory. The finding was never reachable here in any case — Bambuddy is a Vite SPA using `BrowserRouter` with no RSC runtime installed. `npm audit fix --force` remains deliberately avoided; its suggested "fix" is a downgrade to 7.11.0, which reintroduces the 14 advisories older 7.x releases carry. +- **`dompurify` 3.4.12 → 3.4.13 (GHSA-55q2-fjhq-7xh7)** — Removing a hook mid-sanitisation could leave a detached subtree executable in DOMPurify's `IN_PLACE` mode, an XSS. Unlike the build-time bumps above, DOMPurify does ship in the app — it sanitises MakerWorld-supplied design summaries and project notes before they are rendered — so it is worth being explicit that this particular path was not reachable: Bambuddy registers no DOMPurify hooks and never uses `IN_PLACE`, calling only the string-returning `sanitize()` with an explicit tag and attribute allowlist. The patched release is inside the existing `^3.4.10` range, so this is a lockfile move rather than a new pin. +- **Raised the `cryptography`, `pyOpenSSL` and `aiohttp` floors so a resolve cannot pick a vulnerable-but-satisfying version (PYSEC-2026-3552, PYSEC-2026-3545/3546/3547)** — `cryptography>=48.0.1` → `>=50.0.0` and `aiohttp>=3.14.0` → `>=3.14.3`. Neither had gone stale in CI, which resolves from scratch and so was already installing the fixed releases; the floors matter for the case CI does not cover, an existing environment where `>=` is already satisfied and `pip install -r` therefore upgrades nothing. `pyOpenSSL` moves `>=26.3.0` → `>=26.4.0` for a subtler reason worth writing down: every pyOpenSSL release caps `cryptography` to a narrow window (26.3.0 permits `<50`, 26.4.0 permits `<51`), so a stale pyOpenSSL silently holds `cryptography` below its own fix line and pip cannot climb past the cap even when asked for it directly. The two floors have to move together, which the comment in `requirements.txt` now says. Bambuddy's `cryptography` surface is indirect throughout — asyncssh, pyOpenSSL, py-vapid, http_ece, pywebpush — and the 49 → 50 major was verified rather than assumed: the X.509/PKCS#7/EC/RSA entry points and pyftpdlib's `TLS_FTPHandler` all import, `ruff` is clean, and the full backend suite passes unchanged. + ## [1.2.5.1] - 2026-07-27 ### Added diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c949c7e1e..d6a1b91ad 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -33,7 +33,7 @@ "react-dom": "^19.2.0", "react-i18next": "^16.3.5", "react-markdown": "^9.1.0", - "react-router-dom": "7.18.1", + "react-router-dom": "7.18.2", "react-simple-keyboard": "^3.8.164", "recharts": "^3.5.1", "remark-gfm": "^4.0.1", @@ -3173,9 +3173,9 @@ } }, "node_modules/brace-expansion": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.8.tgz", - "integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "dev": true, "dependencies": { "balanced-match": "^4.0.2" @@ -3778,9 +3778,9 @@ "peer": true }, "node_modules/dompurify": { - "version": "3.4.12", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.12.tgz", - "integrity": "sha512-zQvGet8Z2sWbQhCmfFz/T5QWH2oBmjnqK3qvOjaqaNLrLEF912WamU+ohnTp0TCep/MFVHpdJuCZEdFOdTnEFg==", + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.13.tgz", + "integrity": "sha512-2vmYIoqjze2d+kakP8S/nS5shfsl587kzwEjcGlTdiksUVgFHnFCsLYDVj/JNqJVOQZGSYBTmuycv0PodwmnMQ==", "optionalDependencies": { "@types/trusted-types": "^2.0.7" } @@ -4913,9 +4913,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", - "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.2.3.tgz", + "integrity": "sha512-n+mUVyUX5bVv7G/G2zyIHOhdxfuU1dY2NOFzTQUWiMUbFss8b57NFlgCCaggU78wSw5KVS9cllzeLyzyR+n5nw==", "dev": true, "funding": [ { @@ -4927,12 +4927,11 @@ "url": "https://github.com/sponsors/nodeca" } ], - "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, "bin": { - "js-yaml": "bin/js-yaml.js" + "js-yaml": "bin/js-yaml.mjs" } }, "node_modules/jsdom": { @@ -6481,9 +6480,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.16", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", - "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", "dev": true, "funding": [ { @@ -7135,9 +7134,9 @@ } }, "node_modules/react-router": { - "version": "7.18.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.1.tgz", - "integrity": "sha512-GDLgg3i3uM0aeJO3Fm+TCS+sDQ7gu12T6x0qdTEzcwqEfleci7JwugVNIF3U//0FWKnJT7ptG+20B2jfDqnZAg==", + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.2.tgz", + "integrity": "sha512-aUVMjFm3GAPTTZL7oYr5E7ETiqfQCHRLH+B+5afnICvf0r7kkK4eR6SMuwbSTJw/7t+12khT/Kahij49fqOCIg==", "dependencies": { "cookie": "^1.0.1", "set-cookie-parser": "^2.6.0" @@ -7156,11 +7155,11 @@ } }, "node_modules/react-router-dom": { - "version": "7.18.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.1.tgz", - "integrity": "sha512-KaZh+X/6UtEp28x51AUYZDMg9NGoz2ja3dNHa+ta/tk40vCzKhQ/RypCWBMLbmDr6//E24Vv5uPsrqXFozdkAg==", + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.2.tgz", + "integrity": "sha512-AIKJ/jgGlFb3EbfCXk5Gzshiwt+l3mqbCrNjmEWMMjqQxNJ3svBa6bgzFyCC2Sw3RA0VWF1kg3uQf2OFhxb8hw==", "dependencies": { - "react-router": "7.18.1" + "react-router": "7.18.2" }, "engines": { "node": ">=20.0.0" diff --git a/frontend/package.json b/frontend/package.json index 9f40df21d..23e329db8 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -40,7 +40,7 @@ "react-dom": "^19.2.0", "react-i18next": "^16.3.5", "react-markdown": "^9.1.0", - "react-router-dom": "7.18.1", + "react-router-dom": "7.18.2", "react-simple-keyboard": "^3.8.164", "recharts": "^3.5.1", "remark-gfm": "^4.0.1", @@ -48,9 +48,10 @@ }, "overrides": { "minimatch": "^10.2.1", - "brace-expansion": "^5.0.8", - "js-yaml": "^4.3.0", - "react-router": "7.18.1" + "brace-expansion": "^5.0.9", + "js-yaml": "^5.2.3", + "nanoid": "^3.3.18", + "react-router": "7.18.2" }, "devDependencies": { "@eslint/js": "^9.39.1", diff --git a/requirements.txt b/requirements.txt index d9bf74bab..6caed4cc7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -40,14 +40,17 @@ aioftp>=0.22.0 # Virtual Printer (emulates Bambu printer for slicer uploads) pyftpdlib>=2.0.0 -# 46.x line has GHSA-537c-gmf6-5ccf; 48.0.1 is the fix release. Upstream's -# X.509 / PKCS#7 surface is in our trust path via asyncssh, pyOpenSSL, -# py-vapid, http_ece, pywebpush. -cryptography>=48.0.1 -# Transitive of asyncssh / pywebpush. pyopenssl<26.3.0 caps `cryptography<47` -# so without this floor the resolver either downgrades cryptography below -# the GHSA-537c-gmf6-5ccf fix line or installs an inconsistent pair. -pyopenssl>=26.3.0 +# Upstream's X.509 / PKCS#7 surface is in our trust path via asyncssh, +# pyOpenSSL, py-vapid, http_ece, pywebpush, so this floor tracks the current +# fix release: 46.x had GHSA-537c-gmf6-5ccf (fixed in 48.0.1), and 49.0.0 has +# PYSEC-2026-3552 (fixed in 50.0.0). +cryptography>=50.0.0 +# Transitive of asyncssh / pywebpush, and the gate on the line above: each +# pyOpenSSL release caps `cryptography` to a narrow window (26.3.0 allows +# <50, 26.4.0 allows <51), so a stale pyOpenSSL silently pins cryptography +# below its fix line -- pip cannot upgrade past the cap even when asked. +# Raise this floor in the same commit as any cryptography floor. +pyopenssl>=26.4.0 # SpoolBuddy remote SSH updates (pure-Python SSH client; avoids the # OpenSSH `ssh` binary which calls getpwuid() and fails in Docker when @@ -143,13 +146,13 @@ urllib3>=2.7.0 # resolver from picking them. starlette>=1.3.1 -# Transitive of pywebpush (unpinned `aiohttp` requirement). aiohttp 3.13.5 -# has CVE-2026-34993 and CVE-2026-47265, both fixed in 3.14.0. pywebpush -# doesn't declare an upper bound either way, so without this pin the -# resolver keeps installing the vulnerable 3.13.x line. Our direct usage -# in services/external_camera.py (ClientSession, ClientTimeout, ClientError, -# iter_chunked) is unaffected by 3.14.0. -aiohttp>=3.14.0 +# Transitive of pywebpush (unpinned `aiohttp` requirement). pywebpush declares +# no bound in either direction, so without this floor the resolver happily +# installs a vulnerable line: 3.13.5 has CVE-2026-34993 and CVE-2026-47265 +# (fixed in 3.14.0), and 3.14.1 has PYSEC-2026-3545/3546/3547 (3.14.3 clears +# all three). Our direct usage in services/external_camera.py (ClientSession, +# ClientTimeout, ClientError, iter_chunked) is unaffected by either bump. +aiohttp>=3.14.3 # Plate Detection (optional - enables build plate empty detection) opencv-python-headless>=4.8.0 diff --git a/static/assets/index-DPZgvI9N.js b/static/assets/index-DjrhopFm.js similarity index 75% rename from static/assets/index-DPZgvI9N.js rename to static/assets/index-DjrhopFm.js index 2bc1252fb..15473ee12 100644 --- a/static/assets/index-DPZgvI9N.js +++ b/static/assets/index-DjrhopFm.js @@ -1,12 +1,12 @@ -var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),s=(e,n)=>{let r={};for(var i in e)t(r,i,{get:e[i],enumerable:!0});return n||t(r,Symbol.toStringTag,{value:`Module`}),r},c=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;li[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},l=(n,r,a)=>(a=n==null?{}:e(i(n)),c(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n)),u=(e=>typeof require<`u`?require:typeof Proxy<`u`?new Proxy(e,{get:(e,t)=>(typeof require<`u`?require:e)[t]}):e)(function(e){if(typeof require<`u`)return require.apply(this,arguments);throw Error('Calling `require` for "'+e+"\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.")});(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var d=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.iterator;function m(e){return typeof e!=`object`||!e?null:(e=p&&e[p]||e[`@@iterator`],typeof e==`function`?e:null)}var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,_={};function v(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=null)throw Error(`takes an object of state variables to update or a function which returns an object of state variables.`);this.updater.enqueueSetState(this,e,t,`setState`)},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function y(){}y.prototype=v.prototype;function b(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}var x=b.prototype=new y;x.constructor=b,g(x,v.prototype),x.isPureReactComponent=!0;var S=Array.isArray;function C(){}var w={H:null,A:null,T:null,S:null},T=Object.prototype.hasOwnProperty;function E(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function D(e,t){return E(e.type,t,e.props)}function O(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function k(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var A=/\/+/g;function j(e,t){return typeof e==`object`&&e&&e.key!=null?k(``+e.key):t.toString(36)}function M(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(C,C):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function N(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,N(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+j(e,0):a,S(o)?(i=``,c!=null&&(i=c.replace(A,`$&/`)+`/`),N(o,r,i,``,function(e){return e})):o!=null&&(O(o)&&(o=D(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(A,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(S(e))for(var u=0;u{t.exports=d()})),p=o((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m)if(n(c)!==null)m=!0,S||(S=!0,O());else{var t=n(l);t!==null&&j(x,t.startTime-e)}}var S=!1,C=-1,w=5,T=-1;function E(){return g?!0:!(e.unstable_now()-Tt&&E());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&j(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?O():S=!1}}}var O;if(typeof y==`function`)O=function(){y(D)};else if(typeof MessageChannel<`u`){var k=new MessageChannel,A=k.port2;k.port1.onmessage=D,O=function(){A.postMessage(null)}}else O=function(){_(D,0)};function j(t,n){C=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(C),C=-1):h=!0,j(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,S||(S=!0,O()))),r},e.unstable_shouldYield=E,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),m=o(((e,t)=>{t.exports=p()})),h=o((e=>{var t=f();function n(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=h()})),_=o((e=>{var t=m(),n=f(),r=g();function i(e){var t=`https://react.dev/errors/`+e;if(1B||(e.current=z[B],z[B]=null,B--)}function te(e,t){B++,z[B]=e.current,e.current=t}var ne=V(null),re=V(null),ie=V(null),H=V(null);function ae(e,t){switch(te(ie,t),te(re,e),te(ne,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Ud(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Ud(t),e=Wd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}ee(ne),te(ne,e)}function oe(){ee(ne),ee(re),ee(ie)}function U(e){e.memoizedState!==null&&te(H,e);var t=ne.current,n=Wd(t,e.type);t!==n&&(te(re,e),te(ne,n))}function se(e){re.current===e&&(ee(ne),ee(re)),H.current===e&&(ee(H),Zf._currentValue=R)}var ce,le;function ue(e){if(ce===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);ce=t&&t[1]||``,le=-1()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),s=(e,n)=>{let r={};for(var i in e)t(r,i,{get:e[i],enumerable:!0});return n||t(r,Symbol.toStringTag,{value:`Module`}),r},c=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;li[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},l=(n,r,a)=>(a=n==null?{}:e(i(n)),c(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n)),u=(e=>typeof require<`u`?require:typeof Proxy<`u`?new Proxy(e,{get:(e,t)=>(typeof require<`u`?require:e)[t]}):e)(function(e){if(typeof require<`u`)return require.apply(this,arguments);throw Error('Calling `require` for "'+e+"\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.")});(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var d=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.iterator;function m(e){return typeof e!=`object`||!e?null:(e=p&&e[p]||e[`@@iterator`],typeof e==`function`?e:null)}var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,_={};function v(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=null)throw Error(`takes an object of state variables to update or a function which returns an object of state variables.`);this.updater.enqueueSetState(this,e,t,`setState`)},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function y(){}y.prototype=v.prototype;function b(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}var x=b.prototype=new y;x.constructor=b,g(x,v.prototype),x.isPureReactComponent=!0;var S=Array.isArray;function C(){}var w={H:null,A:null,T:null,S:null},T=Object.prototype.hasOwnProperty;function E(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function D(e,t){return E(e.type,t,e.props)}function O(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function k(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var A=/\/+/g;function j(e,t){return typeof e==`object`&&e&&e.key!=null?k(``+e.key):t.toString(36)}function M(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(C,C):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function N(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,N(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+j(e,0):a,S(o)?(i=``,c!=null&&(i=c.replace(A,`$&/`)+`/`),N(o,r,i,``,function(e){return e})):o!=null&&(O(o)&&(o=D(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(A,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(S(e))for(var u=0;u{t.exports=d()})),p=o((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m)if(n(c)!==null)m=!0,S||(S=!0,O());else{var t=n(l);t!==null&&j(x,t.startTime-e)}}var S=!1,C=-1,w=5,T=-1;function E(){return g?!0:!(e.unstable_now()-Tt&&E());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&j(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?O():S=!1}}}var O;if(typeof y==`function`)O=function(){y(D)};else if(typeof MessageChannel<`u`){var k=new MessageChannel,A=k.port2;k.port1.onmessage=D,O=function(){A.postMessage(null)}}else O=function(){_(D,0)};function j(t,n){C=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(C),C=-1):h=!0,j(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,S||(S=!0,O()))),r},e.unstable_shouldYield=E,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),m=o(((e,t)=>{t.exports=p()})),h=o((e=>{var t=f();function n(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=h()})),_=o((e=>{var t=m(),n=f(),r=g();function i(e){var t=`https://react.dev/errors/`+e;if(1B||(e.current=z[B],z[B]=null,B--)}function te(e,t){B++,z[B]=e.current,e.current=t}var ne=V(null),re=V(null),ie=V(null),H=V(null);function ae(e,t){switch(te(ie,t),te(re,e),te(ne,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Ud(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Ud(t),e=Wd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}ee(ne),te(ne,e)}function oe(){ee(ne),ee(re),ee(ie)}function U(e){e.memoizedState!==null&&te(H,e);var t=ne.current,n=Wd(t,e.type);t!==n&&(te(re,e),te(ne,n))}function se(e){re.current===e&&(ee(ne),ee(re)),H.current===e&&(ee(H),Zf._currentValue=R)}var ce,le;function W(e){if(ce===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);ce=t&&t[1]||``,le=-1)`:-1i||c[r]!==l[i]){var u=` -`+c[r].replace(` at new `,` at `);return e.displayName&&u.includes(``)&&(u=u.replace(``,e.displayName)),u}while(1<=r&&0<=i);break}}}finally{de=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:``)?ue(n):``}function pe(e,t){switch(e.tag){case 26:case 27:case 5:return ue(e.type);case 16:return ue(`Lazy`);case 13:return e.child!==t&&t!==null?ue(`Suspense Fallback`):ue(`Suspense`);case 19:return ue(`SuspenseList`);case 0:case 15:return fe(e.type,!1);case 11:return fe(e.type.render,!1);case 1:return fe(e.type,!0);case 31:return ue(`Activity`);default:return``}}function me(e){try{var t=``,n=null;do t+=pe(e,n),n=e,e=e.return;while(e);return t}catch(e){return` +`+c[r].replace(` at new `,` at `);return e.displayName&&u.includes(``)&&(u=u.replace(``,e.displayName)),u}while(1<=r&&0<=i);break}}}finally{ue=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:``)?W(n):``}function fe(e,t){switch(e.tag){case 26:case 27:case 5:return W(e.type);case 16:return W(`Lazy`);case 13:return e.child!==t&&t!==null?W(`Suspense Fallback`):W(`Suspense`);case 19:return W(`SuspenseList`);case 0:case 15:return de(e.type,!1);case 11:return de(e.type.render,!1);case 1:return de(e.type,!0);case 31:return W(`Activity`);default:return``}}function pe(e){try{var t=``,n=null;do t+=fe(e,n),n=e,e=e.return;while(e);return t}catch(e){return` Error generating stack: `+e.message+` -`+e.stack}}var he=Object.prototype.hasOwnProperty,ge=t.unstable_scheduleCallback,_e=t.unstable_cancelCallback,ve=t.unstable_shouldYield,ye=t.unstable_requestPaint,be=t.unstable_now,xe=t.unstable_getCurrentPriorityLevel,Se=t.unstable_ImmediatePriority,Ce=t.unstable_UserBlockingPriority,we=t.unstable_NormalPriority,Te=t.unstable_LowPriority,Ee=t.unstable_IdlePriority,De=t.log,Oe=t.unstable_setDisableYieldValue,ke=null,Ae=null;function je(e){if(typeof De==`function`&&Oe(e),Ae&&typeof Ae.setStrictMode==`function`)try{Ae.setStrictMode(ke,e)}catch{}}var Me=Math.clz32?Math.clz32:Fe,Ne=Math.log,Pe=Math.LN2;function Fe(e){return e>>>=0,e===0?32:31-(Ne(e)/Pe|0)|0}var Ie=256,Le=262144,Re=4194304;function ze(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function Be(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=ze(n))):i=ze(o):i=ze(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=ze(n))):i=ze(o)):i=ze(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function Ve(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function He(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Ue(){var e=Re;return Re<<=1,!(Re&62914560)&&(Re=4194304),e}function We(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function Ge(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function Ke(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0`u`||window.document===void 0||window.document.createElement===void 0),nn=!1;if(tn)try{var rn={};Object.defineProperty(rn,"passive",{get:function(){nn=!0}}),window.addEventListener(`test`,rn,rn),window.removeEventListener(`test`,rn,rn)}catch{nn=!1}var an=null,on=null,sn=null;function cn(){if(sn)return sn;var e,t=on,n=t.length,r,i=`value`in an?an.value:an.textContent,a=i.length;for(e=0;e=Bn),Un=` `,Wn=!1;function Gn(e,t){switch(e){case`keyup`:return Rn.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function Kn(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var qn=!1;function Jn(e,t){switch(e){case`compositionend`:return Kn(t);case`keypress`:return t.which===32?(Wn=!0,Un):null;case`textInput`:return e=t.data,e===Un&&Wn?null:e;default:return null}}function Yn(e,t){if(qn)return e===`compositionend`||!zn&&Gn(e,t)?(e=cn(),sn=on=an=null,qn=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=_r(n)}}function yr(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?yr(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function br(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=At(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=At(e.document)}return t}function xr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var Sr=tn&&`documentMode`in document&&11>=document.documentMode,Cr=null,wr=null,Tr=null,Er=!1;function Dr(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Er||Cr==null||Cr!==At(r)||(r=Cr,`selectionStart`in r&&xr(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),Tr&&gr(Tr,r)||(Tr=r,r=Dd(wr,`onSelect`),0>=o,i-=o,yi=1<<32-Me(t)+i|n<h?(g=d,d=null):g=d.sibling;var _=p(i,d,s[h],c);if(_===null){d===null&&(d=g);break}e&&d&&_.alternate===null&&t(i,d),a=o(_,a,h),u===null?l=_:u.sibling=_,u=_,d=g}if(h===s.length)return n(i,d),Oi&&xi(i,h),l;if(d===null){for(;hg?(_=h,h=null):_=h.sibling;var y=p(a,h,v.value,l);if(y===null){h===null&&(h=_);break}e&&h&&y.alternate===null&&t(a,h),s=o(y,s,g),d===null?u=y:d.sibling=y,d=y,h=_}if(v.done)return n(a,h),Oi&&xi(a,g),u;if(h===null){for(;!v.done;g++,v=c.next())v=f(a,v.value,l),v!==null&&(s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return Oi&&xi(a,g),u}for(h=r(h);!v.done;g++,v=c.next())v=m(h,a,g,v.value,l),v!==null&&(e&&v.alternate!==null&&h.delete(v.key===null?g:v.key),s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return e&&h.forEach(function(e){return t(a,e)}),Oi&&xi(a,g),u}function b(e,r,o,c){if(typeof o==`object`&&o&&o.type===y&&o.key===null&&(o=o.props.children),typeof o==`object`&&o){switch(o.$$typeof){case _:a:{for(var l=o.key;r!==null;){if(r.key===l){if(l=o.type,l===y){if(r.tag===7){n(e,r.sibling),c=a(r,o.props.children),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===O&&Sa(l)===r.type){n(e,r.sibling),c=a(r,o.props),ka(c,o),c.return=e,e=c;break a}n(e,r);break}else t(e,r);r=r.sibling}o.type===y?(c=oi(o.props.children,e.mode,c,o.key),c.return=e,e=c):(c=ai(o.type,o.key,o.props,null,e.mode,c),ka(c,o),c.return=e,e=c)}return s(e);case v:a:{for(l=o.key;r!==null;){if(r.key===l)if(r.tag===4&&r.stateNode.containerInfo===o.containerInfo&&r.stateNode.implementation===o.implementation){n(e,r.sibling),c=a(r,o.children||[]),c.return=e,e=c;break a}else{n(e,r);break}else t(e,r);r=r.sibling}c=li(o,e.mode,c),c.return=e,e=c}return s(e);case O:return o=Sa(o),b(e,r,o,c)}if(F(o))return h(e,r,o,c);if(M(o)){if(l=M(o),typeof l!=`function`)throw Error(i(150));return o=l.call(o),g(e,r,o,c)}if(typeof o.then==`function`)return b(e,r,Oa(o),c);if(o.$$typeof===C)return b(e,r,Xi(e,o),c);Aa(e,o)}return typeof o==`string`&&o!==``||typeof o==`number`||typeof o==`bigint`?(o=``+o,r!==null&&r.tag===6?(n(e,r.sibling),c=a(r,o),c.return=e,e=c):(n(e,r),c=si(o,e.mode,c),c.return=e,e=c),s(e)):n(e,r)}return function(e,t,n,r){try{Da=0;var i=b(e,t,n,r);return Ea=null,i}catch(t){if(t===ga||t===va)throw t;var a=ti(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var Ma=ja(!0),Na=ja(!1),Pa=!1;function Fa(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Ia(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function La(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Ra(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,Fl&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=Qr(e),Zr(e,null,n),t}return Jr(e,r,t,n),Qr(e)}function za(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,Je(e,n)}}function Ba(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var Va=!1;function Ha(){if(Va){var e=sa;if(e!==null)throw e}}function Ua(e,t,n,r){Va=!1;var i=e.updateQueue;Pa=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var f=s.lane&-536870913,m=f!==s.lane;if(m?(Rl&f)===f:(r&f)===f){f!==0&&f===oa&&(Va=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var h=e,g=s;f=t;var _=n;switch(g.tag){case 1:if(h=g.payload,typeof h==`function`){d=h.call(_,d,f);break a}d=h;break a;case 3:h.flags=h.flags&-65537|128;case 0:if(h=g.payload,f=typeof h==`function`?h.call(_,d,f):h,f==null)break a;d=p({},d,f);break a;case 2:Pa=!0}}f=s.callback,f!==null&&(e.flags|=64,m&&(e.flags|=8192),m=i.callbacks,m===null?i.callbacks=[f]:m.push(f))}else m={lane:f,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=m,c=d):u=u.next=m,o|=f;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;m=s,s=m.next,m.next=null,i.lastBaseUpdate=m,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),Kl|=o,e.lanes=o,e.memoizedState=d}}function Wa(e,t){if(typeof e!=`function`)throw Error(i(191,e));e.call(t)}function Ga(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=I.T,s={};I.T=s,ks(e,!1,t,n);try{var c=i(),l=I.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?Os(e,t,ua(c,r),mu(e)):Os(e,t,r,mu(e))}catch(n){Os(e,t,{then:function(){},status:`rejected`,reason:n},mu())}finally{L.p=a,o!==null&&s.types!==null&&(o.types=s.types),I.T=o}}function vs(){}function ys(e,t,n,r){if(e.tag!==5)throw Error(i(476));var a=bs(e).queue;_s(e,a,t,R,n===null?vs:function(){return xs(e),n(r)})}function bs(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:R,baseState:R,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Y,lastRenderedState:R},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Y,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function xs(e){var t=bs(e);t.next===null&&(t=e.alternate.memoizedState),Os(e,t.next.queue,{},mu())}function Ss(){return Yi(Zf)}function Cs(){return To().memoizedState}function ws(){return To().memoizedState}function Ts(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=mu();e=La(n);var r=Ra(t,e,n);r!==null&&(gu(r,t,n),za(r,t,n)),t={cache:na()},e.payload=t;return}t=t.return}}function Es(e,t,n){var r=mu();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},As(e)?js(t,n):(n=Yr(e,t,n,r),n!==null&&(gu(n,e,r),Ms(n,t,r)))}function Ds(e,t,n){Os(e,t,n,mu())}function Os(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(As(e))js(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,hr(s,o))return Jr(e,t,i,0),Il===null&&qr(),!1}catch{}if(n=Yr(e,t,i,r),n!==null)return gu(n,e,r),Ms(n,t,r),!0}return!1}function ks(e,t,n,r){if(r={lane:2,revertLane:dd(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},As(e)){if(t)throw Error(i(479))}else t=Yr(e,n,r,2),t!==null&&gu(t,e,2)}function As(e){var t=e.alternate;return e===oo||t!==null&&t===oo}function js(e,t){uo=lo=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Ms(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,Je(e,n)}}var Ns={readContext:Yi,use:Oo,useCallback:_o,useContext:_o,useEffect:_o,useImperativeHandle:_o,useLayoutEffect:_o,useInsertionEffect:_o,useMemo:_o,useReducer:_o,useRef:_o,useState:_o,useDebugValue:_o,useDeferredValue:_o,useTransition:_o,useSyncExternalStore:_o,useId:_o,useHostTransitionStatus:_o,useFormState:_o,useActionState:_o,useOptimistic:_o,useMemoCache:_o,useCacheRefresh:_o};Ns.useEffectEvent=_o;var Ps={readContext:Yi,use:Oo,useCallback:function(e,t){return wo().memoizedState=[e,t===void 0?null:t],e},useContext:Yi,useEffect:rs,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),ts(4194308,4,us.bind(null,t,e),n)},useLayoutEffect:function(e,t){return ts(4194308,4,e,t)},useInsertionEffect:function(e,t){ts(4,2,e,t)},useMemo:function(e,t){var n=wo();t=t===void 0?null:t;var r=e();if(fo){je(!0);try{e()}finally{je(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=wo();if(n!==void 0){var i=n(t);if(fo){je(!0);try{n(t)}finally{je(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=Es.bind(null,oo,e),[r.memoizedState,e]},useRef:function(e){var t=wo();return e={current:e},t.memoizedState=e},useState:function(e){e=zo(e);var t=e.queue,n=Ds.bind(null,oo,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:fs,useDeferredValue:function(e,t){return hs(wo(),e,t)},useTransition:function(){var e=zo(!1);return e=_s.bind(null,oo,e.queue,!0,!1),wo().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=oo,a=wo();if(Oi){if(n===void 0)throw Error(i(407));n=n()}else{if(n=t(),Il===null)throw Error(i(349));Rl&127||Po(r,t,n)}a.memoizedState=n;var o={value:n,getSnapshot:t};return a.queue=o,rs(Io.bind(null,r,o,e),[e]),r.flags|=2048,$o(9,{destroy:void 0},Fo.bind(null,r,o,n,t),null),n},useId:function(){var e=wo(),t=Il.identifierPrefix;if(Oi){var n=bi,r=yi;n=(r&~(1<<32-Me(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=po++,0<\/script>`,o=o.removeChild(o.firstChild);break;case`select`:o=typeof r.is==`string`?s.createElement(`select`,{is:r.is}):s.createElement(`select`),r.multiple?o.multiple=!0:r.size&&(o.size=r.size);break;default:o=typeof r.is==`string`?s.createElement(a,{is:r.is}):s.createElement(a)}}o[et]=t,o[tt]=r;a:for(s=t.child;s!==null;){if(s.tag===5||s.tag===6)o.appendChild(s.stateNode);else if(s.tag!==4&&s.tag!==27&&s.child!==null){s.child.return=s,s=s.child;continue}if(s===t)break a;for(;s.sibling===null;){if(s.return===null||s.return===t)break a;s=s.return}s.sibling.return=s.return,s=s.sibling}t.stateNode=o;a:switch(Id(o,a,r),a){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&Oc(t)}}return Nc(t),kc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&Oc(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(i(166));if(e=ie.current,Fi(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,a=Ei,a!==null)switch(a.tag){case 27:case 5:r=a.memoizedProps}e[et]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||Nd(e.nodeValue,n)),e||Mi(t,!0)}else e=Hd(e).createTextNode(r),e[et]=t,t.stateNode=e}return Nc(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=Fi(t),n!==null){if(e===null){if(!r)throw Error(i(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(i(557));e[et]=t}else Ii(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;Nc(t),e=!1}else n=Li(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(ro(t),t):(ro(t),null);if(t.flags&128)throw Error(i(558))}return Nc(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(a=Fi(t),r!==null&&r.dehydrated!==null){if(e===null){if(!a)throw Error(i(318));if(a=t.memoizedState,a=a===null?null:a.dehydrated,!a)throw Error(i(317));a[et]=t}else Ii(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;Nc(t),a=!1}else a=Li(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=a),a=!0;if(!a)return t.flags&256?(ro(t),t):(ro(t),null)}return ro(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,a=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(a=r.alternate.memoizedState.cachePool.pool),o=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(o=r.memoizedState.cachePool.pool),o!==a&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),jc(t,t.updateQueue),Nc(t),null);case 4:return oe(),e===null&&Cd(t.stateNode.containerInfo),Nc(t),null;case 10:return Ui(t.type),Nc(t),null;case 19:if(ee(io),r=t.memoizedState,r===null)return Nc(t),null;if(a=(t.flags&128)!=0,o=r.rendering,o===null)if(a)Mc(r,!1);else{if(Gl!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(o=K(e),o!==null){for(t.flags|=128,Mc(r,!1),e=o.updateQueue,t.updateQueue=e,jc(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)ii(n,e),n=n.sibling;return te(io,io.current&1|2),Oi&&xi(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&be()>nu&&(t.flags|=128,a=!0,Mc(r,!1),t.lanes=4194304)}else{if(!a)if(e=K(o),e!==null){if(t.flags|=128,a=!0,e=e.updateQueue,t.updateQueue=e,jc(t,e),Mc(r,!0),r.tail===null&&r.tailMode===`hidden`&&!o.alternate&&!Oi)return Nc(t),null}else 2*be()-r.renderingStartTime>nu&&n!==536870912&&(t.flags|=128,a=!0,Mc(r,!1),t.lanes=4194304);r.isBackwards?(o.sibling=t.child,t.child=o):(e=r.last,e===null?t.child=o:e.sibling=o,r.last=o)}return r.tail===null?(Nc(t),null):(e=r.tail,r.rendering=e,r.tail=e.sibling,r.renderingStartTime=be(),e.sibling=null,n=io.current,te(io,a?n&1|2:n&1),Oi&&xi(t,r.treeForkCount),e);case 22:case 23:return ro(t),Xa(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(Nc(t),t.subtreeFlags&6&&(t.flags|=8192)):Nc(t),n=t.updateQueue,n!==null&&jc(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&ee(fa),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),Ui(ta),Nc(t),null;case 25:return null;case 30:return null}throw Error(i(156,t.tag))}function Fc(e,t){switch(wi(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Ui(ta),oe(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return se(t),null;case 31:if(t.memoizedState!==null){if(ro(t),t.alternate===null)throw Error(i(340));Ii()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(ro(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(i(340));Ii()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return ee(io),null;case 4:return oe(),null;case 10:return Ui(t.type),null;case 22:case 23:return ro(t),Xa(),e!==null&&ee(fa),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return Ui(ta),null;case 25:return null;default:return null}}function Ic(e,t){switch(wi(t),t.tag){case 3:Ui(ta),oe();break;case 26:case 27:case 5:se(t);break;case 4:oe();break;case 31:t.memoizedState!==null&&ro(t);break;case 13:ro(t);break;case 19:ee(io);break;case 10:Ui(t.type);break;case 22:case 23:ro(t),Xa(),e!==null&&ee(fa);break;case 24:Ui(ta)}}function Lc(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){Ku(t,t.return,e)}}function Rc(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){Ku(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){Ku(t,t.return,e)}}function zc(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{Ga(t,n)}catch(t){Ku(e,e.return,t)}}}function Bc(e,t,n){n.props=Vs(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){Ku(e,t,n)}}function Vc(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){Ku(e,t,n)}}function Hc(e,t){var n=e.ref,r=e.refCleanup;if(n!==null)if(typeof r==`function`)try{r()}catch(n){Ku(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){Ku(e,t,n)}else n.current=null}function Uc(e){var t=e.type,n=e.memoizedProps,r=e.stateNode;try{a:switch(t){case`button`:case`input`:case`select`:case`textarea`:n.autoFocus&&r.focus();break a;case`img`:n.src?r.src=n.src:n.srcSet&&(r.srcset=n.srcSet)}}catch(t){Ku(e,e.return,t)}}function Wc(e,t,n){try{var r=e.stateNode;Ld(r,e.type,n,t),r[tt]=t}catch(t){Ku(e,e.return,t)}}function Gc(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Zd(e.type)||e.tag===4}function Kc(e){a:for(;;){for(;e.sibling===null;){if(e.return===null||Gc(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Zd(e.type)||e.flags&2||e.child===null||e.tag===4)continue a;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function qc(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?(n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n).insertBefore(e,t):(t=n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n,t.appendChild(e),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=Kt));else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode,t=null),e=e.child,e!==null))for(qc(e,t,n),e=e.sibling;e!==null;)qc(e,t,n),e=e.sibling}function Jc(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode),e=e.child,e!==null))for(Jc(e,t,n),e=e.sibling;e!==null;)Jc(e,t,n),e=e.sibling}function Yc(e){var t=e.stateNode,n=e.memoizedProps;try{for(var r=e.type,i=t.attributes;i.length;)t.removeAttributeNode(i[0]);Id(t,r,n),t[et]=e,t[tt]=n}catch(t){Ku(e,e.return,t)}}var Xc=!1,X=!1,Zc=!1,Qc=typeof WeakSet==`function`?WeakSet:Set,$c=null;function el(e,t){if(e=e.containerInfo,Bd=op,e=br(e),xr(e)){if(`selectionStart`in e)var n={start:e.selectionStart,end:e.selectionEnd};else a:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var a=r.anchorOffset,o=r.focusNode;r=r.focusOffset;try{n.nodeType,o.nodeType}catch{n=null;break a}var s=0,c=-1,l=-1,u=0,d=0,f=e,p=null;b:for(;;){for(var m;f!==n||a!==0&&f.nodeType!==3||(c=s+a),f!==o||r!==0&&f.nodeType!==3||(l=s+r),f.nodeType===3&&(s+=f.nodeValue.length),(m=f.firstChild)!==null;)p=f,f=m;for(;;){if(f===e)break b;if(p===n&&++u===a&&(c=s),p===o&&++d===r&&(l=s),(m=f.nextSibling)!==null)break;f=p,p=f.parentNode}f=m}n=c===-1||l===-1?null:{start:c,end:l}}else n=null}n||={start:0,end:0}}else n=null;for(Vd={focusedElem:e,selectionRange:n},op=!1,$c=t;$c!==null;)if(t=$c,e=t.child,t.subtreeFlags&1028&&e!==null)e.return=t,$c=e;else for(;$c!==null;){switch(t=$c,o=t.alternate,e=t.flags,t.tag){case 0:if(e&4&&(e=t.updateQueue,e=e===null?null:e.events,e!==null))for(n=0;n title`))),Id(o,r,n),o[et]=e,pt(o),r=o;break a;case`link`:var s=Bf(`link`,`href`,a).get(r+(n.href||``));if(s){for(var c=0;cg&&(o=g,g=h,h=o);var _=vr(s,h),v=vr(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,I.T=null,n=uu,uu=null;var o=ou,s=cu;if(au=0,su=ou=null,cu=0,Fl&6)throw Error(i(331));var c=Fl;if(Fl|=4,Al(o.current),Sl(o,o.current,s,n),Fl=c,od(0,!1),Ae&&typeof Ae.onPostCommitFiberRoot==`function`)try{Ae.onPostCommitFiberRoot(ke,o)}catch{}return!0}finally{L.p=a,I.T=r,Hu(e,t)}}function Gu(e,t,n){t=di(n,t),t=qs(e.stateNode,t,2),e=Ra(e,t,2),e!==null&&(Ge(e,2),ad(e))}function Ku(e,t,n){if(e.tag===3)Gu(e,e,n);else for(;t!==null;){if(t.tag===3){Gu(t,e,n);break}else if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(iu===null||!iu.has(r))){e=di(n,e),n=Js(2),r=Ra(t,n,2),r!==null&&(Ys(n,r,t,e),Ge(r,2),ad(r));break}}t=t.return}}function qu(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new Pl;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(Ul=!0,i.add(n),e=Ju.bind(null,e,t,n),t.then(e,e))}function Ju(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,Il===e&&(Rl&n)===n&&(Gl===4||Gl===3&&(Rl&62914560)===Rl&&300>be()-eu?!(Fl&2)&&Cu(e,0):Jl|=n,Xl===Rl&&(Xl=0)),ad(e)}function Yu(e,t){t===0&&(t=Ue()),e=Xr(e,t),e!==null&&(Ge(e,t),ad(e))}function Xu(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),Yu(e,n)}function Zu(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,a=e.memoizedState;a!==null&&(n=a.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(i(314))}r!==null&&r.delete(t),Yu(e,n)}function Qu(e,t){return ge(e,t)}var $u=null,ed=null,td=!1,nd=!1,rd=!1,id=0;function ad(e){e!==ed&&e.next===null&&(ed===null?$u=ed=e:ed=ed.next=e),nd=!0,td||(td=!0,Q())}function od(e,t){if(!rd&&nd){rd=!0;do for(var n=!1,r=$u;r!==null;){if(!t)if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-Me(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,ud(r,a))}else a=Rl,a=Be(r,r===Il?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||Ve(r,a)||(n=!0,ud(r,a));r=r.next}while(n);rd=!1}}function sd(){cd()}function cd(){nd=td=!1;var e=0;id!==0&&Kd()&&(e=id);for(var t=be(),n=null,r=$u;r!==null;){var i=r.next,a=ld(r,t);a===0?(r.next=null,n===null?$u=i:n.next=i,i===null&&(ed=n)):(n=r,(e!==0||a&3)&&(nd=!0)),r=i}au!==0&&au!==5||od(e,!1),id!==0&&(id=0)}function ld(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&Rd(d)&&(c=c.responseEnd,o+=u*(c`u`?null:document;function xf(e,t,n){var r=bf;if(r&&typeof t==`string`&&t){var i=Mt(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),hf.has(i)||(hf.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),Id(t,`link`,e),pt(t),r.head.appendChild(t)))}}function Sf(e){_f.D(e),xf(`dns-prefetch`,e,null)}function Cf(e,t){_f.C(e,t),xf(`preconnect`,e,t)}function wf(e,t,n){_f.L(e,t,n);var r=bf;if(r&&e&&t){var i=`link[rel="preload"][as="`+Mt(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+Mt(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+Mt(n.imageSizes)+`"]`)):i+=`[href="`+Mt(e)+`"]`;var a=i;switch(t){case`style`:a=kf(e);break;case`script`:a=Nf(e)}mf.has(a)||(e=p({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),mf.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(Af(a))||t===`script`&&r.querySelector(Pf(a))||(t=r.createElement(`link`),Id(t,`link`,e),pt(t),r.head.appendChild(t)))}}function Tf(e,t){_f.m(e,t);var n=bf;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+Mt(r)+`"][href="`+Mt(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=Nf(e)}if(!mf.has(a)&&(e=p({rel:`modulepreload`,href:e},t),mf.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(Pf(a)))return}r=n.createElement(`link`),Id(r,`link`,e),pt(r),n.head.appendChild(r)}}}function Ef(e,t,n){_f.S(e,t,n);var r=bf;if(r&&e){var i=ft(r).hoistableStyles,a=kf(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(Af(a)))s.loading=5;else{e=p({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=mf.get(a))&&Lf(e,n);var c=o=r.createElement(`link`);pt(c),Id(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,If(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function Df(e,t){_f.X(e,t);var n=bf;if(n&&e){var r=ft(n).hoistableScripts,i=Nf(e),a=r.get(i);a||(a=n.querySelector(Pf(i)),a||(e=p({src:e,async:!0},t),(t=mf.get(i))&&Rf(e,t),a=n.createElement(`script`),pt(a),Id(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function tee(e,t){_f.M(e,t);var n=bf;if(n&&e){var r=ft(n).hoistableScripts,i=Nf(e),a=r.get(i);a||(a=n.querySelector(Pf(i)),a||(e=p({src:e,async:!0,type:`module`},t),(t=mf.get(i))&&Rf(e,t),a=n.createElement(`script`),pt(a),Id(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Of(e,t,n,r){var a=(a=ie.current)?gf(a):null;if(!a)throw Error(i(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(t=kf(n.href),n=ft(a).hoistableStyles,r=n.get(t),r||(r={type:`style`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=kf(n.href);var o=ft(a).hoistableStyles,s=o.get(e);if(s||(a=a.ownerDocument||a,s={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},o.set(e,s),(o=a.querySelector(Af(e)))&&!o._p&&(s.instance=o,s.state.loading=5),mf.has(e)||(n={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},mf.set(e,n),o||Mf(a,e,n,s.state))),t&&r===null)throw Error(i(528,``));return s}if(t&&r!==null)throw Error(i(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(t=Nf(n),n=ft(a).hoistableScripts,r=n.get(t),r||(r={type:`script`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(i(444,e))}}function kf(e){return`href="`+Mt(e)+`"`}function Af(e){return`link[rel="stylesheet"][`+e+`]`}function jf(e){return p({},e,{"data-precedence":e.precedence,precedence:null})}function Mf(e,t,n,r){e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)?r.loading=1:(t=e.createElement(`link`),r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2}),Id(t,`link`,n),pt(t),e.head.appendChild(t))}function Nf(e){return`[src="`+Mt(e)+`"]`}function Pf(e){return`script[async]`+e}function Ff(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+Mt(n.href)+`"]`);if(r)return t.instance=r,pt(r),r;var a=p({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),pt(r),Id(r,`style`,a),If(r,n.precedence,e),t.instance=r;case`stylesheet`:a=kf(n.href);var o=e.querySelector(Af(a));if(o)return t.state.loading|=4,t.instance=o,pt(o),o;r=jf(n),(a=mf.get(a))&&Lf(r,a),o=(e.ownerDocument||e).createElement(`link`),pt(o);var s=o;return s._p=new Promise(function(e,t){s.onload=e,s.onerror=t}),Id(o,`link`,r),t.state.loading|=4,If(o,n.precedence,e),t.instance=o;case`script`:return o=Nf(n.src),(a=e.querySelector(Pf(o)))?(t.instance=a,pt(a),a):(r=n,(a=mf.get(o))&&(r=p({},n),Rf(r,a)),e=e.ownerDocument||e,a=e.createElement(`script`),pt(a),Id(a,`link`,r),e.head.appendChild(a),t.instance=a);case`void`:return null;default:throw Error(i(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,If(r,n.precedence,e));return t.instance}function If(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function Hf(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function Uf(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Wf(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=kf(r.href),a=t.querySelector(Af(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=qf.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,pt(a);return}a=t.ownerDocument||t,r=jf(r),(i=mf.get(i))&&Lf(r,i),a=a.createElement(`link`),pt(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),Id(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=qf.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var Gf=0;function Kf(e,t){return e.stylesheets&&e.count===0&&Yf(e,e.stylesheets),0Gf?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function qf(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Yf(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Jf=null;function Yf(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Jf=new Map,t.forEach(Xf,e),Jf=null,qf.call(e))}function Xf(e,t){if(!(t.state.loading&4)){var n=Jf.get(e);if(n)var r=n.get(null);else{n=new Map,Jf.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=_()})),y=l(f()),b=v(),x=e=>typeof e==`string`,S=()=>{let e,t,n=new Promise((n,r)=>{e=n,t=r});return n.resolve=e,n.reject=t,n},C=e=>e==null?``:``+e,w=(e,t,n)=>{e.forEach(e=>{t[e]&&(n[e]=t[e])})},T=/###/g,E=e=>e&&e.indexOf(`###`)>-1?e.replace(T,`.`):e,D=e=>!e||x(e),O=(e,t,n)=>{let r=x(t)?t.split(`.`):t,i=0;for(;i{let{obj:r,k:i}=O(e,t,Object);if(r!==void 0||t.length===1){r[i]=n;return}let a=t[t.length-1],o=t.slice(0,t.length-1),s=O(e,o,Object);for(;s.obj===void 0&&o.length;)a=`${o[o.length-1]}.${a}`,o=o.slice(0,o.length-1),s=O(e,o,Object),s?.obj&&s.obj[`${s.k}.${a}`]!==void 0&&(s.obj=void 0);s.obj[`${s.k}.${a}`]=n},A=(e,t,n,r)=>{let{obj:i,k:a}=O(e,t,Object);i[a]=i[a]||[],i[a].push(n)},j=(e,t)=>{let{obj:n,k:r}=O(e,t);if(n&&Object.prototype.hasOwnProperty.call(n,r))return n[r]},M=(e,t,n)=>{let r=j(e,n);return r===void 0?j(t,n):r},N=(e,t,n)=>{for(let r in t)r!==`__proto__`&&r!==`constructor`&&(r in e?x(e[r])||e[r]instanceof String||x(t[r])||t[r]instanceof String?n&&(e[r]=t[r]):N(e[r],t[r],n):e[r]=t[r]);return e},P=e=>e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,`\\$&`),F={"&":`&`,"<":`<`,">":`>`,'"':`"`,"'":`'`,"/":`/`},I=e=>x(e)?e.replace(/[&<>"'\/]/g,e=>F[e]):e,L=class{constructor(e){this.capacity=e,this.regExpMap=new Map,this.regExpQueue=[]}getRegExp(e){let t=this.regExpMap.get(e);if(t!==void 0)return t;let n=new RegExp(e);return this.regExpQueue.length===this.capacity&&this.regExpMap.delete(this.regExpQueue.shift()),this.regExpMap.set(e,n),this.regExpQueue.push(e),n}},R=[` `,`,`,`?`,`!`,`;`],z=new L(20),B=(e,t,n)=>{t||=``,n||=``;let r=R.filter(e=>t.indexOf(e)<0&&n.indexOf(e)<0);if(r.length===0)return!0;let i=z.getRegExp(`(${r.map(e=>e===`?`?`\\?`:e).join(`|`)})`),a=!i.test(e);if(!a){let t=e.indexOf(n);t>0&&!i.test(e.substring(0,t))&&(a=!0)}return a},V=(e,t,n=`.`)=>{if(!e)return;if(e[t])return Object.prototype.hasOwnProperty.call(e,t)?e[t]:void 0;let r=t.split(n),i=e;for(let e=0;e-1&&oe?.replace(`_`,`-`),te={type:`logger`,log(e){this.output(`log`,e)},warn(e){this.output(`warn`,e)},error(e){this.output(`error`,e)},output(e,t){console?.[e]?.apply?.(console,t)}},ne=new class e{constructor(e,t={}){this.init(e,t)}init(e,t={}){this.prefix=t.prefix||`i18next:`,this.logger=e||te,this.options=t,this.debug=t.debug}log(...e){return this.forward(e,`log`,``,!0)}warn(...e){return this.forward(e,`warn`,``,!0)}error(...e){return this.forward(e,`error`,``)}deprecate(...e){return this.forward(e,`warn`,`WARNING DEPRECATED: `,!0)}forward(e,t,n,r){return r&&!this.debug?null:(x(e[0])&&(e[0]=`${n}${this.prefix} ${e[0]}`),this.logger[t](e))}create(t){return new e(this.logger,{prefix:`${this.prefix}:${t}:`,...this.options})}clone(t){return t||=this.options,t.prefix=t.prefix||this.prefix,new e(this.logger,t)}},re=class{constructor(){this.observers={}}on(e,t){return e.split(` `).forEach(e=>{this.observers[e]||(this.observers[e]=new Map);let n=this.observers[e].get(t)||0;this.observers[e].set(t,n+1)}),this}off(e,t){if(this.observers[e]){if(!t){delete this.observers[e];return}this.observers[e].delete(t)}}emit(e,...t){this.observers[e]&&Array.from(this.observers[e].entries()).forEach(([e,n])=>{for(let r=0;r{for(let i=0;i-1&&this.options.ns.splice(t,1)}getResource(e,t,n,r={}){let i=r.keySeparator===void 0?this.options.keySeparator:r.keySeparator,a=r.ignoreJSONStructure===void 0?this.options.ignoreJSONStructure:r.ignoreJSONStructure,o;e.indexOf(`.`)>-1?o=e.split(`.`):(o=[e,t],n&&(Array.isArray(n)?o.push(...n):x(n)&&i?o.push(...n.split(i)):o.push(n)));let s=j(this.data,o);return!s&&!t&&!n&&e.indexOf(`.`)>-1&&(e=o[0],t=o[1],n=o.slice(2).join(`.`)),s||!a||!x(n)?s:V(this.data?.[e]?.[t],n,i)}addResource(e,t,n,r,i={silent:!1}){let a=i.keySeparator===void 0?this.options.keySeparator:i.keySeparator,o=[e,t];n&&(o=o.concat(a?n.split(a):n)),e.indexOf(`.`)>-1&&(o=e.split(`.`),r=t,t=o[1]),this.addNamespaces(t),k(this.data,o,r),i.silent||this.emit(`added`,e,t,n,r)}addResources(e,t,n,r={silent:!1}){for(let r in n)(x(n[r])||Array.isArray(n[r]))&&this.addResource(e,t,r,n[r],{silent:!0});r.silent||this.emit(`added`,e,t,n)}addResourceBundle(e,t,n,r,i,a={silent:!1,skipCopy:!1}){let o=[e,t];e.indexOf(`.`)>-1&&(o=e.split(`.`),r=n,n=t,t=o[1]),this.addNamespaces(t);let s=j(this.data,o)||{};a.skipCopy||(n=JSON.parse(JSON.stringify(n))),r?N(s,n,i):s={...s,...n},k(this.data,o,s),a.silent||this.emit(`added`,e,t,n)}removeResourceBundle(e,t){this.hasResourceBundle(e,t)&&delete this.data[e][t],this.removeNamespaces(t),this.emit(`removed`,e,t)}hasResourceBundle(e,t){return this.getResource(e,t)!==void 0}getResourceBundle(e,t){return t||=this.options.defaultNS,this.getResource(e,t)}getDataByLanguage(e){return this.data[e]}hasLanguageSomeTranslations(e){let t=this.getDataByLanguage(e);return!!(t&&Object.keys(t)||[]).find(e=>t[e]&&Object.keys(t[e]).length>0)}toJSON(){return this.data}},H={processors:{},addPostProcessor(e){this.processors[e.name]=e},handle(e,t,n,r,i){return e.forEach(e=>{t=this.processors[e]?.process(t,n,r,i)??t}),t}},ae=Symbol(`i18next/PATH_KEY`);function oe(){let e=[],t=Object.create(null),n;return t.get=(r,i)=>(n?.revoke?.(),i===ae?e:(e.push(i),n=Proxy.revocable(r,t),n.proxy)),Proxy.revocable(Object.create(null),t).proxy}function U(e,t){let{[ae]:n}=e(oe());return n.join(t?.keySeparator??`.`)}var se={},ce=e=>!x(e)&&typeof e!=`boolean`&&typeof e!=`number`,le=class e extends re{constructor(e,t={}){super(),w([`resourceStore`,`languageUtils`,`pluralResolver`,`interpolator`,`backendConnector`,`i18nFormat`,`utils`],e,this),this.options=t,this.options.keySeparator===void 0&&(this.options.keySeparator=`.`),this.logger=ne.create(`translator`)}changeLanguage(e){e&&(this.language=e)}exists(e,t={interpolation:{}}){let n={...t};if(e==null)return!1;let r=this.resolve(e,n);if(r?.res===void 0)return!1;let i=ce(r.res);return!(n.returnObjects===!1&&i)}extractFromKey(e,t){let n=t.nsSeparator===void 0?this.options.nsSeparator:t.nsSeparator;n===void 0&&(n=`:`);let r=t.keySeparator===void 0?this.options.keySeparator:t.keySeparator,i=t.ns||this.options.defaultNS||[],a=n&&e.indexOf(n)>-1,o=!this.options.userDefinedKeySeparator&&!t.keySeparator&&!this.options.userDefinedNsSeparator&&!t.nsSeparator&&!B(e,n,r);if(a&&!o){let t=e.match(this.interpolator.nestingRegexp);if(t&&t.length>0)return{key:e,namespaces:x(i)?[i]:i};let a=e.split(n);(n!==r||n===r&&this.options.ns.indexOf(a[0])>-1)&&(i=a.shift()),e=a.join(r)}return{key:e,namespaces:x(i)?[i]:i}}translate(t,n,r){let i=typeof n==`object`?{...n}:n;if(typeof i!=`object`&&this.options.overloadTranslationOptionHandler&&(i=this.options.overloadTranslationOptionHandler(arguments)),typeof i==`object`&&(i={...i}),i||={},t==null)return``;typeof t==`function`&&(t=U(t,{...this.options,...i})),Array.isArray(t)||(t=[String(t)]);let a=i.returnDetails===void 0?this.options.returnDetails:i.returnDetails,o=i.keySeparator===void 0?this.options.keySeparator:i.keySeparator,{key:s,namespaces:c}=this.extractFromKey(t[t.length-1],i),l=c[c.length-1],u=i.nsSeparator===void 0?this.options.nsSeparator:i.nsSeparator;u===void 0&&(u=`:`);let d=i.lng||this.language,f=i.appendNamespaceToCIMode||this.options.appendNamespaceToCIMode;if(d?.toLowerCase()===`cimode`)return f?a?{res:`${l}${u}${s}`,usedKey:s,exactUsedKey:s,usedLng:d,usedNS:l,usedParams:this.getUsedParamsDetails(i)}:`${l}${u}${s}`:a?{res:s,usedKey:s,exactUsedKey:s,usedLng:d,usedNS:l,usedParams:this.getUsedParamsDetails(i)}:s;let p=this.resolve(t,i),m=p?.res,h=p?.usedKey||s,g=p?.exactUsedKey||s,_=[`[object Number]`,`[object Function]`,`[object RegExp]`],v=i.joinArrays===void 0?this.options.joinArrays:i.joinArrays,y=!this.i18nFormat||this.i18nFormat.handleAsObject,b=i.count!==void 0&&!x(i.count),S=e.hasDefaultValue(i),C=b?this.pluralResolver.getSuffix(d,i.count,i):``,w=i.ordinal&&b?this.pluralResolver.getSuffix(d,i.count,{ordinal:!1}):``,T=b&&!i.ordinal&&i.count===0,E=T&&i[`defaultValue${this.options.pluralSeparator}zero`]||i[`defaultValue${C}`]||i[`defaultValue${w}`]||i.defaultValue,D=m;y&&!m&&S&&(D=E);let O=ce(D),k=Object.prototype.toString.apply(D);if(y&&D&&O&&_.indexOf(k)<0&&!(x(v)&&Array.isArray(D))){if(!i.returnObjects&&!this.options.returnObjects){this.options.returnedObjectHandler||this.logger.warn(`accessing an object - but returnObjects options is not enabled!`);let e=this.options.returnedObjectHandler?this.options.returnedObjectHandler(h,D,{...i,ns:c}):`key '${s} (${this.language})' returned an object instead of string.`;return a?(p.res=e,p.usedParams=this.getUsedParamsDetails(i),p):e}if(o){let e=Array.isArray(D),t=e?[]:{},n=e?g:h;for(let e in D)if(Object.prototype.hasOwnProperty.call(D,e)){let r=`${n}${o}${e}`;S&&!m?t[e]=this.translate(r,{...i,defaultValue:ce(E)?E[e]:void 0,joinArrays:!1,ns:c}):t[e]=this.translate(r,{...i,joinArrays:!1,ns:c}),t[e]===r&&(t[e]=D[e])}m=t}}else if(y&&x(v)&&Array.isArray(m))m=m.join(v),m&&=this.extendTranslation(m,t,i,r);else{let e=!1,n=!1;!this.isValidLookup(m)&&S&&(e=!0,m=E),this.isValidLookup(m)||(n=!0,m=s);let a=(i.missingKeyNoValueFallbackToKey||this.options.missingKeyNoValueFallbackToKey)&&n?void 0:m,c=S&&E!==m&&this.options.updateMissing;if(n||e||c){if(this.logger.log(c?`updateKey`:`missingKey`,d,l,s,c?E:m),o){let e=this.resolve(s,{...i,keySeparator:!1});e&&e.res&&this.logger.warn(`Seems the loaded translations were in flat JSON format instead of nested. Either set keySeparator: false on init or make sure your translations are published in nested format.`)}let e=[],t=this.languageUtils.getFallbackCodes(this.options.fallbackLng,i.lng||this.language);if(this.options.saveMissingTo===`fallback`&&t&&t[0])for(let n=0;n{let r=S&&n!==m?n:a;this.options.missingKeyHandler?this.options.missingKeyHandler(e,l,t,r,c,i):this.backendConnector?.saveMissing&&this.backendConnector.saveMissing(e,l,t,r,c,i),this.emit(`missingKey`,e,l,t,m)};this.options.saveMissing&&(this.options.saveMissingPlurals&&b?e.forEach(e=>{let t=this.pluralResolver.getSuffixes(e,i);T&&i[`defaultValue${this.options.pluralSeparator}zero`]&&t.indexOf(`${this.options.pluralSeparator}zero`)<0&&t.push(`${this.options.pluralSeparator}zero`),t.forEach(t=>{n([e],s+t,i[`defaultValue${t}`]||E)})}):n(e,s,E))}m=this.extendTranslation(m,t,i,p,r),n&&m===s&&this.options.appendNamespaceToMissingKey&&(m=`${l}${u}${s}`),(n||e)&&this.options.parseMissingKeyHandler&&(m=this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey?`${l}${u}${s}`:s,e?m:void 0,i))}return a?(p.res=m,p.usedParams=this.getUsedParamsDetails(i),p):m}extendTranslation(e,t,n,r,i){if(this.i18nFormat?.parse)e=this.i18nFormat.parse(e,{...this.options.interpolation.defaultVariables,...n},n.lng||this.language||r.usedLng,r.usedNS,r.usedKey,{resolved:r});else if(!n.skipInterpolation){n.interpolation&&this.interpolator.init({...n,interpolation:{...this.options.interpolation,...n.interpolation}});let a=x(e)&&(n?.interpolation?.skipOnVariables===void 0?this.options.interpolation.skipOnVariables:n.interpolation.skipOnVariables),o;if(a){let t=e.match(this.interpolator.nestingRegexp);o=t&&t.length}let s=n.replace&&!x(n.replace)?n.replace:n;if(this.options.interpolation.defaultVariables&&(s={...this.options.interpolation.defaultVariables,...s}),e=this.interpolator.interpolate(e,s,n.lng||this.language||r.usedLng,n),a){let t=e.match(this.interpolator.nestingRegexp),r=t&&t.length;oi?.[0]===e[0]&&!n.context?(this.logger.warn(`It seems you are nesting recursively key: ${e[0]} in key: ${t[0]}`),null):this.translate(...e,t),n)),n.interpolation&&this.interpolator.reset()}let a=n.postProcess||this.options.postProcess,o=x(a)?[a]:a;return e!=null&&o?.length&&n.applyPostProcessor!==!1&&(e=H.handle(o,e,t,this.options&&this.options.postProcessPassResolved?{i18nResolved:{...r,usedParams:this.getUsedParamsDetails(n)},...n}:n,this)),e}resolve(e,t={}){let n,r,i,a,o;return x(e)&&(e=[e]),e.forEach(e=>{if(this.isValidLookup(n))return;let s=this.extractFromKey(e,t),c=s.key;r=c;let l=s.namespaces;this.options.fallbackNS&&(l=l.concat(this.options.fallbackNS));let u=t.count!==void 0&&!x(t.count),d=u&&!t.ordinal&&t.count===0,f=t.context!==void 0&&(x(t.context)||typeof t.context==`number`)&&t.context!==``,p=t.lngs?t.lngs:this.languageUtils.toResolveHierarchy(t.lng||this.language,t.fallbackLng);l.forEach(e=>{this.isValidLookup(n)||(o=e,!se[`${p[0]}-${e}`]&&this.utils?.hasLoadedNamespace&&!this.utils?.hasLoadedNamespace(o)&&(se[`${p[0]}-${e}`]=!0,this.logger.warn(`key "${r}" for languages "${p.join(`, `)}" won't get resolved as namespace "${o}" was not yet loaded`,`This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!`)),p.forEach(r=>{if(this.isValidLookup(n))return;a=r;let o=[c];if(this.i18nFormat?.addLookupKeys)this.i18nFormat.addLookupKeys(o,c,r,e,t);else{let e;u&&(e=this.pluralResolver.getSuffix(r,t.count,t));let n=`${this.options.pluralSeparator}zero`,i=`${this.options.pluralSeparator}ordinal${this.options.pluralSeparator}`;if(u&&(t.ordinal&&e.indexOf(i)===0&&o.push(c+e.replace(i,this.options.pluralSeparator)),o.push(c+e),d&&o.push(c+n)),f){let r=`${c}${this.options.contextSeparator||`_`}${t.context}`;o.push(r),u&&(t.ordinal&&e.indexOf(i)===0&&o.push(r+e.replace(i,this.options.pluralSeparator)),o.push(r+e),d&&o.push(r+n))}}let s;for(;s=o.pop();)this.isValidLookup(n)||(i=s,n=this.getResource(r,e,s,t))}))})}),{res:n,usedKey:r,exactUsedKey:i,usedLng:a,usedNS:o}}isValidLookup(e){return e!==void 0&&!(!this.options.returnNull&&e===null)&&!(!this.options.returnEmptyString&&e===``)}getResource(e,t,n,r={}){return this.i18nFormat?.getResource?this.i18nFormat.getResource(e,t,n,r):this.resourceStore.getResource(e,t,n,r)}getUsedParamsDetails(e={}){let t=[`defaultValue`,`ordinal`,`context`,`replace`,`lng`,`lngs`,`fallbackLng`,`ns`,`keySeparator`,`nsSeparator`,`returnObjects`,`returnDetails`,`joinArrays`,`postProcess`,`interpolation`],n=e.replace&&!x(e.replace),r=n?e.replace:e;if(n&&e.count!==void 0&&(r.count=e.count),this.options.interpolation.defaultVariables&&(r={...this.options.interpolation.defaultVariables,...r}),!n){r={...r};for(let e of t)delete r[e]}return r}static hasDefaultValue(e){for(let t in e)if(Object.prototype.hasOwnProperty.call(e,t)&&t.substring(0,12)===`defaultValue`&&e[t]!==void 0)return!0;return!1}},ue=class{constructor(e){this.options=e,this.supportedLngs=this.options.supportedLngs||!1,this.logger=ne.create(`languageUtils`)}getScriptPartFromCode(e){if(e=ee(e),!e||e.indexOf(`-`)<0)return null;let t=e.split(`-`);return t.length===2||(t.pop(),t[t.length-1].toLowerCase()===`x`)?null:this.formatLanguageCode(t.join(`-`))}getLanguagePartFromCode(e){if(e=ee(e),!e||e.indexOf(`-`)<0)return e;let t=e.split(`-`);return this.formatLanguageCode(t[0])}formatLanguageCode(e){if(x(e)&&e.indexOf(`-`)>-1){let t;try{t=Intl.getCanonicalLocales(e)[0]}catch{}return t&&this.options.lowerCaseLng&&(t=t.toLowerCase()),t||(this.options.lowerCaseLng?e.toLowerCase():e)}return this.options.cleanCode||this.options.lowerCaseLng?e.toLowerCase():e}isSupportedCode(e){return(this.options.load===`languageOnly`||this.options.nonExplicitSupportedLngs)&&(e=this.getLanguagePartFromCode(e)),!this.supportedLngs||!this.supportedLngs.length||this.supportedLngs.indexOf(e)>-1}getBestMatchFromCodes(e){if(!e)return null;let t;return e.forEach(e=>{if(t)return;let n=this.formatLanguageCode(e);(!this.options.supportedLngs||this.isSupportedCode(n))&&(t=n)}),!t&&this.options.supportedLngs&&e.forEach(e=>{if(t)return;let n=this.getScriptPartFromCode(e);if(this.isSupportedCode(n))return t=n;let r=this.getLanguagePartFromCode(e);if(this.isSupportedCode(r))return t=r;t=this.options.supportedLngs.find(e=>{if(e===r||!(e.indexOf(`-`)<0&&r.indexOf(`-`)<0)&&(e.indexOf(`-`)>0&&r.indexOf(`-`)<0&&e.substring(0,e.indexOf(`-`))===r||e.indexOf(r)===0&&r.length>1))return e})}),t||=this.getFallbackCodes(this.options.fallbackLng)[0],t}getFallbackCodes(e,t){if(!e)return[];if(typeof e==`function`&&(e=e(t)),x(e)&&(e=[e]),Array.isArray(e))return e;if(!t)return e.default||[];let n=e[t];return n||=e[this.getScriptPartFromCode(t)],n||=e[this.formatLanguageCode(t)],n||=e[this.getLanguagePartFromCode(t)],n||=e.default,n||[]}toResolveHierarchy(e,t){let n=this.getFallbackCodes((t===!1?[]:t)||this.options.fallbackLng||[],e),r=[],i=e=>{e&&(this.isSupportedCode(e)?r.push(e):this.logger.warn(`rejecting language code not found in supportedLngs: ${e}`))};return x(e)&&(e.indexOf(`-`)>-1||e.indexOf(`_`)>-1)?(this.options.load!==`languageOnly`&&i(this.formatLanguageCode(e)),this.options.load!==`languageOnly`&&this.options.load!==`currentOnly`&&i(this.getScriptPartFromCode(e)),this.options.load!==`currentOnly`&&i(this.getLanguagePartFromCode(e))):x(e)&&i(this.formatLanguageCode(e)),n.forEach(e=>{r.indexOf(e)<0&&i(this.formatLanguageCode(e))}),r}},de={zero:0,one:1,two:2,few:3,many:4,other:5},fe={select:e=>e===1?`one`:`other`,resolvedOptions:()=>({pluralCategories:[`one`,`other`]})},pe=class{constructor(e,t={}){this.languageUtils=e,this.options=t,this.logger=ne.create(`pluralResolver`),this.pluralRulesCache={}}addRule(e,t){this.rules[e]=t}clearCache(){this.pluralRulesCache={}}getRule(e,t={}){let n=ee(e===`dev`?`en`:e),r=t.ordinal?`ordinal`:`cardinal`,i=JSON.stringify({cleanedCode:n,type:r});if(i in this.pluralRulesCache)return this.pluralRulesCache[i];let a;try{a=new Intl.PluralRules(n,{type:r})}catch{if(!Intl)return this.logger.error(`No Intl support, please use an Intl polyfill!`),fe;if(!e.match(/-|_/))return fe;let n=this.languageUtils.getLanguagePartFromCode(e);a=this.getRule(n,t)}return this.pluralRulesCache[i]=a,a}needsPlural(e,t={}){let n=this.getRule(e,t);return n||=this.getRule(`dev`,t),n?.resolvedOptions().pluralCategories.length>1}getPluralFormsOfKey(e,t,n={}){return this.getSuffixes(e,n).map(e=>`${t}${e}`)}getSuffixes(e,t={}){let n=this.getRule(e,t);return n||=this.getRule(`dev`,t),n?n.resolvedOptions().pluralCategories.sort((e,t)=>de[e]-de[t]).map(e=>`${this.options.prepend}${t.ordinal?`ordinal${this.options.prepend}`:``}${e}`):[]}getSuffix(e,t,n={}){let r=this.getRule(e,n);return r?`${this.options.prepend}${n.ordinal?`ordinal${this.options.prepend}`:``}${r.select(t)}`:(this.logger.warn(`no plural rule found for: ${e}`),this.getSuffix(`dev`,t,n))}},me=(e,t,n,r=`.`,i=!0)=>{let a=M(e,t,n);return!a&&i&&x(n)&&(a=V(e,n,r),a===void 0&&(a=V(t,n,r))),a},he=e=>e.replace(/\$/g,`$$$$`),ge=class{constructor(e={}){this.logger=ne.create(`interpolator`),this.options=e,this.format=e?.interpolation?.format||(e=>e),this.init(e)}init(e={}){e.interpolation||={escapeValue:!0};let{escape:t,escapeValue:n,useRawValueToEscape:r,prefix:i,prefixEscaped:a,suffix:o,suffixEscaped:s,formatSeparator:c,unescapeSuffix:l,unescapePrefix:u,nestingPrefix:d,nestingPrefixEscaped:f,nestingSuffix:p,nestingSuffixEscaped:m,nestingOptionsSeparator:h,maxReplaces:g,alwaysFormat:_}=e.interpolation;this.escape=t===void 0?I:t,this.escapeValue=n===void 0?!0:n,this.useRawValueToEscape=r===void 0?!1:r,this.prefix=i?P(i):a||`{{`,this.suffix=o?P(o):s||`}}`,this.formatSeparator=c||`,`,this.unescapePrefix=l?``:u||`-`,this.unescapeSuffix=this.unescapePrefix?``:l||``,this.nestingPrefix=d?P(d):f||P(`$t(`),this.nestingSuffix=p?P(p):m||P(`)`),this.nestingOptionsSeparator=h||`,`,this.maxReplaces=g||1e3,this.alwaysFormat=_===void 0?!1:_,this.resetRegExp()}reset(){this.options&&this.init(this.options)}resetRegExp(){let e=(e,t)=>e?.source===t?(e.lastIndex=0,e):new RegExp(t,`g`);this.regexp=e(this.regexp,`${this.prefix}(.+?)${this.suffix}`),this.regexpUnescape=e(this.regexpUnescape,`${this.prefix}${this.unescapePrefix}(.+?)${this.unescapeSuffix}${this.suffix}`),this.nestingRegexp=e(this.nestingRegexp,`${this.nestingPrefix}((?:[^()"']+|"[^"]*"|'[^']*'|\\((?:[^()]|"[^"]*"|'[^']*')*\\))*?)${this.nestingSuffix}`)}interpolate(e,t,n,r){let i,a,o,s=this.options&&this.options.interpolation&&this.options.interpolation.defaultVariables||{},c=e=>{if(e.indexOf(this.formatSeparator)<0){let i=me(t,s,e,this.options.keySeparator,this.options.ignoreJSONStructure);return this.alwaysFormat?this.format(i,void 0,n,{...r,...t,interpolationkey:e}):i}let i=e.split(this.formatSeparator),a=i.shift().trim(),o=i.join(this.formatSeparator).trim();return this.format(me(t,s,a,this.options.keySeparator,this.options.ignoreJSONStructure),o,n,{...r,...t,interpolationkey:a})};this.resetRegExp();let l=r?.missingInterpolationHandler||this.options.missingInterpolationHandler,u=r?.interpolation?.skipOnVariables===void 0?this.options.interpolation.skipOnVariables:r.interpolation.skipOnVariables;return[{regex:this.regexpUnescape,safeValue:e=>he(e)},{regex:this.regexp,safeValue:e=>this.escapeValue?he(this.escape(e)):he(e)}].forEach(t=>{for(o=0;i=t.regex.exec(e);){let n=i[1].trim();if(a=c(n),a===void 0)if(typeof l==`function`){let t=l(e,i,r);a=x(t)?t:``}else if(r&&Object.prototype.hasOwnProperty.call(r,n))a=``;else if(u){a=i[0];continue}else this.logger.warn(`missed to pass in variable ${n} for interpolating ${e}`),a=``;else !x(a)&&!this.useRawValueToEscape&&(a=C(a));let s=t.safeValue(a);if(e=e.replace(i[0],s),u?(t.regex.lastIndex+=a.length,t.regex.lastIndex-=i[0].length):t.regex.lastIndex=0,o++,o>=this.maxReplaces)break}}),e}nest(e,t,n={}){let r,i,a,o=(e,t)=>{let n=this.nestingOptionsSeparator;if(e.indexOf(n)<0)return e;let r=e.split(RegExp(`${n}[ ]*{`)),i=`{${r[1]}`;e=r[0],i=this.interpolate(i,a);let o=i.match(/'/g),s=i.match(/"/g);((o?.length??0)%2==0&&!s||s.length%2!=0)&&(i=i.replace(/'/g,`"`));try{a=JSON.parse(i),t&&(a={...t,...a})}catch(t){return this.logger.warn(`failed parsing options string in nesting for key ${e}`,t),`${e}${n}${i}`}return a.defaultValue&&a.defaultValue.indexOf(this.prefix)>-1&&delete a.defaultValue,e};for(;r=this.nestingRegexp.exec(e);){let s=[];a={...n},a=a.replace&&!x(a.replace)?a.replace:a,a.applyPostProcessor=!1,delete a.defaultValue;let c=/{.*}/.test(r[1])?r[1].lastIndexOf(`}`)+1:r[1].indexOf(this.formatSeparator);if(c!==-1&&(s=r[1].slice(c).split(this.formatSeparator).map(e=>e.trim()).filter(Boolean),r[1]=r[1].slice(0,c)),i=t(o.call(this,r[1].trim(),a),a),i&&r[0]===e&&!x(i))return i;x(i)||(i=C(i)),i||=(this.logger.warn(`missed to resolve ${r[1]} for nesting ${e}`),``),s.length&&(i=s.reduce((e,t)=>this.format(e,t,n.lng,{...n,interpolationkey:r[1].trim()}),i.trim())),e=e.replace(r[0],i),this.regexp.lastIndex=0}return e}},_e=e=>{let t=e.toLowerCase().trim(),n={};if(e.indexOf(`(`)>-1){let r=e.split(`(`);t=r[0].toLowerCase().trim();let i=r[1].substring(0,r[1].length-1);t===`currency`&&i.indexOf(`:`)<0?n.currency||=i.trim():t===`relativetime`&&i.indexOf(`:`)<0?n.range||=i.trim():i.split(`;`).forEach(e=>{if(e){let[t,...r]=e.split(`:`),i=r.join(`:`).trim().replace(/^'+|'+$/g,``),a=t.trim();n[a]||(n[a]=i),i===`false`&&(n[a]=!1),i===`true`&&(n[a]=!0),isNaN(i)||(n[a]=parseInt(i,10))}})}return{formatName:t,formatOptions:n}},ve=e=>{let t={};return(n,r,i)=>{let a=i;i&&i.interpolationkey&&i.formatParams&&i.formatParams[i.interpolationkey]&&i[i.interpolationkey]&&(a={...a,[i.interpolationkey]:void 0});let o=r+JSON.stringify(a),s=t[o];return s||(s=e(ee(r),i),t[o]=s),s(n)}},ye=e=>(t,n,r)=>e(ee(n),r)(t),be=class{constructor(e={}){this.logger=ne.create(`formatter`),this.options=e,this.init(e)}init(e,t={interpolation:{}}){this.formatSeparator=t.interpolation.formatSeparator||`,`;let n=t.cacheInBuiltFormats?ve:ye;this.formats={number:n((e,t)=>{let n=new Intl.NumberFormat(e,{...t});return e=>n.format(e)}),currency:n((e,t)=>{let n=new Intl.NumberFormat(e,{...t,style:`currency`});return e=>n.format(e)}),datetime:n((e,t)=>{let n=new Intl.DateTimeFormat(e,{...t});return e=>n.format(e)}),relativetime:n((e,t)=>{let n=new Intl.RelativeTimeFormat(e,{...t});return e=>n.format(e,t.range||`day`)}),list:n((e,t)=>{let n=new Intl.ListFormat(e,{...t});return e=>n.format(e)})}}add(e,t){this.formats[e.toLowerCase().trim()]=t}addCached(e,t){this.formats[e.toLowerCase().trim()]=ve(t)}format(e,t,n,r={}){let i=t.split(this.formatSeparator);if(i.length>1&&i[0].indexOf(`(`)>1&&i[0].indexOf(`)`)<0&&i.find(e=>e.indexOf(`)`)>-1)){let e=i.findIndex(e=>e.indexOf(`)`)>-1);i[0]=[i[0],...i.splice(1,e)].join(this.formatSeparator)}return i.reduce((e,t)=>{let{formatName:i,formatOptions:a}=_e(t);if(this.formats[i]){let t=e;try{let o=r?.formatParams?.[r.interpolationkey]||{},s=o.locale||o.lng||r.locale||r.lng||n;t=this.formats[i](e,s,{...a,...r,...o})}catch(e){this.logger.warn(e)}return t}else this.logger.warn(`there was no format function for ${i}`);return e},e)}},xe=(e,t)=>{e.pending[t]!==void 0&&(delete e.pending[t],e.pendingCount--)},Se=class extends re{constructor(e,t,n,r={}){super(),this.backend=e,this.store=t,this.services=n,this.languageUtils=n.languageUtils,this.options=r,this.logger=ne.create(`backendConnector`),this.waitingReads=[],this.maxParallelReads=r.maxParallelReads||10,this.readingCalls=0,this.maxRetries=r.maxRetries>=0?r.maxRetries:5,this.retryTimeout=r.retryTimeout>=1?r.retryTimeout:350,this.state={},this.queue=[],this.backend?.init?.(n,r.backend,r)}queueLoad(e,t,n,r){let i={},a={},o={},s={};return e.forEach(e=>{let r=!0;t.forEach(t=>{let o=`${e}|${t}`;!n.reload&&this.store.hasResourceBundle(e,t)?this.state[o]=2:this.state[o]<0||(this.state[o]===1?a[o]===void 0&&(a[o]=!0):(this.state[o]=1,r=!1,a[o]===void 0&&(a[o]=!0),i[o]===void 0&&(i[o]=!0),s[t]===void 0&&(s[t]=!0)))}),r||(o[e]=!0)}),(Object.keys(i).length||Object.keys(a).length)&&this.queue.push({pending:a,pendingCount:Object.keys(a).length,loaded:{},errors:[],callback:r}),{toLoad:Object.keys(i),pending:Object.keys(a),toLoadLanguages:Object.keys(o),toLoadNamespaces:Object.keys(s)}}loaded(e,t,n){let r=e.split(`|`),i=r[0],a=r[1];t&&this.emit(`failedLoading`,i,a,t),!t&&n&&this.store.addResourceBundle(i,a,n,void 0,void 0,{skipCopy:!0}),this.state[e]=t?-1:2,t&&n&&(this.state[e]=0);let o={};this.queue.forEach(n=>{A(n.loaded,[i],a),xe(n,e),t&&n.errors.push(t),n.pendingCount===0&&!n.done&&(Object.keys(n.loaded).forEach(e=>{o[e]||(o[e]={});let t=n.loaded[e];t.length&&t.forEach(t=>{o[e][t]===void 0&&(o[e][t]=!0)})}),n.done=!0,n.errors.length?n.callback(n.errors):n.callback())}),this.emit(`loaded`,o),this.queue=this.queue.filter(e=>!e.done)}read(e,t,n,r=0,i=this.retryTimeout,a){if(!e.length)return a(null,{});if(this.readingCalls>=this.maxParallelReads){this.waitingReads.push({lng:e,ns:t,fcName:n,tried:r,wait:i,callback:a});return}this.readingCalls++;let o=(o,s)=>{if(this.readingCalls--,this.waitingReads.length>0){let e=this.waitingReads.shift();this.read(e.lng,e.ns,e.fcName,e.tried,e.wait,e.callback)}if(o&&s&&r{this.read.call(this,e,t,n,r+1,i*2,a)},i);return}a(o,s)},s=this.backend[n].bind(this.backend);if(s.length===2){try{let n=s(e,t);n&&typeof n.then==`function`?n.then(e=>o(null,e)).catch(o):o(null,n)}catch(e){o(e)}return}return s(e,t,o)}prepareLoading(e,t,n={},r){if(!this.backend)return this.logger.warn(`No backend was added via i18next.use. Will not load resources.`),r&&r();x(e)&&(e=this.languageUtils.toResolveHierarchy(e)),x(t)&&(t=[t]);let i=this.queueLoad(e,t,n,r);if(!i.toLoad.length)return i.pending.length||r(),null;i.toLoad.forEach(e=>{this.loadOne(e)})}load(e,t,n){this.prepareLoading(e,t,{},n)}reload(e,t,n){this.prepareLoading(e,t,{reload:!0},n)}loadOne(e,t=``){let n=e.split(`|`),r=n[0],i=n[1];this.read(r,i,`read`,void 0,void 0,(n,a)=>{n&&this.logger.warn(`${t}loading namespace ${i} for language ${r} failed`,n),!n&&a&&this.logger.log(`${t}loaded namespace ${i} for language ${r}`,a),this.loaded(e,n,a)})}saveMissing(e,t,n,r,i,a={},o=()=>{}){if(this.services?.utils?.hasLoadedNamespace&&!this.services?.utils?.hasLoadedNamespace(t)){this.logger.warn(`did not save key "${n}" as the namespace "${t}" was not yet loaded`,`This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!`);return}if(!(n==null||n===``)){if(this.backend?.create){let s={...a,isUpdate:i},c=this.backend.create.bind(this.backend);if(c.length<6)try{let i;i=c.length===5?c(e,t,n,r,s):c(e,t,n,r),i&&typeof i.then==`function`?i.then(e=>o(null,e)).catch(o):o(null,i)}catch(e){o(e)}else c(e,t,n,r,o,s)}!e||!e[0]||this.store.addResource(e[0],t,n,r)}}},Ce=()=>({debug:!1,initAsync:!0,ns:[`translation`],defaultNS:[`translation`],fallbackLng:[`dev`],fallbackNS:!1,supportedLngs:!1,nonExplicitSupportedLngs:!1,load:`all`,preload:!1,simplifyPluralSuffix:!0,keySeparator:`.`,nsSeparator:`:`,pluralSeparator:`_`,contextSeparator:`_`,partialBundledLanguages:!1,saveMissing:!1,updateMissing:!1,saveMissingTo:`fallback`,saveMissingPlurals:!0,missingKeyHandler:!1,missingInterpolationHandler:!1,postProcess:!1,postProcessPassResolved:!1,returnNull:!1,returnEmptyString:!0,returnObjects:!1,joinArrays:!1,returnedObjectHandler:!1,parseMissingKeyHandler:!1,appendNamespaceToMissingKey:!1,appendNamespaceToCIMode:!1,overloadTranslationOptionHandler:e=>{let t={};if(typeof e[1]==`object`&&(t=e[1]),x(e[1])&&(t.defaultValue=e[1]),x(e[2])&&(t.tDescription=e[2]),typeof e[2]==`object`||typeof e[3]==`object`){let n=e[3]||e[2];Object.keys(n).forEach(e=>{t[e]=n[e]})}return t},interpolation:{escapeValue:!0,format:e=>e,prefix:`{{`,suffix:`}}`,formatSeparator:`,`,unescapePrefix:`-`,nestingPrefix:`$t(`,nestingSuffix:`)`,nestingOptionsSeparator:`,`,maxReplaces:1e3,skipOnVariables:!0},cacheInBuiltFormats:!0}),we=e=>(x(e.ns)&&(e.ns=[e.ns]),x(e.fallbackLng)&&(e.fallbackLng=[e.fallbackLng]),x(e.fallbackNS)&&(e.fallbackNS=[e.fallbackNS]),e.supportedLngs?.indexOf?.(`cimode`)<0&&(e.supportedLngs=e.supportedLngs.concat([`cimode`])),typeof e.initImmediate==`boolean`&&(e.initAsync=e.initImmediate),e),Te=()=>{},Ee=e=>{Object.getOwnPropertyNames(Object.getPrototypeOf(e)).forEach(t=>{typeof e[t]==`function`&&(e[t]=e[t].bind(e))})},De=class e extends re{constructor(e={},t){if(super(),this.options=we(e),this.services={},this.logger=ne,this.modules={external:[]},Ee(this),t&&!this.isInitialized&&!e.isClone){if(!this.options.initAsync)return this.init(e,t),this;setTimeout(()=>{this.init(e,t)},0)}}init(e={},t){this.isInitializing=!0,typeof e==`function`&&(t=e,e={}),e.defaultNS==null&&e.ns&&(x(e.ns)?e.defaultNS=e.ns:e.ns.indexOf(`translation`)<0&&(e.defaultNS=e.ns[0]));let n=Ce();this.options={...n,...this.options,...we(e)},this.options.interpolation={...n.interpolation,...this.options.interpolation},e.keySeparator!==void 0&&(this.options.userDefinedKeySeparator=e.keySeparator),e.nsSeparator!==void 0&&(this.options.userDefinedNsSeparator=e.nsSeparator);let r=e=>e?typeof e==`function`?new e:e:null;if(!this.options.isClone){this.modules.logger?ne.init(r(this.modules.logger),this.options):ne.init(null,this.options);let e;e=this.modules.formatter?this.modules.formatter:be;let t=new ue(this.options);this.store=new ie(this.options.resources,this.options);let i=this.services;i.logger=ne,i.resourceStore=this.store,i.languageUtils=t,i.pluralResolver=new pe(t,{prepend:this.options.pluralSeparator,simplifyPluralSuffix:this.options.simplifyPluralSuffix}),this.options.interpolation.format&&this.options.interpolation.format!==n.interpolation.format&&this.logger.deprecate(`init: you are still using the legacy format function, please use the new approach: https://www.i18next.com/translation-function/formatting`),e&&(!this.options.interpolation.format||this.options.interpolation.format===n.interpolation.format)&&(i.formatter=r(e),i.formatter.init&&i.formatter.init(i,this.options),this.options.interpolation.format=i.formatter.format.bind(i.formatter)),i.interpolator=new ge(this.options),i.utils={hasLoadedNamespace:this.hasLoadedNamespace.bind(this)},i.backendConnector=new Se(r(this.modules.backend),i.resourceStore,i,this.options),i.backendConnector.on(`*`,(e,...t)=>{this.emit(e,...t)}),this.modules.languageDetector&&(i.languageDetector=r(this.modules.languageDetector),i.languageDetector.init&&i.languageDetector.init(i,this.options.detection,this.options)),this.modules.i18nFormat&&(i.i18nFormat=r(this.modules.i18nFormat),i.i18nFormat.init&&i.i18nFormat.init(this)),this.translator=new le(this.services,this.options),this.translator.on(`*`,(e,...t)=>{this.emit(e,...t)}),this.modules.external.forEach(e=>{e.init&&e.init(this)})}if(this.format=this.options.interpolation.format,t||=Te,this.options.fallbackLng&&!this.services.languageDetector&&!this.options.lng){let e=this.services.languageUtils.getFallbackCodes(this.options.fallbackLng);e.length>0&&e[0]!==`dev`&&(this.options.lng=e[0])}!this.services.languageDetector&&!this.options.lng&&this.logger.warn(`init: no languageDetector is used and no lng is defined`),[`getResource`,`hasResourceBundle`,`getResourceBundle`,`getDataByLanguage`].forEach(e=>{this[e]=(...t)=>this.store[e](...t)}),[`addResource`,`addResources`,`addResourceBundle`,`removeResourceBundle`].forEach(e=>{this[e]=(...t)=>(this.store[e](...t),this)});let i=S(),a=()=>{let e=(e,n)=>{this.isInitializing=!1,this.isInitialized&&!this.initializedStoreOnce&&this.logger.warn(`init: i18next is already initialized. You should call init just once!`),this.isInitialized=!0,this.options.isClone||this.logger.log(`initialized`,this.options),this.emit(`initialized`,this.options),i.resolve(n),t(e,n)};if(this.languages&&!this.isInitialized)return e(null,this.t.bind(this));this.changeLanguage(this.options.lng,e)};return this.options.resources||!this.options.initAsync?a():setTimeout(a,0),i}loadResources(e,t=Te){let n=t,r=x(e)?e:this.language;if(typeof e==`function`&&(n=e),!this.options.resources||this.options.partialBundledLanguages){if(r?.toLowerCase()===`cimode`&&(!this.options.preload||this.options.preload.length===0))return n();let e=[],t=t=>{t&&t!==`cimode`&&this.services.languageUtils.toResolveHierarchy(t).forEach(t=>{t!==`cimode`&&e.indexOf(t)<0&&e.push(t)})};r?t(r):this.services.languageUtils.getFallbackCodes(this.options.fallbackLng).forEach(e=>t(e)),this.options.preload?.forEach?.(e=>t(e)),this.services.backendConnector.load(e,this.options.ns,e=>{!e&&!this.resolvedLanguage&&this.language&&this.setResolvedLanguage(this.language),n(e)})}else n(null)}reloadResources(e,t,n){let r=S();return typeof e==`function`&&(n=e,e=void 0),typeof t==`function`&&(n=t,t=void 0),e||=this.languages,t||=this.options.ns,n||=Te,this.services.backendConnector.reload(e,t,e=>{r.resolve(),n(e)}),r}use(e){if(!e)throw Error(`You are passing an undefined module! Please check the object you are passing to i18next.use()`);if(!e.type)throw Error(`You are passing a wrong module! Please check the object you are passing to i18next.use()`);return e.type===`backend`&&(this.modules.backend=e),(e.type===`logger`||e.log&&e.warn&&e.error)&&(this.modules.logger=e),e.type===`languageDetector`&&(this.modules.languageDetector=e),e.type===`i18nFormat`&&(this.modules.i18nFormat=e),e.type===`postProcessor`&&H.addPostProcessor(e),e.type===`formatter`&&(this.modules.formatter=e),e.type===`3rdParty`&&this.modules.external.push(e),this}setResolvedLanguage(e){if(!(!e||!this.languages)&&!([`cimode`,`dev`].indexOf(e)>-1)){for(let e=0;e-1)&&this.store.hasLanguageSomeTranslations(t)){this.resolvedLanguage=t;break}}!this.resolvedLanguage&&this.languages.indexOf(e)<0&&this.store.hasLanguageSomeTranslations(e)&&(this.resolvedLanguage=e,this.languages.unshift(e))}}changeLanguage(e,t){this.isLanguageChangingTo=e;let n=S();this.emit(`languageChanging`,e);let r=e=>{this.language=e,this.languages=this.services.languageUtils.toResolveHierarchy(e),this.resolvedLanguage=void 0,this.setResolvedLanguage(e)},i=(i,a)=>{a?this.isLanguageChangingTo===e&&(r(a),this.translator.changeLanguage(a),this.isLanguageChangingTo=void 0,this.emit(`languageChanged`,a),this.logger.log(`languageChanged`,a)):this.isLanguageChangingTo=void 0,n.resolve((...e)=>this.t(...e)),t&&t(i,(...e)=>this.t(...e))},a=t=>{!e&&!t&&this.services.languageDetector&&(t=[]);let n=x(t)?t:t&&t[0],a=this.store.hasLanguageSomeTranslations(n)?n:this.services.languageUtils.getBestMatchFromCodes(x(t)?[t]:t);a&&(this.language||r(a),this.translator.language||this.translator.changeLanguage(a),this.services.languageDetector?.cacheUserLanguage?.(a)),this.loadResources(a,e=>{i(e,a)})};return!e&&this.services.languageDetector&&!this.services.languageDetector.async?a(this.services.languageDetector.detect()):!e&&this.services.languageDetector&&this.services.languageDetector.async?this.services.languageDetector.detect.length===0?this.services.languageDetector.detect().then(a):this.services.languageDetector.detect(a):a(e),n}getFixedT(e,t,n){let r=(e,t,...i)=>{let a;a=typeof t==`object`?{...t}:this.options.overloadTranslationOptionHandler([e,t].concat(i)),a.lng=a.lng||r.lng,a.lngs=a.lngs||r.lngs,a.ns=a.ns||r.ns,a.keyPrefix!==``&&(a.keyPrefix=a.keyPrefix||n||r.keyPrefix);let o=this.options.keySeparator||`.`,s;return a.keyPrefix&&Array.isArray(e)?s=e.map(e=>(typeof e==`function`&&(e=U(e,{...this.options,...t})),`${a.keyPrefix}${o}${e}`)):(typeof e==`function`&&(e=U(e,{...this.options,...t})),s=a.keyPrefix?`${a.keyPrefix}${o}${e}`:e),this.t(s,a)};return x(e)?r.lng=e:r.lngs=e,r.ns=t,r.keyPrefix=n,r}t(...e){return this.translator?.translate(...e)}exists(...e){return this.translator?.exists(...e)}setDefaultNamespace(e){this.options.defaultNS=e}hasLoadedNamespace(e,t={}){if(!this.isInitialized)return this.logger.warn(`hasLoadedNamespace: i18next was not initialized`,this.languages),!1;if(!this.languages||!this.languages.length)return this.logger.warn(`hasLoadedNamespace: i18n.languages were undefined or empty`,this.languages),!1;let n=t.lng||this.resolvedLanguage||this.languages[0],r=this.options?this.options.fallbackLng:!1,i=this.languages[this.languages.length-1];if(n.toLowerCase()===`cimode`)return!0;let a=(e,t)=>{let n=this.services.backendConnector.state[`${e}|${t}`];return n===-1||n===0||n===2};if(t.precheck){let e=t.precheck(this,a);if(e!==void 0)return e}return!!(this.hasResourceBundle(n,e)||!this.services.backendConnector.backend||this.options.resources&&!this.options.partialBundledLanguages||a(n,e)&&(!r||a(i,e)))}loadNamespaces(e,t){let n=S();return this.options.ns?(x(e)&&(e=[e]),e.forEach(e=>{this.options.ns.indexOf(e)<0&&this.options.ns.push(e)}),this.loadResources(e=>{n.resolve(),t&&t(e)}),n):(t&&t(),Promise.resolve())}loadLanguages(e,t){let n=S();x(e)&&(e=[e]);let r=this.options.preload||[],i=e.filter(e=>r.indexOf(e)<0&&this.services.languageUtils.isSupportedCode(e));return i.length?(this.options.preload=r.concat(i),this.loadResources(e=>{n.resolve(),t&&t(e)}),n):(t&&t(),Promise.resolve())}dir(e){if(e||=this.resolvedLanguage||(this.languages?.length>0?this.languages[0]:this.language),!e)return`rtl`;try{let t=new Intl.Locale(e);if(t&&t.getTextInfo){let e=t.getTextInfo();if(e&&e.direction)return e.direction}}catch{}let t=`ar.shu.sqr.ssh.xaa.yhd.yud.aao.abh.abv.acm.acq.acw.acx.acy.adf.ads.aeb.aec.afb.ajp.apc.apd.arb.arq.ars.ary.arz.auz.avl.ayh.ayl.ayn.ayp.bbz.pga.he.iw.ps.pbt.pbu.pst.prp.prd.ug.ur.ydd.yds.yih.ji.yi.hbo.men.xmn.fa.jpr.peo.pes.prs.dv.sam.ckb`.split(`.`),n=this.services?.languageUtils||new ue(Ce());return e.toLowerCase().indexOf(`-latn`)>1?`ltr`:t.indexOf(n.getLanguagePartFromCode(e))>-1||e.toLowerCase().indexOf(`-arab`)>1?`rtl`:`ltr`}static createInstance(t={},n){let r=new e(t,n);return r.createInstance=e.createInstance,r}cloneInstance(t={},n=Te){let r=t.forkResourceStore;r&&delete t.forkResourceStore;let i={...this.options,...t,isClone:!0},a=new e(i);return(t.debug!==void 0||t.prefix!==void 0)&&(a.logger=a.logger.clone(t)),[`store`,`services`,`language`].forEach(e=>{a[e]=this[e]}),a.services={...this.services},a.services.utils={hasLoadedNamespace:a.hasLoadedNamespace.bind(a)},r&&(a.store=new ie(Object.keys(this.store.data).reduce((e,t)=>(e[t]={...this.store.data[t]},e[t]=Object.keys(e[t]).reduce((n,r)=>(n[r]={...e[t][r]},n),e[t]),e),{}),i),a.services.resourceStore=a.store),a.translator=new le(a.services,i),a.translator.on(`*`,(e,...t)=>{a.emit(e,...t)}),a.init(i,n),a.translator.options=i,a.translator.backendConnector.services.utils={hasLoadedNamespace:a.hasLoadedNamespace.bind(a)},a}toJSON(){return{options:this.options,store:this.store,language:this.language,languages:this.languages,resolvedLanguage:this.resolvedLanguage}}}.createInstance();De.createInstance,De.dir,De.init,De.loadResources,De.reloadResources,De.use,De.changeLanguage,De.getFixedT,De.t,De.exists,De.setDefaultNamespace,De.hasLoadedNamespace,De.loadNamespaces,De.loadLanguages;var Oe=(e,t,n,r)=>{let i=[n,{code:t,...r||{}}];if(e?.services?.logger?.forward)return e.services.logger.forward(i,`warn`,`react-i18next::`,!0);Fe(i[0])&&(i[0]=`react-i18next:: ${i[0]}`),e?.services?.logger?.warn?e.services.logger.warn(...i):console?.warn&&console.warn(...i)},ke={},Ae=(e,t,n,r)=>{Fe(n)&&ke[n]||(Fe(n)&&(ke[n]=new Date),Oe(e,t,n,r))},je=(e,t)=>()=>{if(e.isInitialized)t();else{let n=()=>{setTimeout(()=>{e.off(`initialized`,n)},0),t()};e.on(`initialized`,n)}},Me=(e,t,n)=>{e.loadNamespaces(t,je(e,n))},Ne=(e,t,n,r)=>{if(Fe(n)&&(n=[n]),e.options.preload&&e.options.preload.indexOf(t)>-1)return Me(e,n,r);n.forEach(t=>{e.options.ns.indexOf(t)<0&&e.options.ns.push(t)}),e.loadLanguages(t,je(e,r))},Pe=(e,t,n={})=>!t.languages||!t.languages.length?(Ae(t,`NO_LANGUAGES`,`i18n.languages were undefined or empty`,{languages:t.languages}),!0):t.hasLoadedNamespace(e,{lng:n.lng,precheck:(t,r)=>{if(n.bindI18n&&n.bindI18n.indexOf(`languageChanging`)>-1&&t.services.backendConnector.backend&&t.isLanguageChangingTo&&!r(t.isLanguageChangingTo,e))return!1}}),Fe=e=>typeof e==`string`,Ie=e=>typeof e==`object`&&!!e,Le=/&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34|nbsp|#160|copy|#169|reg|#174|hellip|#8230|#x2F|#47);/g,Re={"&":`&`,"&":`&`,"<":`<`,"<":`<`,">":`>`,">":`>`,"'":`'`,"'":`'`,""":`"`,""":`"`," ":` `," ":` `,"©":`©`,"©":`©`,"®":`®`,"®":`®`,"…":`…`,"…":`…`,"/":`/`,"/":`/`},ze=e=>Re[e],Be={bindI18n:`languageChanged`,bindI18nStore:``,transEmptyNodeValue:``,transSupportBasicHtmlNodes:!0,transWrapTextNodes:``,transKeepBasicHtmlNodesFor:[`br`,`strong`,`i`,`p`],useSuspense:!0,unescape:e=>e.replace(Le,ze),transDefaultProps:void 0},Ve=(e={})=>{Be={...Be,...e}},He=()=>Be,Ue,We=e=>{Ue=e},Ge=()=>Ue,Ke={type:`3rdParty`,init(e){Ve(e.options.react),We(e)}},qe=(0,y.createContext)(),Je=class{constructor(){this.usedNamespaces={}}addUsedNamespaces(e){e.forEach(e=>{this.usedNamespaces[e]||(this.usedNamespaces[e]=!0)})}getUsedNamespaces(){return Object.keys(this.usedNamespaces)}},Ye=o((e=>{var t=f();function n(e,t){return e===t&&(e!==0||1/e==1/t)||e!==e&&t!==t}var r=typeof Object.is==`function`?Object.is:n,i=t.useState,a=t.useEffect,o=t.useLayoutEffect,s=t.useDebugValue;function c(e,t){var n=t(),r=i({inst:{value:n,getSnapshot:t}}),c=r[0].inst,u=r[1];return o(function(){c.value=n,c.getSnapshot=t,l(c)&&u({inst:c})},[e,n,t]),a(function(){return l(c)&&u({inst:c}),e(function(){l(c)&&u({inst:c})})},[e]),s(n),n}function l(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!r(e,n)}catch{return!0}}function u(e,t){return t()}var d=typeof window>`u`||window.document===void 0||window.document.createElement===void 0?u:c;e.useSyncExternalStore=t.useSyncExternalStore===void 0?d:t.useSyncExternalStore})),Xe=o(((e,t)=>{t.exports=Ye()})),Ze=Xe(),Qe={t:(e,t)=>Fe(t)?t:Ie(t)&&Fe(t.defaultValue)?t.defaultValue:Array.isArray(e)?e[e.length-1]:e,ready:!1},$e=()=>()=>{},W=(e,t={})=>{let{i18n:n}=t,{i18n:r,defaultNS:i}=(0,y.useContext)(qe)||{},a=n||r||Ge();a&&!a.reportNamespaces&&(a.reportNamespaces=new Je),a||Ae(a,`NO_I18NEXT_INSTANCE`,`useTranslation: You will need to pass in an i18next instance by using initReactI18next`);let o=(0,y.useMemo)(()=>({...He(),...a?.options?.react,...t}),[a,t]),{useSuspense:s,keyPrefix:c}=o,l=e||i||a?.options?.defaultNS,u=Fe(l)?[l]:l||[`translation`],d=(0,y.useMemo)(()=>u,u);a?.reportNamespaces?.addUsedNamespaces?.(d);let f=(0,y.useRef)(0),p=(0,y.useCallback)(e=>{if(!a)return $e;let{bindI18n:t,bindI18nStore:n}=o,r=()=>{f.current+=1,e()};return t&&a.on(t,r),n&&a.store.on(n,r),()=>{t&&t.split(` `).forEach(e=>a.off(e,r)),n&&n.split(` `).forEach(e=>a.store.off(e,r))}},[a,o]),m=(0,y.useRef)(),h=(0,y.useCallback)(()=>{if(!a)return Qe;let e=!!(a.isInitialized||a.initializedStoreOnce)&&d.every(e=>Pe(e,a,o)),n=t.lng||a.language,r=f.current,i=m.current;if(i&&i.ready===e&&i.lng===n&&i.keyPrefix===c&&i.revision===r)return i;let s={t:a.getFixedT(n,o.nsMode===`fallback`?d:d[0],c),ready:e,lng:n,keyPrefix:c,revision:r};return m.current=s,s},[a,d,c,o,t.lng]),[g,_]=(0,y.useState)(0),{t:v,ready:b}=(0,Ze.useSyncExternalStore)(p,h,h);(0,y.useEffect)(()=>{if(a&&!b&&!s){let e=()=>_(e=>e+1);t.lng?Ne(a,t.lng,d,e):Me(a,d,e)}},[a,t.lng,d,b,s,g]);let x=a||{},S=(0,y.useRef)(null),C=(0,y.useRef)(),w=e=>{let t=Object.getOwnPropertyDescriptors(e);t.__original&&delete t.__original;let n=Object.create(Object.getPrototypeOf(e),t);if(!Object.prototype.hasOwnProperty.call(n,`__original`))try{Object.defineProperty(n,"__original",{value:e,writable:!1,enumerable:!1,configurable:!1})}catch{}return n},T=(0,y.useMemo)(()=>{let e=x,t=e?.language,n=e;e&&(S.current&&S.current.__original===e&&C.current===t?n=S.current:(n=w(e),S.current=n,C.current=t));let r=[v,n,b];return r.t=v,r.i18n=n,r.ready=b,r},[v,x,b,x.resolvedLanguage,x.language,x.languages]);if(a&&s&&!b)throw new Promise(e=>{let n=()=>e();t.lng?Ne(a,t.lng,d,n):Me(a,d,n)});return T},{slice:et,forEach:tt}=[];function nt(e){return tt.call(et.call(arguments,1),t=>{if(t)for(let n in t)e[n]===void 0&&(e[n]=t[n])}),e}function rt(e){return typeof e==`string`?[/<\s*script.*?>/i,/<\s*\/\s*script\s*>/i,/<\s*img.*?on\w+\s*=/i,/<\s*\w+\s*on\w+\s*=.*?>/i,/javascript\s*:/i,/vbscript\s*:/i,/expression\s*\(/i,/eval\s*\(/i,/alert\s*\(/i,/document\.cookie/i,/document\.write\s*\(/i,/window\.location/i,/innerHTML/i].some(t=>t.test(e)):!1}var it=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/,at=function(e,t){let n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{path:`/`},r=`${e}=${encodeURIComponent(t)}`;if(n.maxAge>0){let e=n.maxAge-0;if(Number.isNaN(e))throw Error(`maxAge should be a Number`);r+=`; Max-Age=${Math.floor(e)}`}if(n.domain){if(!it.test(n.domain))throw TypeError(`option domain is invalid`);r+=`; Domain=${n.domain}`}if(n.path){if(!it.test(n.path))throw TypeError(`option path is invalid`);r+=`; Path=${n.path}`}if(n.expires){if(typeof n.expires.toUTCString!=`function`)throw TypeError(`option expires is invalid`);r+=`; Expires=${n.expires.toUTCString()}`}if(n.httpOnly&&(r+=`; HttpOnly`),n.secure&&(r+=`; Secure`),n.sameSite)switch(typeof n.sameSite==`string`?n.sameSite.toLowerCase():n.sameSite){case!0:r+=`; SameSite=Strict`;break;case`lax`:r+=`; SameSite=Lax`;break;case`strict`:r+=`; SameSite=Strict`;break;case`none`:r+=`; SameSite=None`;break;default:throw TypeError(`option sameSite is invalid`)}return n.partitioned&&(r+=`; Partitioned`),r},ot={create(e,t,n,r){let i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:{path:`/`,sameSite:`strict`};n&&(i.expires=new Date,i.expires.setTime(i.expires.getTime()+n*60*1e3)),r&&(i.domain=r),document.cookie=at(e,t,i)},read(e){let t=`${e}=`,n=document.cookie.split(`;`);for(let e=0;e-1&&(e=window.location.hash.substring(window.location.hash.indexOf(`?`)));let r=e.substring(1).split(`&`);for(let e=0;e0&&r[e].substring(0,i)===t&&(n=r[e].substring(i+1))}}return n}},lt={name:`hash`,lookup(e){let{lookupHash:t,lookupFromHashIndex:n}=e,r;if(typeof window<`u`){let{hash:e}=window.location;if(e&&e.length>2){let i=e.substring(1);if(t){let e=i.split(`&`);for(let n=0;n0&&e[n].substring(0,i)===t&&(r=e[n].substring(i+1))}}if(r)return r;if(!r&&n>-1){let t=e.match(/\/([a-zA-Z-]*)/g);return Array.isArray(t)?t[typeof n==`number`?n:0]?.replace(`/`,``):void 0}}}return r}},ut=null,dt=()=>{if(ut!==null)return ut;try{if(ut=typeof window<`u`&&window.localStorage!==null,!ut)return!1;let e=`i18next.translate.boo`;window.localStorage.setItem(e,`foo`),window.localStorage.removeItem(e)}catch{ut=!1}return ut},ft={name:`localStorage`,lookup(e){let{lookupLocalStorage:t}=e;if(t&&dt())return window.localStorage.getItem(t)||void 0},cacheUserLanguage(e,t){let{lookupLocalStorage:n}=t;n&&dt()&&window.localStorage.setItem(n,e)}},pt=null,mt=()=>{if(pt!==null)return pt;try{if(pt=typeof window<`u`&&window.sessionStorage!==null,!pt)return!1;let e=`i18next.translate.boo`;window.sessionStorage.setItem(e,`foo`),window.sessionStorage.removeItem(e)}catch{pt=!1}return pt},ht={name:`sessionStorage`,lookup(e){let{lookupSessionStorage:t}=e;if(t&&mt())return window.sessionStorage.getItem(t)||void 0},cacheUserLanguage(e,t){let{lookupSessionStorage:n}=t;n&&mt()&&window.sessionStorage.setItem(n,e)}},gt={name:`navigator`,lookup(e){let t=[];if(typeof navigator<`u`){let{languages:e,userLanguage:n,language:r}=navigator;if(e)for(let n=0;n0?t:void 0}},_t={name:`htmlTag`,lookup(e){let{htmlTag:t}=e,n,r=t||(typeof document<`u`?document.documentElement:null);return r&&typeof r.getAttribute==`function`&&(n=r.getAttribute(`lang`)),n}},vt={name:`path`,lookup(e){let{lookupFromPathIndex:t}=e;if(typeof window>`u`)return;let n=window.location.pathname.match(/\/([a-zA-Z-]*)/g);if(Array.isArray(n))return n[typeof t==`number`?t:0]?.replace(`/`,``)}},yt={name:`subdomain`,lookup(e){let{lookupFromSubdomainIndex:t}=e,n=typeof t==`number`?t+1:1,r=typeof window<`u`&&window.location?.hostname?.match(/^(\w{2,5})\.(([a-z0-9-]{1,63}\.[a-z]{2,6})|localhost)/i);if(r)return r[n]}},bt=!1;try{document.cookie,bt=!0}catch{}var xt=[`querystring`,`cookie`,`localStorage`,`sessionStorage`,`navigator`,`htmlTag`];bt||xt.splice(1,1);var St=()=>({order:xt,lookupQuerystring:`lng`,lookupCookie:`i18next`,lookupLocalStorage:`i18nextLng`,lookupSessionStorage:`i18nextLng`,caches:[`localStorage`],excludeCacheFor:[`cimode`],convertDetectedLanguage:e=>e}),Ct=class{constructor(e){let t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};this.type=`languageDetector`,this.detectors={},this.init(e,t)}init(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{languageUtils:{}},t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};this.services=e,this.options=nt(t,this.options||{},St()),typeof this.options.convertDetectedLanguage==`string`&&this.options.convertDetectedLanguage.indexOf(`15897`)>-1&&(this.options.convertDetectedLanguage=e=>e.replace(`-`,`_`)),this.options.lookupFromUrlIndex&&(this.options.lookupFromPathIndex=this.options.lookupFromUrlIndex),this.i18nOptions=n,this.addDetector(st),this.addDetector(ct),this.addDetector(ft),this.addDetector(ht),this.addDetector(gt),this.addDetector(_t),this.addDetector(vt),this.addDetector(yt),this.addDetector(lt)}addDetector(e){return this.detectors[e.name]=e,this}detect(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:this.options.order,t=[];return e.forEach(e=>{if(this.detectors[e]){let n=this.detectors[e].lookup(this.options);n&&typeof n==`string`&&(n=[n]),n&&(t=t.concat(n))}}),t=t.filter(e=>e!=null&&!rt(e)).map(e=>this.options.convertDetectedLanguage(e)),this.services&&this.services.languageUtils&&this.services.languageUtils.getBestMatchFromCodes?t:t.length>0?t[0]:null}cacheUserLanguage(e){let t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:this.options.caches;t&&(this.options.excludeCacheFor&&this.options.excludeCacheFor.indexOf(e)>-1||t.forEach(t=>{this.detectors[t]&&this.detectors[t].cacheUserLanguage(e,this.options)}))}};Ct.type=`languageDetector`;var wt={en:{translation:{nav:{printers:`Printers`,archives:`Archives`,queue:`Print Queue`,stats:`Statistics`,profiles:`Profiles`,maintenance:`Maintenance`,projects:`Projects`,inventory:`Filament`,files:`File Manager`,makerworld:`MakerWorld`,notifications:`Notifications`,settings:`Settings`,system:`System`,collapseSidebar:`Collapse sidebar`,expandSidebar:`Expand sidebar`,update:`Update`,updateAvailable:`Update available: v{{version}}`,updateAvailableBanner:`Version {{version}} is available!`,viewUpdate:`View update`,viewOnGithub:`View on GitHub`,keyboardShortcuts:`Keyboard shortcuts (?)`,switchToLight:`Switch to light mode`,switchToDark:`Switch to dark mode`,switchToSystem:`Switch to system mode`,smartSwitches:`Smart Switches`,logout:`Logout`,installApp:`Install app`,installAppSuccess:`Bambuddy was installed`},common:{save:`Save`,saving:`Saving...`,cancel:`Cancel`,delete:`Delete`,edit:`Edit`,add:`Add`,close:`Close`,confirm:`Confirm`,loading:`Loading...`,error:`Error`,errorLoading:`Error loading data`,retry:`Retry`,success:`Success`,warning:`Warning`,enabled:`Enabled`,disabled:`Disabled`,yes:`Yes`,no:`No`,on:`On`,off:`Off`,all:`All`,none:`None`,search:`Search`,filter:`Filter`,sort:`Sort`,refresh:`Refresh`,download:`Download`,upload:`Upload`,uploading:`Uploading...`,uploadFailed:`Upload failed`,actions:`Actions`,status:`Status`,name:`Name`,description:`Description`,date:`Date`,time:`Time`,hours:`hours`,minutes:`minutes`,seconds:`seconds`,days:`days`,enable:`Enable`,disable:`Disable`,permissions:`Permissions`,noPrinters:`No printers configured`,noData:`No data available`,linkNotFound:`Link not found`,required:`Required`,optional:`Optional`,dismiss:`Dismiss`,apply:`Apply`,reset:`Reset`,export:`Export`,import:`Import`,clear:`Clear`,selectAll:`Select All`,deselectAll:`Deselect All`,noChange:`— No change —`,unchanged:`Unchanged`,unassigned:`Unassigned`,unknown:`Unknown`,unknownError:`Unknown error`,today:`Today`,tomorrow:`Tomorrow`,asap:`ASAP`,overdue:`Overdue`,now:`Now`,collapse:`Collapse`,expand:`Expand`,previous:`Previous`,next:`Next`,viewArchive:`View archive`,viewInFileManager:`View in File Manager`,addedBy:`Added by {{username}}`,prints:`prints`,more:`+{{count}} more`,ascending:`Ascending`,descending:`Descending`,back:`Back`,copy:`Copy`,copied:`Copied!`,printer:`Printer`,remove:`Remove`,type:`Type`,print:`Print`,rename:`Rename`,move:`Move`,create:`Create`,duplicate:`Duplicate`,left:`Left`,right:`Right`},printers:{title:`Printers`,addPrinter:`Add Printer`,addPreflight:{checking:`Checking connection...`,warning:`Some connection checks failed. This printer may show as offline. Review the checks below, fix what you can, or save anyway.`,back:`Back`,saveAnyway:`Save anyway`},editPrinter:`Edit Printer`,deletePrinter:`Delete Printer`,printerName:`Printer Name`,serialNumber:`Serial Number`,ipAddress:`IP Address / Hostname`,accessCode:`Access Code`,model:`Model`,nozzleCount:`Nozzle Count`,autoArchive:`Auto Archive`,status:{available:`Available`,idle:`Idle`,printing:`Printing`,paused:`Paused`,offline:`Offline`,problem:`Problem`,error:`Error`,finished:`Finished`,unknown:`Unknown`},temperatures:{nozzle:`Nozzle`,bed:`Bed`,chamber:`Chamber`},heaterHistory:{title:`Heater History`,openLabel:`View heater history`,nozzle:`Nozzle`,nozzle2:`Nozzle 2`,bed:`Bed`,chamber:`Chamber`,error:`Failed to load history`,empty:`No data recorded yet`},progress:`{{percent}}% complete`,timeRemaining:`{{time}} remaining`,deleteConfirm:`Are you sure you want to delete "{{name}}"?`,maintenanceOk:`Maintenance OK`,maintenanceWarning:`{{count}} warning`,maintenanceWarning_plural:`{{count}} warnings`,maintenanceDue:`{{count}} due`,maintenanceDue_plural:`{{count}} due`,sort:{name:`Name`,status:`Status`,model:`Model`,location:`Location`,eta:`ETA`,ascending:`Sort ascending`,descending:`Sort descending`},cardSize:{small:`Small cards`,medium:`Medium cards`,large:`Large cards`,extraLarge:`Extra large cards`},pageView:{openCamWallPage:`Open cam wall as page`,cards:`Cards`,camWall:`Cam wall`},camWall:{page:{tokenRejected:`This Cam Wall link is no longer valid. The token may have expired or been revoked.`,loadFailed:`Could not load the printers.`},noPrinters:`No printers to show`,noSignal:`No signal`,live:`Live`,snap:`Snap`,off:`Off`,summary:`{{live}} live, {{snap}} snapshots, {{total}} total`,layer:`Layer {{cur}}/{{total}}`,timeLeft:`{{time}} left`,statusMode:{off:`Off`,compact:`Compact`,full:`Full`},settings:{title:`Cam wall settings`,maxLive:`Max live streams`,maxLiveHint:`How many tiles stream live at once. Others refresh as snapshots.`,snapshotInterval:`Snapshot interval (seconds)`,snapshotIntervalHint:`How often non-live tiles fetch a fresh snapshot.`,statusOverlay:`Status overlay`,statusOverlayHint:`Compact: state badge only. Full: + progress, layer, time left.`}},hideOffline:`Hide offline`,nextAvailable:`Next available`,powerOn:`Power On`,offlinePrintersWithPlugs:`Offline printers with smart plugs`,noPrintersConfigured:`No printers configured yet`,search:`Search printers...`,noSearchResults:`No printers match your search or filters`,filter:{allStatuses:`All statuses`,allLocations:`All locations`},toolbar:{filters:`Filters`,view:`View`,actions:`Actions`},readyToPrint:`Ready to print`,external:`External`,extL:`Ext-L`,extR:`Ext-R`,deleteArchives:`Delete print archives`,noLabel:`No label`,printPreview:`Print preview`,width:`Width`,height:`Height`,noObjectsFound:`No objects found`,objectsLoadedOnPrintStart:`Objects are loaded when a print starts`,willBeSkipped:`Will be skipped`,name:`Name`,serialCannotBeChanged:`Serial number cannot be changed`,locationHelp:`Used to group printers and filter queue jobs`,wifiSignal:{veryWeak:`Very weak`,weak:`Weak`,fair:`Fair`,good:`Good`,excellent:`Excellent`},maintenanceUpToDate:`All maintenance up to date - Click to view`,maintenance:{title:`In Maintenance`,subtitle:`This printer is paused — not connected, not eligible for the queue, not sending notifications.`,pillLabel:`Maintenance`,exitButton:`Exit maintenance`,menuEnter:`Enter maintenance mode`,menuExit:`Exit maintenance mode`,toastEntered:`{{name}} is now in maintenance mode`,toastExited:`{{name}} is back online`,confirmMidPrintTitle:`Enter maintenance mode mid-print?`,confirmMidPrintMessage:`{{name}} is currently printing. Entering maintenance mode will disconnect MQTT and stop progress tracking and completion notifications for this job. Continue?`,editFieldLabel:`Maintenance mode`,editFieldHelp:`When on, this printer is paused from MQTT, queue dispatch and notifications — useful for repair, parallel Bambuddy installs, or temporary suspension.`},chamberLightOn:`Turn on chamber light`,chamberLightOff:`Turn off chamber light`,files:`Files`,browseFiles:`Browse printer files`,autoOffAfterPrint:`Auto power-off after print`,autoOffExecuted:`Auto-off was executed - turn printer on to reset`,hmsErrors:`HMS Errors`,viewHmsErrors:`View {{count}} HMS error(s)`,resume:`Resume`,pause:`Pause`,stop:`Stop`,camera:`Camera`,skipObject:`Skip Object`,reconnect:`Reconnect`,forceRefresh:`Force Refresh`,forceRefreshSuccess:`Refresh requested`,mqttDebug:`MQTT Debug`,printerInformation:`Printer Information`,copyToClipboard:`Copy`,copied:`Copied!`,state:`State`,wifiSignalLabel:`WiFi Signal`,developerMode:`Developer Mode`,enabled:`Enabled`,disabled:`Disabled`,addedOn:`Added`,sdCard:`SD Card`,inserted:`Inserted`,notInserted:`Not inserted`,totalPrintHours:`Print Hours`,activeNozzle:`Active: {{nozzle}} nozzle`,nozzleRack:`Nozzle Rack`,nozzleDocked:`Docked`,nozzleMounted:`Mounted`,nozzleActive:`Active`,nozzleIdle:`Idle`,nozzleDiameter:`Diameter`,nozzleType:`Type`,nozzleStatus:`Status`,nozzleFilament:`Filament`,nozzleWear:`Wear`,nozzleMaxTemp:`Max Temp`,nozzleSerial:`Serial`,nozzleHardenedSteel:`Hardened Steel`,nozzleStainlessSteel:`Stainless Steel`,nozzleTungstenCarbide:`Tungsten Carbide`,nozzleFlow:`Flow`,nozzleHighFlow:`High Flow`,nozzleStandardFlow:`Standard`,firmwareUpdate:`Firmware Update`,firmwareInstructions:`On the printer's touchscreen, go to`,firmwareNav:`Navigate to`,settings:`Settings`,firmware:`Firmware`,discoverPrinters:`Discover Printers`,searching:`Searching...`,manualEntry:`Manual Entry`,addFromCloud:`Add from Cloud`,toast:{printerDeleted:`Printer deleted`,missingSpoolAssignment:`Print started on {{printer}}. Missing spool assignment for: {{slots}}`,assignmentVerified:`Filament loaded on slot {{slot}} ({{printer}})`,assignmentVerifiedNoKprofile:`Slot {{slot}} on {{printer}} loaded, but the flow calibration (K-profile) was not applied`,assignmentNotConfirmed:`Could not confirm the assignment for slot {{slot}} on {{printer}} — check the AMS slot`,printerAdded:`Printer added`,printerUpdated:`Printer updated`,failedToDelete:`Failed to delete printer`,failedToAdd:`Failed to add printer`,connectionFailedNotAdded:`Could not connect to the printer. Verify the IP, serial number, and access code, and confirm LAN-only mode is on. The printer was not added.`,failedToUpdate:`Failed to update printer`,commandSent:`Command sent`,failedToSendCommand:`Failed to send command`,turnedOn:`{{name}} turned on`,failedToPowerOn:`Failed to power on {{name}}`,scriptTriggered:`Script triggered`,printStopped:`Print stopped`,printPaused:`Print paused`,printResumed:`Print resumed`,referenceDeleted:`Reference deleted`,detectionAreaSaved:`Detection area saved`,failedToRunScript:`Failed to run script`,failedToStopPrint:`Failed to stop print`,failedToPausePrint:`Failed to pause print`,failedToResumePrint:`Failed to resume print`,failedToControlChamberLight:`Failed to control chamber light`,failedToSetSpeed:`Failed to set print speed`,failedToUpdateSetting:`Failed to update setting`,failedToSkipObjects:`Failed to skip objects`,failedToRereadRfid:`Failed to re-read RFID`,failedToCheckPlate:`Failed to check plate`,failedToUpdateLabel:`Failed to update label`,failedToDeleteReference:`Failed to delete reference`,failedToSaveDetectionArea:`Failed to save detection area`,plateCheckEnabled:`Plate check enabled`,plateCheckDisabled:`Plate check disabled`,calibrationSaved:`Calibration saved!`,calibrationFailed:`Calibration failed`,rfidRereadInitiated:`RFID re-read initiated`,loadInitiated:`Loading filament…`,unloadInitiated:`Unloading filament…`,failedToLoad:`Failed to load filament`,failedToUnload:`Failed to unload filament`},connection:{connected:`Connected`,offline:`Offline`},plateStatus:{markCleared:`Mark plate as cleared`,cleared:`Plate Clear`,notCleared:`Plate not Clear`,inUse:`Plate in Use`},queue:{inQueue:`{{count}} print in queue`,inQueue_plural:`{{count}} prints in queue`},controls:`Controls`,rfid:{reread:`Re-read RFID`},ams:{load:`Load`,unload:`Unload`},bedJog:{limitWarning:`Travel limits are not enforced during manual moves — a Bambu firmware bug ignores software endstops for remote commands. Move carefully to avoid a collision.`,title:`Jog Controls`,bed:`Bed`,step:`Step (mm)`,up:`Move plate up`,down:`Move plate down`,disabledWhilePrinting:`Disabled while printing`,notHomedTitle:`Printer is not homed`,notHomedMessage:`The printer has not been homed since the last print. Run auto-home first for safe positioning (parks the toolhead, then homes X, Y, and Z), or move anyway — soft endstops will be bypassed.`,homeZ:`Auto Home`,moveAnyway:`Move anyway`,homingStarted:`Auto-homing printer…`},permission:{noAdd:`You do not have permission to add printers`,noEdit:`You do not have permission to edit printers`,noDelete:`You do not have permission to delete printers`,noControl:`You do not have permission to control printers`,noFiles:`You do not have permission to access printer files`,noAmsRfid:`You do not have permission to re-read AMS RFID`,noSmartPlugControl:`You do not have permission to control smart plugs`,noCamera:`You do not have permission to view cameras`},modal:{addTitle:`Add Printer`,editTitle:`Edit Printer`,myPrinter:`My Printer`,selectModel:`Select model...`,locationGroup:`Location / Group (optional)`,locationPlaceholder:`e.g., Workshop, Office, Basement`,autoArchiveLabel:`Auto-archive completed prints`,fromPrinterSettings:`From printer settings`,modelOptional:`Model (optional)`,saveChanges:`Save Changes`},skipObjects:{tooltip:`Skip objects`,onlyWhilePrinting:`Skip objects (only while printing)`,requiresMultiple:`Skip objects (requires 2+ objects)`,title:`Skip Objects`,matchIdsInfo:`Match IDs with your printer display`,printerShowsIds:`The printer screen shows object IDs on the build plate`,skipSelected:`Skip Selected`,skipping:`Skipping...`,noObjectsSelected:`No objects selected`,selectObjectsToSkip:`Select objects you want to skip from the current print`,skipped:`skipped`,objectsSkipped:`Objects skipped`,activeCount:`{{count}} active`,waitForLayer:`Wait for layer 2+ to skip objects (currently layer {{layer}})`,skip:`Skip`,confirmTitle:`Skip Object?`,confirmMessage:`Are you sure you want to skip "{{name}}"? This cannot be undone.`,confirmAllMessage:`All remaining objects are selected. This will stop the print job. Continue?`,confirmMultipleMessage:`Skip {{count}} selected objects? This cannot be undone.`},confirm:{deleteTitle:`Delete Printer`,deleteMessage:`Are you sure you want to delete "{{name}}"? This will remove all connection settings.`,deleteArchivesNote:`All print history for this printer will be permanently deleted.`,keepArchivesNote:`Print history will be kept but no longer associated with this printer.`,stopTitle:`Stop Print`,stopMessage:`Are you sure you want to stop the current print on "{{name}}"? This will cancel the print job.`,stopButton:`Stop Print`,pauseTitle:`Pause Print`,pauseMessage:`Are you sure you want to pause the current print on "{{name}}"?`,pauseButton:`Pause Print`,resumeTitle:`Resume Print`,resumeMessage:`Are you sure you want to resume the print on "{{name}}"?`,resumeButton:`Resume Print`,powerOnTitle:`Power On Printer`,powerOnMessage:`Are you sure you want to turn ON the power for "{{name}}"?`,powerOnButton:`Power On`,powerOffTitle:`Power Off Printer`,powerOffMessage:`Are you sure you want to turn OFF the power for "{{name}}"?`,powerOffWarning:`WARNING: "{{name}}" is currently printing! Are you sure you want to turn OFF the power? This will interrupt the print and may damage the printer.`,powerOffButton:`Power Off`,haToggleTitle:`Toggle "{{name}}"`,haToggleMessage:`Toggle the Home Assistant entity {{entity}}? This may turn power off if it is currently on.`,haToggleWarning:`WARNING: "{{name}}" is currently printing! Toggling {{entity}} may cut power and interrupt the print. Continue?`,haToggleButton:`Toggle`},bulk:{select:`Select`,selectAll:`Select All`,selectByLocation:`Select by Location`,selected:`{{count}} selected`,actions:{stop:`Stop`,pause:`Pause`,resume:`Resume`,clearPlate:`Clear Bed`,clearHMS:`Clear Notifications`},confirm:{stopTitle:`Stop {{count}} Prints`,stopMessage:`This will cancel active prints on {{count}} printer(s). This action cannot be undone.`,stopButton:`Stop All`,pauseTitle:`Pause {{count}} Prints`,pauseMessage:`This will pause active prints on {{count}} printer(s).`,pauseButton:`Pause All`,clearPlateTitle:`Clear {{count}} Print Beds`,clearPlateMessage:`This will clear the print bed on {{count}} printer(s) and may trigger queued jobs.`,clearPlateButton:`Clear All`},success:`{{action}} completed on {{count}} printer(s)`,partial:`{{succeeded}} succeeded, {{failed}} failed`,noneApplicable:`No selected printers are in the right state for this action`,selectByState:`Select by State`},discovery:{title:`Discover Printers`,searching:`Searching...`,scanning:`Scanning...`,scanProgress:`Scanning... {{scanned}}/{{total}}`,foundPrinters:`Found {{count}} printer(s)`,noPrintersFound:`No printers found`,noPrintersFoundSubnet:`No printers found in the specified subnet.`,noPrintersFoundNetwork:`No printers found on the network.`,allConfigured:`All discovered printers are already configured.`,alreadyAdded:`Already added`,select:`Select`,manualEntry:`Manual Entry`,addFromCloud:`Add from Cloud`,subnetToScan:`Subnet to scan`,dockerNote:`Docker detected. Enter your printer's subnet in CIDR notation. Requires network_mode: host in docker-compose.yml.`,scanSubnet:`Scan Subnet for Printers`,discoverNetwork:`Discover Printers on Network`,scanningSubnet:`Scanning subnet for Bambu printers...`,scanningNetwork:`Scanning network...`,serialRequired:`Serial required`,unknown:`Unknown`,failedToStart:`Failed to start discovery`,customSubnetOption:`Custom subnet...`,customSubnetLabel:`Custom subnet (CIDR)`,customSubnetNote:`Use a custom subnet if your printer is on a different network than this server. The FTP (990) and MQTT (8883) ports must be reachable across the routing boundary.`},drying:{start:`Start Drying`,stop:`Stop Drying`,temperature:`Temperature`,duration:`Duration`,hours:`hours`,timeRemaining:`{{time}} left`,active:`Drying`,targetSummary:`{{filament}} @ {{temp}}°C`,notSupported:`Drying not supported`,powerRequired:`Connect AMS power adapter to enable drying`,startingDrying:`Starting drying...`,toastCommandSent:`Drying command sent`,toastStopped:`Drying stopped`,toastNotStarted:`The printer accepted the command but the AMS never started drying. Check that the AMS power adapter is connected and that the printer is idle.`,screenOnly:`AMS drying on this printer can only be controlled from the printer's own screen (Bambu limitation)`,stoppingDrying:`Stopping drying...`,rotateTray:`Rotate spool during drying`,rotateUnavailableReason:`Unavailable — a slot in this AMS is loaded to the toolhead. The spool is locked by the feed tube and cannot rotate. Retract the filament first.`},amsBackup:{titleOn:`AMS Filament Backup is ON. Click to disable.`,titleOff:`AMS Filament Backup is OFF. Click to enable.`,titleUnknown:`AMS Filament Backup status unavailable on this printer.`,toastEnabled:`AMS Filament Backup enabled`,toastDisabled:`AMS Filament Backup disabled`,modalTitle:`AMS Filament Backup`,modalHelp:`When the active slot runs out, the printer cycles through any matching same-preset, same-colour slots in this order.`,modalNoSlots:`No filament loaded.`,modalNoPairs:`No backup pairs — no two slots share the same filament profile and colour.`,extruderRightShort:`R`,extruderLeftShort:`L`,stateOn:`Enabled`,stateOff:`Disabled`,stateUnknown:`Unsupported on this printer`},activeJobSlot:{title:`This slot is filament {{n}} in the active print`,ariaLabel:`Active print slot {{n}}`},expectedSlot:{title:`The printer is waiting for filament in this slot`,ariaLabel:`Expected filament slot {{n}}`,label:`{{ams}} · Slot {{slot}}`,external:`External spool`},filaments:`Filaments`,openCameraOverlay:`Open camera overlay`,openCameraWindow:`Open camera in new window`,firmwareUpdateAvailable:`Firmware update available: {{current}} → {{latest}}`,firmwareUpToDate:`Firmware {{version}} — Up to date`,firmwareUpdateButton:`Update`,plateDetection:{noPermission:`You do not have permission to update printers`,enabledClick:`Plate check enabled - Click to disable`,disabledClick:`Plate check disabled - Click to enable`,manageCalibration:`Manage plate detection calibration`,calibrationRequired:`Calibration Required`,calibrationInstructions:`Please ensure the build plate is completely empty, then click Calibrate.`,calibrationDescription:`Calibration captures a reference image of the empty plate. Future checks will compare against this reference to detect objects.`,calibrationTip:`Tip: You can store up to 5 calibrations for different plates. The system automatically uses the best match when checking.`,plateEmpty:`Plate appears empty`,objectsDetected:`Objects detected on plate`,confidence:`Confidence`,difference:`Difference`,analysisPreview:`Analysis preview:`,analysisLegend:`Green box = detection area, Red overlay = differences from calibration`,savedReferences:`Saved References ({{count}}/{{max}})`,deleteReference:`Delete reference`,labelPlaceholder:`Label...`,clickToEdit:`{{label}} - Click to edit`,clickToAddLabel:`Click to add label`},speed:{title:`Print Speed`,silent:`Silent (50%)`,standard:`Standard (100%)`,sport:`Sport (124%)`,ludicrous:`Ludicrous (166%)`},airduct:{title:`Airduct Mode`,cooling:`Cooling`,heating:`Heating`},noSdCard:`No SD`,door:{open:`Open`,closed:`Closed`},fans:{partCooling:`Part Cooling Fan`,auxiliary:`Auxiliary Fan`,leftAuxiliary:`Left Auxiliary Fan`,exhaust:`Exhaust`,chamber:`Chamber Fan`},clickToViewHmsErrors:`Click to view HMS errors`,aiDetection:{safe:`Safe`,warning:`Warning`,failure:`Failure`,idle:`Idle`,tooltip:`AI Failure Detection: {{status}} (score {{score}}) - click for details`,tooltipIdle:`AI Failure Detection enabled - monitoring starts with the next print - click for details`,modalTitle:`AI Failure Detection - {{name}}`,currentStatus:`Status`,score:`Score`,framesAnalyzed:`Frames analyzed`,idleHint:`No print is being monitored right now. Monitoring starts automatically with the next print.`,lastError:`Last error`,openSettings:`Open settings`},estimatedCompletion:`Estimated completion time`,plateNumber:`Plate {{number}}`,slotOptions:`Slot options`,amsPopup:{friendlyName:`AMS Name`,friendlyNamePlaceholder:`e.g. AMS Friendly Name`,serialNumber:`Serial Number`,firmwareVersion:`Firmware`,save:`Save`,clear:`Clear`,noEditPermission:`You do not have permission to rename AMS units`},firmwareModal:{title:`Firmware Update`,titleUpToDate:`Firmware Info`,currentVersion:`Current:`,latestVersion:`Latest:`,releaseNotes:`Release Notes`,checkingPrereqs:`Checking prerequisites...`,sdCardReady:`SD card ready. Click below to upload firmware.`,uploadedSuccess:`Firmware uploaded to SD card!`,applyInstructions:`To apply the update on your printer:`,step1:`On the printer's touchscreen, go to Settings`,step2:`Navigate to Firmware`,step3:`Select Update from SD card`,step4:`The update will take 10-20 minutes`,done:`Done`,starting:`Starting...`,uploadFirmware:`Upload Firmware`,uploadFailed:`Failed to start upload: {{error}}`,uploadedToast:`Firmware uploaded! Trigger update from printer screen.`,availableVersions:`Available versions`,usable:`Usable`,unavailable:`Unavailable`,installed:`Installed`,newerBadge:`newer`,olderBadge:`older`,currentBadge:`current`},accessCodePlaceholder:`Leave empty to keep current`,roi:{title:`Detection Area (ROI)`,xStart:`X Start`,yStart:`Y Start`,width:`Width`,height:`Height`,instruction:`Adjust the detection area to focus on the build plate. The green box in the preview shows the current area.`},developerModeWarning:`Developer LAN mode is not enabled on: {{names}}. Some features may not work.`,howToEnable:`How to enable`,incompatibleFile:`This file was sliced for {{slicedFor}}, but this printer is a {{printerModel}}`,dropNotPrintable:`Only .gcode and .gcode.3mf files can be printed`,dropToPrint:`Drop to print`,cannotPrint:`Printer busy`},archives:{title:`Print Archives`,no3mfBanner:{title:`Some recent prints couldn't be archived with thumbnails`,body:`The slicer didn't leave the .gcode.3mf on the printer's SD card, so Bambuddy couldn't pull the thumbnail or slicer metadata. This is usually because "Store sent files on external storage" is off in the slicer (Bambu Studio / OrcaSlicer Device tab).`,docsLink:`See install step 4`,dismissLabel:`Dismiss this notice`},searchPlaceholder:`Search archives...`,filterByPrinter:`Filter by printer`,filterByStatus:`Filter by status`,sortBy:`Sort by`,sortNewest:`Newest first`,sortOldest:`Oldest first`,sortName:`Name`,sortDuration:`Duration`,sortLargest:`Largest first`,sortSmallest:`Smallest first`,sortSize:`Size`,noArchives:`No archives found`,noArchivesSearch:`No archives match your search`,originalPrintNotVisible:`Original print not visible - try clearing filters`,noArchivesYet:`No archives yet`,prints:`prints`,pagination:{showing:`Showing`,to:`to`,of:`of`,show:`Show`,page:`Page`,all:`All`},loadingArchives:`Loading archives...`,releaseToUpload:`Release to upload`,showAll:`Show all`,showFavoritesOnly:`Show favorites only`,gridView:`Grid view`,listView:`List view`,calendarView:`Calendar view`,logView:`Print Log`,manageTags:`Manage Tags`,showFailedPrints:`Show failed prints`,hideFailedPrints:`Hide failed prints`,hideDuplicates:`Hide Duplicates`,viewOriginalPrint:`Click to view original print (#{{id}})`,printTime:`Print Time`,filamentUsed:`Filament Used`,cost:`Cost`,preview:`Preview`,deleteArchive:`Delete Archive`,deleteConfirm:`Are you sure you want to delete this archive?`,favorite:`Favorite`,unfavorite:`Remove from favorites`,viewDetails:`View Details`,status:{completed:`Completed`,failed:`Failed`,stopped:`Stopped`},toast:{source3mfAttached:`Source 3MF attached: {{filename}}`,failedUploadSource3mf:`Failed to upload source 3MF`,source3mfRemoved:`Source 3MF removed`,failedRemoveSource3mf:`Failed to remove source 3MF`,f3dAttached:`F3D attached: {{filename}}`,failedUploadF3d:`Failed to upload F3D`,f3dRemoved:`F3D removed`,failedRemoveF3d:`Failed to remove F3D`,timelapseAttached:`Timelapse attached: {{filename}}`,timelapseAlreadyAttached:`Timelapse already attached`,noMatchingTimelapse:`No matching timelapse found`,failedScanTimelapse:`Failed to scan for timelapse`,failedAttachTimelapse:`Failed to attach timelapse`,timelapseRemoved:`Timelapse removed`,failedRemoveTimelapse:`Failed to remove timelapse`,timelapseUploaded:`Timelapse uploaded: {{filename}}`,failedUploadTimelapse:`Failed to upload timelapse`,archiveDeleted:`Archive deleted`,failedDeleteArchive:`Failed to delete archive`,addedToFavorites:`Added to favorites`,removedFromFavorites:`Removed from favorites`,projectUpdated:`Project updated`,failedUpdateProject:`Failed to update project`,linkCopied:`Link copied to clipboard`,failedCopyLink:`Failed to copy link`,photoDeleted:`Photo deleted`,failedDeletePhoto:`Failed to delete photo`,failedDeleteArchives:`Failed to delete archives`,failedUpdateFavorites:`Failed to update favorites`,exportDownloaded:`Export downloaded`,exportFailed:`Export failed`},menu:{print:`Print`,openInBambuStudio:`Open in Slicer`,slice:`Slice`,externalLink:`External Link`,viewOnMakerWorld:`View on MakerWorld`,preview3d:`3D Preview`,viewTimelapse:`View Timelapse`,scanForTimelapse:`Scan for Timelapse`,uploadTimelapse:`Upload Timelapse`,removeTimelapse:`Remove Timelapse`,downloadSource3mf:`Download Source 3MF`,uploadSource3mf:`Upload Source 3MF`,replaceSource3mf:`Replace Source 3MF`,removeSource3mf:`Remove Source 3MF`,uploadF3d:`Upload F3D`,replaceF3d:`Replace F3D`,downloadF3d:`Download F3D`,removeF3d:`Remove F3D`,download:`Download`,copyDownloadLink:`Copy Download Link`,qrCode:`QR Code`,viewPhotos:`View Photos`,viewPhotosCount:`View Photos ({{count}})`,projectPage:`Project Page`,addToFavorites:`Add to Favorites`,removeFromFavorites:`Remove from Favorites`,edit:`Edit`,printLog:`Print Log`,goToProject:`Go to Project: {{name}}`,addToProject:`Add to Project`,removeFromProject:`Remove from Project`,loading:`Loading...`,noProjectsAvailable:`No projects available`,searchProjects:`Search projects…`,select:`Select`,deselect:`Deselect`,delete:`Delete`},permission:{noReprint:`You do not have permission to reprint this archive`,noAddToQueue:`You do not have permission to add to queue`,noUpdateArchives:`You do not have permission to update archives`,noUploadFiles:`You do not have permission to upload files`,noDownload:`You do not have permission to download archives`,noCopyLink:`You do not have permission to copy download links`,noDelete:`You do not have permission to delete this archive`,noEdit:`You do not have permission to edit this entry`,noCreate:`You do not have permission to create archives`},platePicker:{title:`Select plate to preview`,hint:`This archive has multiple plates. Pick one to open in the GCode viewer.`,plateLabel:`Plate {{index}}`,objectCount:`{{count}} object`,objectCount_plural:`{{count}} objects`,noGcode:`This archive has no sliced G-code to preview. Open it in Bambu Studio to slice first.`},card:{previousPlate:`Previous plate`,nextPlate:`Next plate`,plateNumber:`Plate {{index}}`,moreOptions:`Right-click for more options`,addToFavorites:`Add to favorites`,removeFromFavorites:`Remove from favorites`,cancelled:`cancelled`,failed:`failed`,duplicate:`duplicate`,duplicateTitle:`This model has been printed before`,openSource3mf:`Open source 3MF in Bambu Studio (right-click for more options)`,downloadF3d:`Download Fusion 360 design file`,viewTimelapse:`View timelapse`,viewPhoto:`View 1 photo`,viewPhotos:`View {{count}} photos`,openFolder:`Open folder: {{name}}`,slicedFile:`Sliced file - ready to print`,sourceFile:`Source file only - no AMS mapping available`,gcode:`GCODE`,source:`SOURCE`,project:`Project: {{name}}`,runsBadge:`{{count}} prints`,runsBadgeTitle:`{{count}} prints total — {{successful}} successful, {{failed}} failed. Click to see the full print log.`,estimated:`Estimated: {{time}}`,actual:`Actual: {{time}}`,accuracy:`Accuracy: {{percent}}%`,filament:`{{weight}}g`,layer:`{{count}} layer`,layers:`{{count}} layers`,object:`{{count}} object`,objects:`{{count}} objects`,slicedFor:`Sliced for {{model}}`,uploadedBy:`Uploaded By`,noPermissionReprint:`You do not have permission to reprint`,noFileForReprint:`No 3MF file available — the file could not be downloaded from the printer when the print was recorded`,slicerAmsMapping:`AMS mapping saved ({{printer}})`,slicerAmsMappingTooltip:`The slicer's own AMS slot choice was saved for {{printer}}. Tray numbers only mean something on that printer, so a reprint reuses them only when it targets {{printer}} again.`,noPermissionEdit:`You do not have permission to edit archives`,noPermissionDelete:`You do not have permission to delete archives`,openInBambuStudio:`Open in Slicer`,openInBambuStudioToSlice:`Open in Slicer to slice`,slice:`Slice`,externalLink:`External Link`,makerWorld:`MakerWorld: {{designer}}`,viewProject:`View project`,noExternalLink:`No external link`,preview3d:`3D Preview`,download:`Download`,edit:`Edit`,delete:`Delete`},runLog:{title:`Print Log`,modalTitle:`Print Log — {{name}}`,modalTitleFallback:`this archive`,empty:`No print events recorded for this archive yet.`,col:{date:`Date`,status:`Status`,duration:`Duration`,filament:`Filament`,cost:`Cost`},status:{completed:`Completed`,failed:`Failed`,cancelled:`Cancelled`,stopped:`Stopped`,skipped:`Skipped`,printing:`Printing`}},modal:{deleteArchive:`Delete Archive`,deleteConfirm:`Are you sure you want to delete "{{name}}"? This action cannot be undone.`,deleteButton:`Delete`,deletePurgeStats:`Also remove this print from Quick Stats (filament, time, cost, energy)`,deleteQueueItemsWarning:`{{count}} queue item(s) linked to this archive will also be removed.`,deleteBlockedByPrinting:`Cannot delete — {{count}} queue item(s) are currently printing. Stop the print first, then retry.`,removeSource3mf:`Remove Source 3MF`,removeSource3mfConfirm:`Are you sure you want to remove the source 3MF file from "{{name}}"? This will delete the original slicer project file.`,removeButton:`Remove`,removeF3d:`Remove F3D`,removeF3dConfirm:`Are you sure you want to remove the Fusion 360 design file from "{{name}}"?`,removeTimelapse:`Remove Timelapse`,removeTimelapseConfirm:`Are you sure you want to remove the timelapse video from "{{name}}"?`,timelapse:`{{name}} - Timelapse`,selectTimelapse:`Select Timelapse`,selectTimelapseDesc:`No auto-match found. Select the timelapse for this print:`,deleteArchives:`Delete Archives`,deleteArchivesConfirm:`Are you sure you want to delete {{count}} archive(s)? This action cannot be undone.`,deleteCount:`Delete {{count}}`},page:{title:`Archives`,printsCount:`{{filtered}} of {{total}} prints`,dropFilesHere:`Drop .3mf files here`,releaseToUpload:`Release to upload`,only3mfSupported:`Only .3mf files are supported`,close:`Close`,selected:`{{count}} selected`,selectAll:`Select All`,tags:`Tags`,project:`Project`,favorite:`Favorite`,delete:`Delete`,toggledFavorites:`Toggled favorites for {{count}} archive(s)`,failedUpdateFavorites:`Failed to update favorites`,archivesDeleted:`{{count}} archive(s) deleted`,failedDeleteArchives:`Failed to delete archives`,photoDeleted:`Photo deleted`,failedDeletePhoto:`Failed to delete photo`},list:{name:`Name`,printer:`Printer`,date:`Date`,size:`Size`,actions:`Actions`,hasTimelapse:`Has timelapse`},log:{date:`Date`,printName:`Print Name`,printer:`Printer`,user:`User`,status:`Status`,duration:`Duration`,filament:`Filament`,allPrinters:`All Printers`,allUsers:`All Users`,allStatuses:`All Statuses`,cancelled:`Cancelled`,skipped:`Skipped`,dateFrom:`From`,dateTo:`To`,noEntries:`No print log entries found`,showing:`Showing {{count}} of {{total}} entries`,rowsPerPage:`Rows`,page:`Page`,prev:`Prev`,next:`Next`,clearLog:`Clear Log`,clearLogTitle:`Clear Print Log`,clearLogConfirm:`All print log entries will be permanently deleted. Archives and queue items are not affected. This action cannot be undone. Are you sure?`,clearLogButton:`Clear All`,cleared:`{{count}} log entries cleared`,clearFailed:`Failed to clear print log`,deleteEntryTitle:`Delete print log entry`,deleteEntryConfirm:`This entry will be removed from the log and its filament, time, and cost contributions will drop out of Quick Stats. The matching archive (if any) is not affected. This action cannot be undone.`,entryDeleted:`Print log entry deleted`,entryDeleteFailed:`Failed to delete print log entry`,editEntryTitle:`Edit print log entry`,editEntryDescription:`Classify this print run. The Failure Analysis widget groups by these values, so updates flow through to stats immediately.`,entryUpdated:`Print log entry updated`,entryUpdateFailed:`Failed to update print log entry`,statuses:{completed:`Completed`,failed:`Failed`,stopped:`Stopped`,cancelled:`Cancelled`,skipped:`Skipped`}}},dispatchToast:{untitled:`Print job`,startingPrints:`Starting prints`,progressSummary:`{{complete}}/{{total}} complete • Processing: {{processing}}`,expandDetails:`Expand dispatch details`,collapseDetails:`Collapse dispatch details`,awaitingPrinter:`Awaiting printer…`,status:{processing:`Processing`,completed:`Completed`,failed:`Failed`},failed:{generic:`Dispatch failed`,upload_failed:`Upload to printer failed`,start_command_failed:`Printer rejected start command`},dismiss:`Dismiss`},pipelineRuns:{title:`Pipeline Runs`,loading:`Loading…`,empty:`No pipeline runs yet.`,filter:{pipeline:`Pipeline`,status:`Status`,target:`Target`,all:`All`,allPipelines:`All pipelines`,allStatus:`All statuses`,allTargets:`All targets`,clear:`Clear filters`,noMatches:`No runs match the current filters.`},totalCount_one:`{{n}} run`,totalCount_other:`{{n}} runs`,copies:`{{n}} copies`,failedCount:`{{n}} failed`,copyN:`Copy {{n}}`,retryFailed:`Retry failed`,retryOf:`retry of #{{n}}`,pagination:`{{start}}–{{end}} of {{total}}`,cancelledByUser:`Cancelled by user`,toast:{cancelled:`Run cancelled`,cancelFailed:`Cancel failed`,retryStarted:`Retry started`,retryFailed:`Retry failed`,cleared:`{{n}} runs cleared`,clearFailed:`Clear failed`},clearLog:`Clear log`,clearConfirmTitle:`Clear log?`,clearConfirmBody:`Delete every completed, failed, cancelled, and partial-failure pipeline run? In-flight runs are kept. This cannot be undone.`,clearConfirmAction:`Clear`,jobStatus:{pending:`pending`,awaiting_printer:`awaiting printer`,queued:`queued`,printing:`printing`,completed:`completed`,failed:`failed`,cancelled:`cancelled`}},queue:{title:`Print Queue`,subtitle:`Schedule and manage your print jobs`,filamentShort:{rowBadge:`Insufficient filament for the assigned spool`,rowTooltip:`The dispatch scheduler flagged this item. Click Play to see the per-slot deficit and decide whether to print anyway.`,confirmTitle:`Insufficient filament`,confirmIntro:`The assigned spool cannot satisfy at least one slot. Print anyway?`,lineItem:`Slot {{slot}}: needs {{required}} g, {{remaining}} g remaining`,unknown:`unknown`,printAnyway:`Print Anyway`},slicerAmsMapping:{rowBadge:`AMS slots saved for this printer`,rowTooltip:`This archive carries the exact AMS slots the slicer picked, saved for the printer this item targets. A reprint on it can reuse those trays instead of matching again by type and colour.`},editQueueItem:`Edit Queue Item`,selectAllPlates:`Select All {{count}} Plates`,deselectAll:`Deselect All`,printQueued:`Print queued`,printQueuedWillStartWhenIdle:`Will start when printer is idle`,itemsQueued:`{{count}} items queued`,sending:`Sending...`,sendingProgress:`Sending {{current}}/{{total}}...`,adding:`Adding...`,addingProgress:`Adding {{current}}/{{total}}...`,savingProgress:`Saving {{current}}/{{total}}...`,clearQueue:`Clear Queue`,clearHistory:`Clear History`,emptyQueue:`Queue is empty`,position:`Position`,scheduledTime:`Scheduled Time`,moveUp:`Move Up`,moveDown:`Move Down`,startNow:`Start Now`,printingInProgress:`Printing in progress...`,viewArchive:`View archive`,viewInFileManager:`View in File Manager`,itemCount:`{{count}} item`,itemCount_plural:`{{count}} items`,dragToReorder:`Drag to reorder (ASAP only)`,reorderHint:`Position only affects ASAP items. Scheduled items run at their set time.`,sjf:{label:`SJF`,tooltip:`Shortest Job First — scheduler prioritizes shorter prints`},addedBy:`Added by {{name}}`,nextInQueue:`Next in queue`,clearPlateSuccess:`Plate cleared — ready for next print`,plateNumber:`Plate {{index}}`,quantity:`Quantity`,quantityHint:`Creates {{count}} queue items`,activeBatches:`Active Batches`,batchProgress:`{{completed}} of {{total}} completed`,cancelBatch:`Cancel Remaining`,batchCancelled:`Remaining batch items cancelled`,cancelBatchConfirmTitle:`Cancel Batch`,cancelBatchConfirmMessage:`Cancel all remaining pending items in this batch?`,batch:{defaultName:`Batch`,label:`{{count}} item`,label_plural:`{{count}} items`,pendingCount:`{{count}} pending`,pendingCount_plural:`{{count}} pending`,expand:`Expand batch`,collapse:`Collapse batch`,groupAsBatch:`Group as batch…`,groupAsBatchDescription:`Combine the {{count}} selected items into a single collapsible batch.`,nameLabel:`Batch name`,namePlaceholder:`e.g. Friday gifts`,create:`Create batch`,ungroup:`Ungroup`,ungroupConfirmTitle:`Ungroup batch?`,ungroupConfirmMessage:`The items will stay in the queue but no longer be grouped together.`,dragGroup:`Drag group`},tabs:{queue:`Queue`,history:`History`,timeline:`Timeline`,pipelines:`Pipelines`},layout:{flatList:`List`,byPrinter:`By Printer`,groupByPrinter:`Group by Printer`},history:{emptyTitle:`No history yet`,emptyDescription:`Completed, cancelled, and failed prints will appear here.`,showMore:`Show more`,showingCount:`Showing {{shown}} of {{total}}`},dragGhost:{multiCount:`{{count}} items`,batch:`{{name}} ({{count}} copy)`,batch_plural:`{{name}} ({{count}} copies)`},sections:{currentlyPrinting:`Currently Printing`,queued:`Queued`,history:`History`},status:{pending:`Pending`,waiting:`Waiting`,printing:`Printing`,paused:`Paused`,completed:`Completed`,failed:`Failed`,skipped:`Skipped`,cancelled:`Cancelled`},summary:{printing:`Printing`,queued:`Queued`,totalTime:`Total Queue Time`,totalWeight:`Total Queue Weight`,history:`History`},filter:{allPrinters:`All Printers`,unassigned:`Unassigned`,allStatus:`All Status`,allLocations:`All Locations`,any:`Any`},sort:{byPosition:`Sort by Position`,byName:`Sort by Name`,byPrinter:`Sort by Printer`,bySchedule:`Sort by Schedule`,byDate:`Sort by Date`,ascendingOldest:`Ascending (oldest first)`,descendingNewest:`Descending (newest first)`},badges:{staged:`Staged`,requiresPrevious:`Requires previous success`,autoPowerOff:`Auto power off`,gcodeInjection:`G-code`},empty:{title:`No prints scheduled`,description:`Schedule a print from the Archives page using the "Schedule" option in the context menu, or drag and drop files to get started.`},time:{etaIfStartedNow:`Completion time if this job started now`,asap:`ASAP`,overdue:`Overdue`,now:`Now`,lessThanMinute:`In less than a minute`,inMinutes:`In {{count}} min`,inHours:`In {{count}} hours`},actions:{startPrint:`Start Print`,stopPrint:`Stop Print`,requeue:`Re-queue`},bulkEdit:{title:`Edit {{count}} Item`,title_plural:`Edit {{count}} Items`,description:`Only changed settings will be applied to selected items.`,printer:`Printer`,noChange:`— No change —`,queueOptions:`Queue Options`,staged:`Staged (manual start)`,autoPowerOff:`Auto power off after print`,requirePrevious:`Require previous success`,printOptions:`Print Options`,bedLevelling:`Bed levelling`,flowCalibration:`Flow calibration`,vibrationCalibration:`Vibration calibration`,layerInspection:`First layer inspection`,timelapse:`Timelapse`,useAms:`Use AMS`,nozzleOffsetCali:`Nozzle offset calibration`,applyChanges:`Apply Changes`,selectAll:`Select All`,deselectAll:`Deselect All`,selected:`{{count}} selected`,editSelected:`Edit Selected`,cancelSelected:`Cancel Selected`},confirm:{cancelTitle:`Cancel Scheduled Print`,cancelMessage:`Are you sure you want to cancel "{{name}}"?`,stopTitle:`Stop Print`,stopMessage:`Are you sure you want to stop the current print "{{name}}"? This will cancel the print job on the printer.`,removeTitle:`Remove from History`,removeMessage:`Are you sure you want to remove "{{name}}" from the queue history?`,clearHistoryTitle:`Clear History`,clearHistoryMessage:`Are you sure you want to remove all {{count}} item(s) from the history?`,cancelButton:`Cancel Print`,stopButton:`Stop Print`,thisPrint:`this print`,thisItem:`this item`},toast:{cancelled:`Queue item cancelled`,cancelFailed:`Failed to cancel item`,removed:`Queue item removed`,removeFailed:`Failed to remove item`,stopped:`Print stopped`,stopFailed:`Failed to stop print`,released:`Print released to queue`,startFailed:`Failed to start print`,reorderFailed:`Failed to reorder queue`,historyCleared:`Cleared {{count}} history item(s)`,clearHistoryFailed:`Failed to clear history`,updateFailed:`Failed to update items`,bulkCancelled:`Cancelled {{count}} item(s)`,bulkCancelFailed:`Failed to cancel items`,batchCreated:`Batch "{{name}}" created`,batchCreateFailed:`Failed to create batch`,batchUngrouped:`Ungrouped {{count}} item(s)`,batchUngroupFailed:`Failed to ungroup batch`,resumedAfterFailure:`Resumed queue — {{restored}} job(s) restored to pending`,resumeAfterFailureFailed:`Failed to resume queue`},resumeAfterFailure:{banner:`{{printer}} is blocked by a previous-print failure — {{count}} job(s) skipped`,bannerHint:`Fix the printer issue, then resume to restore the skipped jobs and clear the gate.`,button:`Resume after failure`,confirmTitle:`Resume queue after failure?`,confirmMessage:`Restore {{count}} skipped job(s) on {{printer}} to pending and clear the previous-print gate. Make sure the printer is ready before continuing.`},timeline:{listView:`List`,timelineView:`Timeline`,unassigned:`Unassigned`,noData:`No scheduled prints for this day`,nothingCommitted:`No committed schedules in this window. Staged items, waiting items, and ASAP jobs on idle printers are not shown — set a scheduled time or release a staged item to see it here.`,allDoneBy:`All prints estimated done by {{time}}`,staged:`Staged`,filterAll:`Show All`,filterPrinting:`Printing`,filterQueued:`Queued`,time:{anyMoment:`any moment`,minutesLeft:`{{minutes}}m left`,hoursLeft:`{{hours}}h left`,hoursMinutesLeft:`{{hours}}h {{minutes}}m left`},day:{previous:`Previous day`,next:`Next day`,today:`Today`},window:{back12h:`Back 12 hours`,forward12h:`Forward 12 hours`,now:`Now`},printerColumnHeader:`Printer`},permissions:{noStopPrint:`You do not have permission to stop prints`,noStartPrint:`You do not have permission to start prints`,noEdit:`You do not have permission to edit this queue item`,noCancel:`You do not have permission to cancel this queue item`,noRequeue:`You do not have permission to re-queue items`,noRemove:`You do not have permission to remove this queue item`,noClearHistory:`You do not have permission to clear all history`,noEditItems:`You do not have permission to edit queue items`,noCancelItems:`You do not have permission to cancel queue items`}},stats:{title:`Statistics`,subtitle:`Drag widgets to rearrange. Click the eye icon to hide.`,overview:`Overview`,totalPrints:`Total Prints`,successRate:`Success Rate`,totalPrintTime:`Total Print Time`,printTime:`Print Time`,totalFilament:`Total Filament Used`,filamentUsed:`Filament Used`,filamentCost:`Filament Cost`,totalCost:`Total Cost`,energyUsed:`Energy Used`,energyCost:`Energy Cost`,energyWarmingUpTooltip:`Energy tracking is still collecting hourly snapshots. Date-range totals will become accurate once at least one snapshot exists before the selected range. Early values may undercount.`,averagePrintTime:`Average Print Time`,printsPerDay:`Prints per Day`,byPrinter:`By Printer`,printsByPrinter:`Prints by Printer`,byMaterial:`By Material`,byMonth:`By Month`,last7Days:`Last 7 Days`,last30Days:`Last 30 Days`,last90Days:`Last 90 Days`,allTime:`All Time`,quickStats:`Quick Stats`,printActivity:`Print Activity`,filamentTypes:`Filament Types`,filamentTrends:`Filament Trends`,failureAnalysis:`Failure Analysis`,timeAccuracy:`Time Accuracy`,successful:`Successful:`,failed:`Failed:`,cancelled:`Cancelled:`,perfectEstimate:`100% = perfect estimate`,noTimeAccuracyData:`No time accuracy data yet`,noFilamentData:`No filament data available`,noPrinterData:`No printer data available`,noPrintData:`No print data available`,noPrintDataLast30Days:`No print data in the last 30 days`,failureReasons:`Failure Reasons`,topFailureReasons:`Top Failure Reasons`,failedPrintsCount:`{{failed}} / {{total}} prints failed`,lastWeekRate:`Last week: {{rate}}%`,resetLayout:`Reset Layout`,recalculateCosts:`Recalculate Costs`,recalculateCostsHint:`Recalculate all archive costs using current filament prices`,exportStats:`Export Stats`,exportAsCsv:`Export as CSV`,exportAsExcel:`Export as Excel`,hiddenCount:`{{count}} Hidden`,exportDownloaded:`Export downloaded`,exportFailed:`Export failed`,layoutReset:`Layout reset`,recalculatedCosts:`Recalculated costs for {{count}} archives`,recalculateFailed:`Failed to recalculate costs`,loadingStats:`Loading statistics...`,noPermissionResetLayout:`You do not have permission to reset layout`,noPermissionRecalculate:`You do not have permission to recalculate costs`,noPrintDataInRange:`No print data in selected range`,periodFilament:`Period Filament`,periodCost:`Period Cost`,avgPerPrint:`Avg per Print`,usageOverTime:`Usage Over Time`,energyOverTime:`Energy Over Time`,filamentByWeight:`Weight`,printDuration:`Print Duration`,printerUtilization:`Printer Utilization`,filamentSuccess:`Success by Material`,printHabits:`Print Habits`,printTimeOfDay:`Print Time of Day`,colorDistribution:`Color Distribution`,noColorData:`No color data available`,records:`Records`,longestPrint:`Longest Print`,heaviestPrint:`Heaviest Print`,mostExpensivePrint:`Most Expensive`,busiestDay:`Busiest Day`,successStreak:`Success Streak`,streakPrint:`consecutive print`,streakPrints:`{{count}} consecutive prints`,printerStats:`Printer Stats`,hours:`hours`,avgPrints:`Avg. prints`,noArchiveData:`No print data available`,filamentByTime:`Time`,avgWeight:`Avg. weight`,avgTime:`Avg. time`,filamentByPrints:`Prints`,timeframe:{today:`Today`,"this-week":`This Week`,"this-month":`This Month`,"last-7":`Last 7 Days`,"last-30":`Last 30 Days`,"last-90":`Last 90 Days`,"this-year":`This Year`,"all-time":`All Time`,custom:`Custom Range`,from:`From`,to:`To`},allUsers:`All Users`,noUser:`No User (System)`,filterByUser:`Filter by User`},maintenance:{title:`Maintenance`,overview:`Overview`,allOk:`All maintenance up to date`,dueCount:`{{count}} item due`,dueCount_plural:`{{count}} items due`,warningCount:`{{count}} warning`,warningCount_plural:`{{count}} warnings`,totalPrintTime:`Total Print Time`,nextMaintenance:`Next Maintenance`,nothingDue:`Nothing due`,tasks:`Tasks`,lastPerformed:`Last performed`,interval:`Interval`,hoursRemaining:`{{hours}}h remaining`,hoursOverdue:`{{hours}}h overdue`,markDone:`Mark as Done`,performMaintenance:`Perform Maintenance`,history:`History`,noHistory:`No maintenance history`,editPrintHours:`Edit Print Hours`,currentHours:`Current Hours`,statusTab:`Status`,settingsTab:`Settings`,overdueCount:`{{count}} overdue`,dueSoonCount:`{{count}} due soon`,dueSoon:`Due soon`,allGood:`All good`,overdueBy:`Overdue by {{duration}}`,dueIn:`Due in {{duration}}`,timeLeft:`{{duration}} left`,day:`1 day`,days:`{{count}} days`,week:`1 week`,weeks:`{{count}} weeks`,month:`1 month`,months:`{{count}} months`,year:`1 year`,maintenanceTypes:`Maintenance Types`,maintenanceTypesDescription:`System types and your custom maintenance tasks`,addCustomType:`Add Custom Type`,restoreDefaults:`Restore Default Tasks`,intervalType:`Interval Type`,intervalValue:`Interval ({{type}})`,icon:`Icon`,documentationLink:`Documentation Link (optional)`,assignToPrinters:`Assign to Printers`,selectAtLeastOnePrinter:`Select at least one printer`,addType:`Add Type`,custom:`Custom`,printHours:`Print Hours`,calendarDays:`Calendar Days`,exampleName:`e.g., Replace HEPA Filter`,viewDocumentation:`View documentation`,timeBasedInterval:`Time-based interval`,intervalOverrides:`Interval Overrides`,intervalOverridesDescription:`Customize intervals for specific printers`,assignedToPrinters:`Assigned to printers:`,noPrintersAssigned:`No printers assigned`,addPrinterShort:`Add:`,printersAssignedClick:`{{count}} printer(s) assigned - click to manage`,removeFromPrinter:`Remove from this printer`,types:{lubricateCarbonRods:`Lubricate Carbon Rods`,lubricateRails:`Lubricate Linear Rails`,cleanNozzle:`Clean Nozzle/Hotend`,checkBelts:`Check Belt Tension`,cleanBuildPlate:`Clean Build Plate`,checkExtruder:`Check Extruder Gears`,checkCooling:`Check Cooling Fans`,generalInspection:`General Inspection`,cleanCarbonRods:`Clean Carbon Rods`,lubricateSteelRods:`Lubricate Steel Rods`,cleanSteelRods:`Clean Steel Rods`,cleanLinearRails:`Clean Linear Rails`,checkPtfeTube:`Check PTFE Tube`,replaceHepaFilter:`Replace HEPA Filter`,replaceCarbonFilter:`Replace Carbon Filter`,lubricateLeftNozzleRail:`Lubricate Left Nozzle Rail`},maintenanceComplete:`Maintenance marked as complete`,typeUpdated:`Maintenance type updated`,typeDeleted:`Maintenance type deleted`,defaultsRestored:`Restored {{count}} default task(s)`,printHoursUpdated:`Print hours updated`,printerAssigned:`Printer assigned`,printerRemoved:`Printer removed`,deleteTypeConfirm:`Delete "{{name}}"?`,deleteSystemTypeTitle:`Delete default maintenance task?`,deleteSystemTypeMessage:`Are you sure you want to delete the default maintenance task "{{name}}"?`,noPermissionUpdate:`You do not have permission to update maintenance items`,noPermissionPerform:`You do not have permission to perform maintenance`,noPermissionEditTypes:`You do not have permission to edit maintenance types`,noPermissionDeleteTypes:`You do not have permission to delete maintenance types`,noPermissionEditHours:`You do not have permission to edit print hours`,noPermissionRemovePrinter:`You do not have permission to remove printer assignments`,noPermissionAssignPrinter:`You do not have permission to assign printers`,noPermissionEditIntervals:`You do not have permission to edit intervals`,configureSettings:`Configure maintenance types and intervals`},settings:{title:`Settings`,general:`General`,tabs:{general:`General`,smartPlugs:`Smart Plugs`,notifications:`Notifications`,queue:`Workflow`,queueDispatch:`Queue & Dispatch`,queuePipelines:`Pipelines`,filament:`Filament`,network:`Network`,apiKeys:`API Keys`,virtualPrinter:`Virtual Printer`,spoolbuddy:`SpoolBuddy`,failureDetection:`Failure Detection`,users:`Authentication`,backup:`Backup`,emailAuth:`Email Authentication`,ldap:`LDAP`,twoFa:`Two-Factor Auth`,oidc:`SSO / OIDC`,security:`Security`},spoolbuddy:{infoTitle:`SpoolBuddy devices`,infoBody:`SpoolBuddy kiosks register themselves automatically via heartbeat. Unregister a device here if it is no longer in use or if a stale duplicate was left behind by a daemon crash.`,duplicatesTitle:`{{count}} devices registered`,duplicatesBody:`Only the first registered device is used by the kiosk UI. If one of these is a stale duplicate from a crash, unregister it — an online device will re-register itself on its next heartbeat.`,empty:`No SpoolBuddy devices registered yet.`,online:`Online`,offline:`Offline`,unregister:`Unregister`,unregisterSuccess:`Device unregistered`,unregisterError:`Failed to unregister device`,confirmTitle:`Unregister SpoolBuddy device?`,confirmBody:`This will remove "{{hostname}}" ({{deviceId}}) from the database. If the device is online, it will re-register itself on its next heartbeat.`,ipAddress:`IP address`,firmware:`Firmware`,lastSeen:`Last seen`,daemonUptime:`Daemon uptime`,systemUptime:`System uptime`,never:`never`,nfc:`NFC`,scale:`Scale`,cpuTemp:`CPU temp`,cpuLoad:`CPU load`,memory:`Memory`,disk:`Disk`,update:`Update`,updateConfirmTitle:`Update Spoolbuddy daemon?`,updateConfirmBody:`Trigger a software update on "{{hostname}}"? The daemon will restart once the update is applied.`,restartBrowser:`Restart Browser`,restartBrowserConfirmTitle:`Restart kiosk browser?`,restartBrowserConfirmBody:`Restart the kiosk browser on "{{hostname}}"? The display will blank briefly.`,restartDaemon:`Restart Daemon`,restartDaemonConfirmTitle:`Restart Spoolbuddy daemon?`,restartDaemonConfirmBody:`Restart the Spoolbuddy daemon on "{{hostname}}"? The device will go offline for a few seconds.`,reboot:`Reboot`,rebootConfirmTitle:`Reboot device?`,rebootConfirmBody:`Reboot "{{hostname}}"? The device will be offline for around a minute.`,shutdown:`Shutdown`,shutdownConfirmTitle:`Shutdown device?`,shutdownConfirmBody:`Shutdown "{{hostname}}"? You will need physical access to power it back on.`,commandConfirm:`Confirm`,commandQueued:`Command queued`,commandError:`Failed to send command`},ldap:{title:`LDAP Authentication`,enabledDesc:`LDAP authentication is enabled`,disabledDesc:`LDAP authentication is disabled`,disabledHint:`Configure and save LDAP settings below, then enable.`,enabled:`LDAP authentication enabled`,disabled:`LDAP authentication disabled`,feature1:`Users can login with LDAP credentials`,feature2:`Local admin account remains as fallback`,feature3:`LDAP groups are mapped to BamBuddy groups on login`,serverConfig:`LDAP Server Configuration`,serverUrl:`Server URL`,serverUrlHint:`Use ldaps:// for SSL or ldap:// with StartTLS`,security:`Security`,securityHint:`StartTLS upgrades a plain connection to TLS. LDAPS uses TLS from the start.`,bindDn:`Bind DN (Service Account)`,bindPassword:`Bind Password`,searchBase:`Search Base DN`,userFilter:`User Search Filter`,userFilterHint:`{username} is replaced with the login username. Use (uid={username}) for OpenLDAP.`,advanced:`Advanced`,autoProvision:`Auto-provision users`,autoProvisionHint:`Automatically create a BamBuddy account on first LDAP login`,defaultGroup:`Default group`,defaultGroupNone:`— None (no fallback) —`,defaultGroupHint:`Fallback group assigned when an LDAP user authenticates but is not listed in any mapped LDAP group. Leave empty to leave unmapped users without permissions.`,groupMapping:`Group Mapping (JSON)`,groupMappingHint:`Map LDAP group DNs to BamBuddy groups. Available groups: `,testConnection:`Test Connection`,settingsSaved:`LDAP settings saved`,errors:{serverRequired:`LDAP server URL is required`,searchBaseRequired:`Search base DN is required`,enableAuthFirst:`Enable authentication first`,configureLdapFirst:`Save LDAP settings first`}},email:{smtpSettings:`SMTP Configuration`,smtpHost:`SMTP Server`,smtpPort:`SMTP Port`,security:`Security`,authentication:`Authentication`,username:`Username`,password:`Password`,fromEmail:`From Email`,fromName:`From Name`,testConnection:`Test SMTP Connection`,testRecipient:`Test Recipient Email`,sendTest:`Send Test Email`,sending:`Sending...`,save:`Save Settings`,saving:`Saving...`,advancedAuth:`Advanced Authentication`,advancedAuthEnabled:`Advanced Authentication is enabled`,advancedAuthEnabledDesc:`Email-based user management features are active. New users will receive auto-generated passwords via email, and users can reset their passwords through the forgot password feature.`,advancedAuthDisabled:`Advanced Authentication is disabled`,advancedAuthDisabledDesc:`Enable advanced authentication to activate email-based features for user management.`,enable:`Enable`,disable:`Disable`,feature1:`Passwords are auto-generated and emailed to new users`,feature2:`Users can login with username or email`,feature3:`Forgot password feature is available`,feature4:`Admins can reset user passwords via email`,errors:{requiredFields:`Please fill in all required fields`,usernameRequired:`Username is required when authentication is enabled`,enterTestEmail:`Please enter a test email address`,smtpServerAndEmail:`Please fill in SMTP Server and From Email before testing`,usernamePasswordRequired:`Username and Password are required when authentication is enabled`,configureSmtpFirst:`Please configure and test SMTP settings first`,enableAuthFirst:`Please enable authentication first to use email-based features.`},success:{settingsSaved:`SMTP settings saved successfully`},securityOptions:{starttls:`STARTTLS (Port 587)`,ssl:`SSL/TLS (Port 465)`,none:`None (Port 25)`},authOptions:{enabled:`Enabled`,disabled:`Disabled`}},appearance:`Appearance`,notifications:`Notifications`,smartPlugs:`Smart Plugs`,spoolman:`Spoolman`,updates:`Updates`,language:`Language`,languageDescription:`Select your preferred language`,theme:`Theme`,themeLight:`Light`,themeDark:`Dark`,themeSystem:`System`,defaultView:`Default View`,defaultViewDescription:`Page to show when opening the app`,checkForUpdates:`Check for Updates`,autoUpdate:`Auto Update`,currentVersion:`Current Version`,latestVersion:`Latest Version`,upToDate:`You are up to date`,updateAvailable:`Update available`,notificationLanguage:`Notification Language`,notificationLanguageDescription:`Language for push notifications`,bedCooledThreshold:`Bed Cooled Threshold`,bedCooledThresholdDescription:`Temperature below which the bed is considered cooled after a print`,userNotificationsEnabled:`User Notifications`,userNotificationsEnabledDescription:`Enable the user notifications menu and email notifications for print job events. Requires Advanced Authentication.`,userNotificationsDisabledHint:`Enable Advanced Authentication to use user notifications.`,notificationProviders:`Notification Providers`,addProvider:`Add Provider`,editProvider:`Edit Provider`,providerType:`Provider Type`,testNotification:`Test Notification`,testSuccess:`Test notification sent successfully`,testFailed:`Failed to send test notification`,quietHours:`Quiet Hours`,quietHoursDescription:`Do not disturb during these hours`,quietHoursStart:`Start`,quietHoursEnd:`End`,events:{title:`Notification Events`,printStart:`Print Started`,printComplete:`Print Completed`,printFailed:`Print Failed`,printStopped:`Print Stopped`,printProgress:`Progress Milestones`,printProgressDescription:`Notify at 25%, 50%, 75%`,printerOffline:`Printer Offline`,printerError:`Printer Error`,filamentLow:`Low Filament`,maintenanceDue:`Maintenance Due`,maintenanceDueDescription:`Notify when maintenance is needed`},smartPlug:{title:`Smart Plugs`,add:`Add Smart Plug`,edit:`Edit Smart Plug`,name:`Name`,ipAddress:`IP Address`,linkedPrinter:`Linked Printer`,autoOn:`Auto Power On`,autoOnDescription:`Turn on when print starts`,autoOff:`Auto Power Off`,autoOffDescription:`Turn off after print completes`,offDelay:`Off Delay`,offDelayMinutes:`Minutes after print`,offDelayTemp:`When nozzle below temperature`,currentState:`Current State`,turnOn:`Turn On`,turnOff:`Turn Off`},filamentTracking:`Filament Tracking`,filamentTrackingDesc:`Choose how to track your filament spools. You can use the built-in inventory or connect an external Spoolman server.`,autoAddUnknownRfid:`Auto-add unknown RFID spools`,autoAddUnknownRfidDesc:`Automatically create an inventory entry when a spool with an unknown RFID tag is detected. Turn off if you pre-register new spools manually to avoid duplicates.`,filamentChecks:`Filament checks`,disableFilamentWarnings:`Disable filament warnings`,disableFilamentWarningsDesc:`Don't show warnings about insufficient filament when printing or queueing`,preferLowestFilament:`Prefer lowest remaining filament`,preferLowestFilamentDesc:`When multiple spools match, use the one with the least filament remaining`,preferLowestFilamentBackupNote:`Only takes effect when AMS Filament Backup is enabled on the printer — otherwise the printer cannot switch to a second spool when the picked one runs out.`,trackingModeBuiltIn:`Built-in Inventory`,trackingModeBuiltInDesc:`RFID auto-matching and usage tracking included`,trackingModeSpoolmanDesc:`External filament management server`,builtInFeatureRfid:`Automatically detects Bambu Lab RFID spools in AMS`,builtInFeatureUsage:`Tracks filament consumption per print`,builtInFeatureCatalog:`Manage spools, colors, and K-factor profiles`,builtInFeatureThirdParty:`Third-party spools can be assigned to inventory spools`,amsSyncButton:`Sync Weights from AMS`,amsSyncTitle:`Sync Spool Weights from AMS`,amsSyncMessage:`This will overwrite all inventory spool weights with the current AMS remain% values from connected printers. Use this to recover from corrupted weight data. Printers must be online.`,amsSyncing:`Syncing...`,amsSyncSuccess:`{{synced}} spool(s) synced, {{skipped}} skipped`,amsSyncError:`Failed to sync weights from AMS`,spoolmanAmsSyncButton:`Sync Spoolman Weights from AMS`,spoolmanAmsSyncTitle:`Sync Spoolman Spool Weights from AMS`,spoolmanAmsSyncMessage:`This will update all Spoolman spool weights based on the current AMS remain% values from connected printers. Printers must be online.`,spoolmanAmsSyncing:`Syncing...`,spoolmanAmsSyncSuccess:`{{synced}} spool(s) synced, {{skipped}} skipped`,spoolmanAmsSyncError:`Failed to sync Spoolman weights from AMS`,spoolmanAmsSyncErrorUnreachable:`Failed to sync Spoolman weights (Spoolman unreachable)`,spoolmanAmsSyncErrorNotConfigured:`Failed to sync Spoolman weights (Spoolman not configured)`,spoolmanNotConfigured:`Spoolman not configured`,spoolmanFilamentCatalogTitle:`Spoolman Filament Catalog`,spoolmanFilamentCatalogDesc:`Filament names and tare weights from your Spoolman instance. Name and spool weight are editable here; all other properties are managed directly in Spoolman.`,spoolmanUrl:`Spoolman URL`,spoolmanUrlHint:`URL of your Spoolman server (e.g., http://localhost:7912)`,spoolmanConnected:`Connected`,spoolmanDisconnected:`Disconnected`,status:`Status`,connect:`Connect`,disconnect:`Disconnect`,howSyncWorks:`How Sync Works`,syncInfoRfidOnly:`Only official Bambu Lab spools with RFID are synced`,syncInfoAutoCreate:`New spools are auto-created in Spoolman on first sync`,syncInfoThirdPartySkipped:`Non-Bambu Lab spools (third-party, refilled) are skipped`,linkingExistingSpools:`Linking Existing Spools`,linkingExistingSpoolsDesc:`To link existing Spoolman spools to your AMS, hover over an AMS slot and click "Link to Spoolman".`,syncMode:`Sync Mode`,syncModeAuto:`Automatic`,syncModeManual:`Manual Only`,syncModeAutoDesc:`AMS data syncs automatically when changes are detected`,syncModeManualDesc:`Only sync when manually triggered`,syncAmsData:`Sync AMS Data`,syncAmsDataDesc:`Manually sync printer AMS data to Spoolman`,allPrinters:`All Printers`,noDefaultPrinter:`No default (ask each time)`,sidebarOrder:`Sidebar order`,saveThumbnails:`Save thumbnails`,captureFinishPhoto:`Capture finish photo`,noPrintersConfigured:`No printers configured`,archiveMode:{always:`Always create archive entry`,never:`Never create archive entry`,ask:`Ask each time`},checkForUpdatesLabel:`Check for updates`,checkPrinterFirmware:`Check printer firmware`,includeBetaUpdates:`Include beta versions`,includeBetaUpdatesDesc:`Notify about beta and prerelease versions when checking for updates`,localLogin:{disable:`Disable local username/password login`,disableHint:`When enabled, only SSO providers can sign in. LDAP is unaffected. Set BAMBUDDY_LOCAL_LOGIN=true on the server to keep a recovery path.`},enableRetry:`Enable retry`,homeAssistantDescription:`Control smart plugs via Home Assistant`,environmentManagedLabel:`(Environment Managed)`,autoEnabledViaEnv:`Automatically enabled via environment variables`,urlFromEnvReadOnly:`Value set by HA_URL environment variable (read-only)`,tokenFromEnvReadOnly:`Value set by HA_TOKEN environment variable (read-only)`,mqttConnectedTo:`Connected to`,prometheusDescription:`Expose printer data in Prometheus format`,noSmartPlugsTitle:`No smart plugs configured`,noSmartPlugsDescription:`Add a Tasmota-based smart plug to track energy usage and automate power control.`,noProvidersTitle:`No providers configured`,noProvidersDescription:`Add a provider to receive alerts.`,noTemplatesAvailable:`No templates available. Restart the backend to seed default templates.`,apiPermissionView:`View printer status and queue`,apiPermissionEdit:`Add and remove items from print queue`,apiKeysEmptyTitle:`No API keys`,apiKeysEmptyDescription:`Create an API key to integrate with external services.`,noUsersFound:`No users found`,noGroupsFound:`No groups found`,noGroupsAvailable:`No groups available`,passwordsDoNotMatch:`Passwords do not match`,systemGroupWarning:`System group names cannot be changed`,authDisabledTitle:`Authentication is Disabled`,authDisabledFeature1:`Require login to access the system`,authDisabledFeature2:`Create multiple users with group-based permissions`,authDisabledFeature3:`Control access with 50+ granular permissions`,userHasCreated:`This user has created:`,userItemsQuestion:`What would you like to do with these items?`,deleteUserConfirm:`Are you sure you want to delete this user?`,actionCannotBeUndone:`This action cannot be undone.`,addFirstSmartPlug:`Add Your First Smart Plug`,providers:`Providers`,log:`Log`,testAll:`Test All`,testResults:`Test Results`,testPassedCount:`{{count}} passed`,testFailedCount:`{{count}} failed`,messageTemplates:`Message Templates`,messageTemplatesDescription:`Customize notification messages for each event.`,apiKeys:`API Keys`,apiKeysDescription:`Create API keys for external integrations and webhooks.`,createKey:`Create Key`,apiKeyCreated:`API Key Created Successfully`,apiKeyCopyWarning:`Copy this key now - it won't be shown again!`,useInApiBrowser:`Use in API Browser`,apiKeyQrButton:`QR code`,apiKeyQrTitle:`Scan to configure`,apiKeyQrCaption:`Scan with your mobile app to add this server and API key.`,apiKeyQrWarning:`Contains your secret API key — don't share or screenshot it where others can see.`,createNewApiKey:`Create New API Key`,keyName:`Key Name`,keyNamePlaceholder:`e.g., Home Assistant, OctoPrint`,readStatus:`Read Status`,readStatusDescription:`View printer status and queue`,manageQueue:`Manage Queue`,manageQueueDescription:`Add and remove items from print queue`,controlPrinter:`Control Printer`,controlPrinterDescription:`Pause, resume, and stop prints`,manageLibrary:`Manage Library`,manageLibraryDescription:`Upload, rename, and delete library files; import models from MakerWorld`,manageInventory:`Manage Inventory`,manageInventoryDescription:`Create, update, and delete spools and inventory records. Required for SpoolBuddy kiosks (NFC scan, scale readings, kiosk system commands).`,manageMaintenance:`Manage Maintenance`,manageMaintenanceDescription:`Log completed maintenance, reset counters, edit intervals, and manage the maintenance-type catalog. Suited to Home Assistant automations that record "I cleaned the nozzle" without granting broader printer control.`,manageArchives:`Manage Archives`,manageArchivesDescription:`Edit and delete print archives, including removing old prints. Does not include purging their statistics contribution. Suited to automations that prune the print history.`,manageProjects:`Manage Projects`,manageProjectsDescription:`Create, update, and delete projects, and add archives to them. Suited to automations that organize prints into projects.`,libraryBadge:`Library`,inventoryBadge:`Inventory`,maintenanceBadge:`Maintenance`,archivesBadge:`Archives`,projectsBadge:`Projects`,cloudAccess:`Allow cloud access`,cloudAccessDescription:`Read Bambu Cloud presets and filaments on your behalf. Requires you to be signed into Bambu Cloud.`,cloudBadge:`Cloud`,updateEnergyCost:`Update electricity price`,updateEnergyCostDescription:`Allow this key to POST a new per-kWh electricity price to /settings/electricity-price. Useful for Home Assistant dynamic-tariff automations (Tibber, Octopus, etc.). This is the only settings field writable via API key.`,energyCostBadge:`Energy`,legacyKey:`Legacy`,legacyKeyTooltip:`Created before per-user ownership; recreate to use cloud access`,unnamedKey:`Unnamed Key`,lastUsed:`Last used`,read:`Read`,control:`Control`,createFirstKey:`Create Your First Key`,webhookEndpoints:`Webhook Endpoints`,webhookApiKeyHint:`Use your API key in the X-API-Key header.`,webhook:{getAllStatus:`Get all printer status`,getSpecificStatus:`Get specific printer status`,addToQueue:`Add to print queue`,pausePrint:`Pause print`,resumePrint:`Resume print`,stopPrint:`Stop print`},apiBrowser:`API Browser`,apiBrowserDescription:`Explore and test all available API endpoints.`,apiKeyForTesting:`API Key for Testing`,apiKeyPlaceholder:`Paste your API key here to test authenticated endpoints...`,apiKeyHint:`This key will be sent as X-API-Key header with requests.`,deleteApiKeyTitle:`Delete API Key`,deleteApiKeyMessage:`Are you sure you want to delete this API key? Any integrations using this key will stop working.`,deleteKey:`Delete Key`,amsDisplayThresholds:`AMS Display Thresholds`,amsThresholdsDescription:`Configure color thresholds for AMS humidity and temperature indicators.`,humidity:`Humidity`,goodGreen:`Good (green)`,fairOrange:`Fair (orange)`,aboveFairBad:`Above fair threshold shows as red (bad)`,fairAlsoDryingThreshold:`This threshold is also used to trigger auto-drying when enabled`,temperature:`Temperature`,goodBlue:`Good (blue)`,aboveFairHot:`Above fair threshold shows as red (hot)`,historyRetention:`History Retention`,keepSensorHistory:`Keep sensor history for`,historyRetentionDescription:`Older humidity and temperature data will be automatically deleted`,defaultPrintOptions:`Default Print Options`,defaultPrintOptionsDescription:`Set default values for print options when starting new prints. These can be overridden per print in the print dialog.`,defaultBedLevelling:`Bed Levelling`,defaultBedLevellingDesc:`Auto-level bed before print`,defaultFlowCali:`Flow Calibration`,defaultFlowCaliDesc:`Calibrate extrusion flow`,defaultVibrationCali:`Vibration Calibration`,defaultVibrationCaliDesc:`Reduce ringing artifacts`,defaultLayerInspect:`First Layer Inspection`,defaultLayerInspectDesc:`AI inspection of first layer`,defaultTimelapse:`Timelapse`,defaultTimelapseDesc:`Record timelapse video`,defaultNozzleOffsetCali:`Nozzle Offset Calibration`,defaultNozzleOffsetCaliDesc:`Calibrate nozzle offsets between extruders`,tempFanPresetsTitle:`Temperature & Fan Presets`,tempFanPresetsDescription:`Customize the quick-select values shown in printer-card temperature and fan-speed popovers. The Off button is always shown.`,tempFanPresetsNozzle:`Nozzle temperature`,tempFanPresetsBed:`Bed temperature`,tempFanPresetsChamber:`Chamber temperature`,tempFanPresetsFan:`Fan speed`,tempFanPresetsReset:`Reset to defaults`,concurrentUploadsTitle:`Concurrent Uploads`,concurrentUploadsDescription:`How many printers the queue may send files to at the same time. Printers receive files slowly (a large print can take several minutes), and each one waits its turn — so on a bigger fleet, raising this is what stops the last printer in a batch from waiting out every transfer before it. Lower it if your network or Bambuddy host struggles with parallel transfers.`,concurrentUploadsLabel:`Printers uploaded to at once`,concurrentUploadsHelp:`1 sends to one printer at a time (the old behaviour). Default is 4.`,staggeredStart:`Staggered Start`,staggeredStartDescription:`Default group size and interval when staggering multi-printer batch starts. Can be overridden per batch in the print modal.`,preheatTitle:`Preheat & Heat Soak`,preheatDescription:`Heat the bed (and chamber, if supported) and hold at temperature before each queued print starts. Helpful for engineering filaments (PA, ABS) on printers without an active chamber heater — the bed warms the chamber by radiation while the soak timer runs. The bed target is read from the print file; chamber behaviour depends on printer model.`,preheatEnabled:`Enable preheat & soak`,preheatEnabledDesc:`When off, queued prints dispatch immediately. Each queue item can override per print.`,preheatFilamentTargetsLabel:`Per-filament chamber target (°C)`,preheatFilamentTargetsHint:`Bambuddy picks the highest target across the loaded AMS slots; PLA-only prints derive 0 and skip the chamber phase automatically.`,preheatFilamentTargetsReset:`Reset to defaults`,preheatFilamentTargetsDefaultRow:`Other / unmapped`,preheatMaxWait:`Max wait (seconds)`,preheatMaxWaitHelp:`Cap on the chamber warm-up phase before falling through.`,preheatSoak:`Soak (seconds)`,preheatSoakHelp:`Hold time after target reached or max-wait elapsed.`,preheatHardwareTitle:`Per-printer behaviour:`,preheatHardwareDetail:`H2C/H2D/H2D Pro/H2S/X2D/X1E actively heat the chamber via M141. X1C/P2S read chamber temp but rely on bed-radiation heating. P1S/P1P/A1/A1 Mini have no chamber sensor — only the soak timer applies.`,preheatPerItemDesc:`Heat the bed and chamber before this print starts. Defaults to the global Settings → Workflow toggle.`,preheatOverride_inherit:`Inherit`,preheatOverride_on:`On`,preheatOverride_off:`Off`,calibrationMode_off:`Off`,calibrationMode_on:`On`,calibrationMode_auto:`Auto`,preheatTargetOverride:`Chamber target override (°C, blank = filament default)`,plateClear:`Plate-Clear Confirmation`,requirePlateClear:`Require plate-clear confirmation`,requirePlateClearDescription:`When enabled, the scheduler waits for per-printer plate-clear confirmation before starting queued prints on printers with finished jobs. Disabling this also hides the plate status badge and the "Mark plate as cleared" button on printer cards.`,gcodeInjection:`G-code Injection`,gcodeInjectionDescription:`Configure custom G-code to inject at the start and/or end of prints for auto-print systems like Farmloop, SwapMod, AutoClear, and Printflow 3D. Snippets are configured per printer model and applied when "Inject G-code" is enabled on a queue item.`,gcodeInjectionNoPrinters:`No printers found. Add printers to configure G-code snippets.`,gcodeStartLabel:`Start G-code`,gcodeEndLabel:`End G-code`,gcodeStartPlaceholder:`G-code prepended before the print starts...`,gcodeEndPlaceholder:`G-code appended after the print ends...`,staggerGroupSize:`Group size`,staggerGroupSizeHelp:`Printers to start simultaneously per group`,staggerInterval:`Interval (minutes)`,staggerIntervalHelp:`Delay between each group starting`,queueDrying:`Queue Auto-Drying`,queueDryingDescription:`Automatically dry AMS filament when printer is idle between queued prints. Uses humidity threshold above to trigger drying.`,queueDryingEnabled:`Enable auto-drying`,queueDryingEnabledDescription:`Start AMS drying automatically when printer is idle and humidity is above threshold`,queueDryingBlock:`Wait for drying to complete`,queueDryingBlockDescription:`Block the print queue until drying finishes. When off, prints take priority over drying.`,ambientDryingEnabled:`Ambient drying`,ambientDryingEnabledDescription:`Automatically dry filament on idle printers when humidity exceeds threshold, even without queued prints.`,printDryingEnabled:`Continue drying while printing`,printDryingEnabledDescription:`Allow auto-drying to keep running during a print on supported hardware (H2D, H2C, H2S, P2S, H2D Pro, X2D, X1C, A2L on recent firmware). Drying temperature is automatically capped 5°C below the idle preset to protect spools.`,dryingPresets:`Drying Presets`,dryingPresetsDescription:`Temperature and duration per filament type. AMS 2 Pro uses lower temps, AMS-HT supports higher temps.`,dryingFilament:`Filament`,humidityThresholds:`Humidity Thresholds`,humidityThresholdsDescription:`Per-filament humidity trigger for auto-drying and alarms. Mixed loads in one AMS use the lowest threshold.`,humidityThresholdCol:`Threshold`,humidityThresholdDefault:`Default (unknown types)`,printModal:`Print Modal`,expandCustomMapping:`Expand custom mapping by default`,expandCustomMappingDescription:`When printing to multiple printers, show per-printer AMS mapping expanded`,authentication:`Authentication`,authEnabledDescription:`Your instance is secured with user authentication`,authDisabledDescription:`Enable to require login and manage user access`,authDisabledMessage:`Enable authentication to create user accounts, manage permissions, and secure your Bambuddy instance.`,enableAuthentication:`Enable Authentication`,currentUser:`Current User`,changePassword:`Change Password`,admin:`Admin`,users:`Users`,addUser:`Add User`,groups:`Groups`,addGroup:`Add Group`,system:`System`,noDescription:`No description`,userCount:`{{count}} users`,permissionCount:`{{count}} permissions`,createUser:`Create User`,username:`Username`,enterUsername:`Enter username`,password:`Password`,enterPassword:`Enter password`,passwordRequirements:`At least 8 characters, with one uppercase, one lowercase, one digit, and one special character.`,confirmPassword:`Confirm Password`,confirmPasswordPlaceholder:`Confirm password`,viewReleaseOnGitHub:`View release on GitHub`,turnAllPlugsOn:`Turn all plugs on`,turnAllPlugsOff:`Turn all plugs off`,clearNotificationLogs:`Clear Notification Logs`,clearLogsMessage:`This will permanently delete all notification logs older than 30 days. This action cannot be undone.`,clearLogs:`Clear Logs`,resetUiPreferences:`Reset UI Preferences`,resetUiPreferencesMessage:`This will reset all UI preferences to defaults: sidebar order, theme, dashboard layout, view modes, and sorting preferences. Your printers, archives, and server settings will NOT be affected. The page will reload after clearing.`,resetPreferences:`Reset Preferences`,deleteGroupTitle:`Delete Group`,deleteGroupMessage:`Are you sure you want to delete this group? Users in this group will lose these permissions.`,deleteGroup:`Delete Group`,disableAuthenticationTitle:`Disable Authentication`,disableAuthenticationMessage:`Are you sure you want to disable authentication? This will make your Bambuddy instance accessible without login. All users will remain in the database but authentication will be disabled.`,disableAuthentication:`Disable Authentication`,configureBambuddy:`Configure Bambuddy`,systemDefault:`System Default`,archiveSettings:`Archive Settings`,newWindow:`New Window`,embeddedOverlay:`Embedded Overlay`,preferredSlicer:`Preferred Slicer`,preferredSlicerDescription:`Slicer used for in-app slicing via the API sidecar`,openInSlicerLabel:`Open in Slicer`,openInSlicerInherit:`Same as API slicer`,openInSlicerDescription:`Desktop slicer used by the 'Open in Slicer' button. Leave on 'Same as API slicer' to inherit, or pick a different slicer to use locally.`,orcaslicerKnownIssuesWarning:`OrcaSlicer 2.3.2 / 2.4.0-dev have known CLI bugs that block slicing many Bambu-authored 3MFs — see upstream issues #12426 (segfault on painted multi-extruder files) and #13386 (parameter-range strict-validation reject). Bambu Studio is recommended until the upstream fixes land.`,useSlicerApi:`Use Slicer API`,useSlicerApiDescription:`When on, "Slice" actions open the in-app slicer modal and call the slicer-API sidecar. When off (default), they hand off to the desktop slicer via URI scheme.`,slicerCard:`Slicer`,orcaslicerApiUrl:`OrcaSlicer sidecar URL`,bambuStudioApiUrl:`Bambu Studio sidecar URL`,slicerStallTimeout:`Slicer stall timeout (minutes)`,slicerStallTimeoutDescription:`Give up on a slice after this long with no progress from the sidecar. Heavy models that keep reporting progress are never cut off, however long they take. Sidecars that do not report progress use this as a total time limit instead.`,slicerApiUrlDescription:`URL of the slicer-API sidecar container. Leave blank to use the SLICER_API_URL / BAMBU_STUDIO_API_URL env var defaults.`,slicerBundlesRemoved:{title:`Slicer Bundles (removed)`,description:`Printer Preset Bundle (.bbscfg) import was removed. BambuStudio's bundle export only includes user-customised presets, so the import never delivered standard processes / filaments and slicing fell back to embedded settings.`,alternatives:`Use Single Preset Import for individual customs, or sync via Bambu Cloud / Orca Cloud. Stock presets come from the slicer sidecar automatically.`,lookupOrder:`Slice-time preset lookup order: 1) Imported (local), 2) Orca Cloud, 3) Bambu Cloud, 4) Standard (sidecar fallback).`},externalCameras:`External Cameras`,costTracking:`Cost Tracking`,printsOnly:`Prints Only`,totalConsumption:`Total Consumption`,dataManagement:`Data Management`,storageUsage:`Storage Usage`,storageUsageDescription:`Breakdown of data usage by category`,storageUsageTotal:`Total`,storageUsageErrors:`Errors`,storageUsageOtherBreakdown:`Other (includes static assets, scripts, and configuration files)`,storageUsageSystem:`System`,storageUsageData:`Data`,storageUsageUnavailable:`Storage usage information unavailable`,clearNotificationLogsDescription:`Delete notification logs older than 30 days`,resetUiPreferencesDescription:`Reset sidebar order, theme, view modes, and layout preferences. Printers, archives, and settings are not affected.`,enableHomeAssistant:`Enable Home Assistant`,enableMqtt:`Enable MQTT`,useTls:`Use TLS`,enableMetricsEndpoint:`Enable Metrics Endpoint`,availableMetrics:`Available Metrics`,editUser:`Edit User`,deleteUserTitle:`Delete User`,groupName:`Group Name`,leaveEmptyForAnonymous:`Leave empty for anonymous`,leaveEmptyForNoAuth:`Leave empty for no authentication`,enterNewPassword:`Enter new password`,confirmNewPassword:`Confirm new password`,enterGroupName:`Enter group name`,enterDescriptionOptional:`Enter description (optional)`,enterCurrentPassword:`Enter current password`,enterNewPasswordMin6:`Enter new password (min 6 characters)`,toast:{keyCopied:`Key copied to clipboard`,copyFailed:`Failed to copy key`,keyAddedToBrowser:`Key added to API Browser`,clearLogsFailed:`Failed to clear logs`,uiPreferencesReset:`UI preferences reset. Refreshing...`,authDisabled:`Authentication disabled successfully`,authDisableFailed:`Failed to disable authentication`,apiKeyCreated:`API key created`,apiKeyDeleted:`API key deleted`,userCreated:`User created successfully`,userUpdated:`User updated successfully`,userDeleted:`User deleted successfully`,groupCreated:`Group created successfully`,groupUpdated:`Group updated successfully`,groupDeleted:`Group deleted successfully`,fillRequiredFields:`Please fill in all required fields`,passwordsDoNotMatch:`Passwords do not match`,passwordTooShort:`Password must be at least 8 characters`,passwordNeedsUppercase:`Password must contain at least one uppercase letter`,passwordNeedsLowercase:`Password must contain at least one lowercase letter`,passwordNeedsDigit:`Password must contain at least one digit`,passwordNeedsSpecial:`Password must contain at least one special character`,enterGroupName:`Please enter a group name`,settingsSaved:`Settings saved`,noPermissionUpdate:`You do not have permission to change settings`,cameraSettingsSaved:`Camera settings saved`,enterCameraUrl:`Please enter a camera URL`,passwordChanged:`Password changed successfully`,connectionFailed:`Connection failed`,testFailed:`Test failed`,cameraConnected:`Camera connected{{resolution}}`,cameraConnectedCoalesced:`Camera connected{{resolution}} (shared with a capture already running)`},testConnection:`Test Connection`,catalog:{spoolCatalog:`Spool Catalog`,spoolCatalogDescription:`Empty spool weights by brand/type. Used for automatic weight lookup when adding spools.`,searchCatalog:`Search catalog...`,addNewEntry:`Add New Entry`,namePlaceholder:`Name (e.g., Bambu Lab - Plastic)`,weight:`Weight`,type:`Type`,default:`Default`,custom:`Custom`,noMatch:`No entries match your search`,empty:`No entries in catalog`,deleteEntry:`Delete Entry`,deleteConfirm:`Are you sure you want to delete "{{name}}"?`,resetCatalog:`Reset Catalog`,resetConfirm:`Reset catalog to defaults? This will remove all custom entries.`,loadFailed:`Failed to load spool catalog`,nameWeightRequired:`Name and weight are required`,entryAdded:`Entry added`,addFailed:`Failed to add entry`,entryUpdated:`Entry updated`,updateFailed:`Failed to update entry`,entryDeleted:`Entry deleted`,deleteFailed:`Failed to delete entry`,resetSuccess:`Catalog reset to defaults`,resetFailed:`Failed to reset catalog`,exported:`Exported {{count}} entries`,imported:`Imported {{added}} entries ({{skipped}} skipped)`,importFailed:`Failed to import: invalid JSON format`,exportTooltip:`Export catalog to JSON`,importTooltip:`Import catalog from JSON`,resetTooltip:`Reset to defaults`,selectedCount:`{{count}} selected`,deleteSelected:`Delete Selected`,bulkDeleteConfirm:`Are you sure you want to delete {{count}} entries?`,bulkDeleted:`Deleted {{count}} entries`,bulkDeleteFailed:`Failed to delete entries`,material:`Material`,spoolWeight:`Spool Weight`,color:`Color`,updateSpoolWeight:`Update Spool Weight`,filamentUpdated:`Filament updated`,filamentUpdateFailed:`Failed to update filament`,filamentUpdateInvalid:`Invalid filament data`,keepExistingSpoolWeight:`Keep old weight for existing spools`,keepExistingSpoolWeightDesc:`Spools already created with this filament type retain the old tare weight. New spools use the updated value.`,applyToAllSpools:`Apply to all spools`,applyToAllSpoolsDesc:`All weight calculations for this filament type immediately use the new tare weight.`},colorCatalog:{title:`Color Catalog`,description:`Filament colors by manufacturer/material. Used for automatic color lookup when adding spools.`,searchColors:`Search colors...`,allManufacturers:`All manufacturers`,addNewColor:`Add New Color`,manufacturer:`Manufacturer`,colorName:`Color Name`,hex:`Hex`,materialOptional:`Material (optional)`,showing:`Showing {{filtered}} of {{total}} colors`,noMatch:`No colors match your search`,empty:`No colors in catalog`,deleteColor:`Delete Color`,deleteConfirm:`Are you sure you want to delete "{{name}}"?`,resetCatalog:`Reset Color Catalog`,resetConfirm:`Reset catalog to defaults? This will remove all custom colors.`,sync:`Sync`,starting:`Starting...`,syncTooltip:`Sync from FilamentColors.xyz (2000+ colors, may take a minute)`,loadFailed:`Failed to load color catalog`,fieldsRequired:`Manufacturer, color name, and hex color are required`,colorAdded:`Color added`,addFailed:`Failed to add color`,colorUpdated:`Color updated`,updateFailed:`Failed to update color`,colorDeleted:`Color deleted`,deleteFailed:`Failed to delete color`,resetSuccess:`Color catalog reset to defaults`,resetFailed:`Failed to reset catalog`,syncUpToDate:`Already up to date ({{count}} colors checked)`,syncComplete:`Added {{added}} new colors ({{skipped}} already existed)`,syncError:`Sync error`,syncFailed:`Failed to sync from FilamentColors.xyz`,exported:`Exported {{count}} colors`,imported:`Imported {{added}} colors ({{skipped}} skipped)`,importFailed:`Failed to import: invalid JSON format`,selectedCount:`{{count}} selected`,deleteSelected:`Delete Selected`,bulkDeleteConfirm:`Are you sure you want to delete {{count}} colors?`,bulkDeleted:`Deleted {{count}} colors`,bulkDeleteFailed:`Failed to delete colors`},dateFormat:`Date Format`,dateFormatUs:`US (MM/DD/YYYY)`,dateFormatEu:`EU (DD/MM/YYYY)`,dateFormatIso:`ISO (YYYY-MM-DD)`,timeFormat:`Time Format`,timeFormat12:`12-hour (3:30 PM)`,timeFormat24:`24-hour (15:30)`,defaultPrinter:`Default Printer`,defaultPrinterDescription:`Pre-select this printer for uploads, reprints, and other operations.`,slicerBambuStudio:`Bambu Studio`,slicerOrcaSlicer:`OrcaSlicer`,sidebarOrderDescription:`Use Sidebar to reorder items, reset visibility, and manage custom links.`,setDefault:`Set Default`,sidebarOrderSetDefaultHint:`Set default applies the current menu order to users who haven't customized theirs.`,sidebarDefaultSet:`Default menu order has been set.`,sidebarDefaultCleared:`Default menu order cleared.`,sidebarDefaultFailed:`Failed to set default menu order.`,reset:`Reset`,darkMode:`Dark Mode`,lightMode:`Light Mode`,active:`(active)`,background:`Background`,accent:`Accent`,style:`Style`,bgNeutral:`Neutral`,bgWarm:`Warm`,bgCool:`Cool`,bgOled:`OLED Black`,bgSlate:`Slate Blue`,bgForest:`Forest Green`,accentGreen:`Green`,accentTeal:`Teal`,accentBlue:`Blue`,accentOrange:`Orange`,accentPurple:`Purple`,accentRed:`Red`,styleClassic:`Classic`,styleGlow:`Glow`,styleVibrant:`Vibrant`,themeToggleHint:`Toggle between dark, light, and system mode using the icon in the sidebar.`,progressInTitle:`Print progress in tab`,progressInTitleDescription:`Show the active print's percentage and a progress ring in the browser tab.`,autoArchivePrints:`Auto-archive prints`,autoArchiveDescription:`Automatically save 3MF files when prints complete`,saveThumbnailsDescription:`Extract and save preview images from 3MF files`,captureFinishPhotoDescription:`Take a photo from printer camera when print completes. Bambuddy records a brief timelapse during the print so the photo can be sourced from the moment before the bed drops; the timelapse file is kept if you enabled timelapse for this print, otherwise it is deleted automatically after the photo is captured.`,finishPhotoRestorePlate:`Restore plate for finish photo`,finishPhotoRestorePlateDescription:`The printer drops the build plate about 100 mm when a print ends, leaving the finished print below the camera's framing. Bambuddy raises it back to just above the last printed layer, takes the photo, then lowers it again. Skipped when the print height is unknown or another job is queued.`,ffmpegNotInstalled:`ffmpeg not installed`,ffmpegRequired:`Camera capture requires ffmpeg. Install it via brew install ffmpeg (macOS) or apt install ffmpeg (Linux).`,camera:`Camera`,cameraViewMode:`Camera View Mode`,cameraOverlayDescription:`Camera opens in a resizable overlay on the main screen`,cameraWindowDescription:`Camera opens in a separate browser window`,externalCamerasDescription:`Configure external cameras to replace the built-in printer camera. Supports MJPEG streams, RTSP, HTTP snapshots, and USB cameras (V4L2). When enabled, the external camera is used for live view and finish photos.`,cameraPlaceholderUsb:`Device path (/dev/video0)`,cameraPlaceholderUrl:`Camera URL (rtsp://... or http://...)`,cameraTypeMjpeg:`MJPEG Stream`,cameraTypeRtsp:`RTSP Stream`,cameraTypeSnapshot:`HTTP Snapshot`,cameraTypeUsb:`USB Camera (V4L2)`,cameraSnapshotUrl:`Snapshot URL (optional)`,cameraSnapshotUrlPlaceholder:`http://192.168.1.61:1984/api/frame.jpeg?src=printer`,cameraSnapshotUrlHelp:`Single-frame URL used for notification thumbnails, finish photos, layer-timelapse frames, and plate detection. Timelapse and plate detection each require their own per-printer toggle — this URL is just the image source they pull from when active. Leave blank to capture from the live stream above. Useful for go2rtc (/api/frame.jpeg) and IP cameras with a dedicated snapshot endpoint.`,cameraRotation:`Rotation`,test:`Test`,connected:`Connected`,disconnected:`Disconnected`,currency:`Currency`,defaultFilamentCost:`Default filament cost (per kg)`,electricityCost:`Electricity cost per kWh`,energyDisplayMode:`Energy display mode`,energyModePrintDescription:`Dashboard shows sum of energy used during prints`,energyModeTotalDescription:`Dashboard shows lifetime energy from smart plugs`,fileManager:`File Manager`,createArchiveEntry:`Create Archive Entry When Printing`,createArchiveEntryDescription:`When printing from File Manager, optionally create an archive entry`,lowDiskSpaceWarning:`Low Disk Space Warning`,lowDiskSpaceDescription:`Show warning when free disk space falls below this threshold`,printerFirmware:`Printer Firmware`,checkFirmwareDescription:`Check for printer firmware updates from Bambu Lab`,bambuddySoftware:`Bambuddy Software`,autoCheckDescription:`Automatically check for new versions on startup`,checkNow:`Check now`,updateAvailableVersion:`Update available: v{{version}}`,releaseNotes:`Release Notes`,updateViaDocker:`Update via Docker Compose:`,updateViaHomeAssistant:`Updates are managed by the Home Assistant Supervisor. Open Settings → Add-ons → Bambuddy in Home Assistant to install the new version.`,updateViaWindowsInstaller:`Windows installations are updated by re-running the installer. Download the new version below — your data, settings and printers are preserved.`,downloadWindowsInstaller:`Download installer for v{{version}}`,installUpdate:`Install Update`,latestVersionRunning:`You're running the latest version`,failedToCheckUpdates:`Failed to check for updates: {{error}}`,backupRestore:`Backup & Restore`,backupRestoreDescription:`Export/import settings and configure GitHub backup`,goToBackup:`Go to Backup`,externalUrl:`External URL`,externalUrlDescription:`The external URL where Bambuddy is accessible. Used for notification images and external integrations.`,bambuddyUrl:`Bambuddy URL`,externalUrlHint:`Include protocol and port (e.g., http://192.168.1.100:8000)`,ftpRetry:`FTP Retry`,ftpRetryDescription:`Retry FTP operations when printer WiFi is unreliable. Applies to 3MF downloads, print uploads, timelapse downloads, and firmware updates.`,autoRetryDescription:`Automatically retry failed FTP operations`,retryAttempts:`Retry attempts`,retryDelay:`Retry delay`,connectionTimeout:`Connection timeout`,time_one:`{{count}} time`,time_other:`{{count}} times`,second_one:`{{count}} second`,second_other:`{{count}} seconds`,nSeconds:`{{count}} seconds`,increaseForWeakWifi:`Increase for printers with weak WiFi`,homeAssistant:`Home Assistant`,homeAssistantFullDescription:`Connect to Home Assistant to control smart plugs via HA's REST API. Supports switch, light, input_boolean, and script entities.`,homeAssistantUrl:`Home Assistant URL`,longLivedAccessToken:`Long-Lived Access Token`,haTokenHint:`Create a token in HA: Profile → Long-Lived Access Tokens → Create Token`,connectionSuccessful:`Connection Successful`,connectionFailed:`Connection Failed`,haConnectionSuccess:`Successfully connected to Home Assistant.`,haConnectionFailed:`Failed to connect to Home Assistant.`,mqttPublishing:`MQTT Publishing`,mqttDescription:`Publish BamBuddy events to an external MQTT broker for integration with Node-RED, Home Assistant, and other automation systems.`,mqttEnableDescription:`Publish events to external MQTT broker`,brokerHostname:`Broker hostname`,port:`Port`,usernameOptional:`Username (optional)`,passwordOptional:`Password (optional)`,topicPrefix:`Topic prefix`,topicPrefixHint:`Topics will be: {{prefix}}/printers//status, etc.`,prometheusMetrics:`Prometheus Metrics`,prometheusEndpointDescription:`Expose printer metrics at /api/v1/metrics for Prometheus/Grafana monitoring.`,bearerTokenOptional:`Bearer Token (optional)`,bearerTokenHint:`If set, requests must include Authorization: Bearer `,metricsConnectionStatus:`Connection status`,metricsPrinterState:`Printer state (idle/printing/etc)`,metricsPrintProgress:`Print progress 0-100%`,metricsBedTemp:`Bed temperature`,metricsNozzleTemp:`Nozzle temperature`,metricsPrintsTotal:`Total prints by result`,metricsMore:`...and more (layers, fans, queue, filament usage)`,smartPlugsDescription:`Connect smart plugs (Tasmota or Home Assistant) to automate power control and track energy usage for your printers.`,allOn:`All On`,allOff:`All Off`,addSmartPlug:`Add Smart Plug`,energySummary:`Energy Summary`,currentPower:`Current Power`,plugsOnline:`{{reachable}}/{{total}} plugs online`,today:`Today`,yesterday:`Yesterday`,total:`Total`,enablePlugsForSummary:`Enable plugs to see energy summary`,addNotificationProvider:`Add`,systemBadge:`(System)`,creating:`Creating...`,changing:`Changing...`,deleteUserAndItems:`Delete user AND their items`,deleteUserKeepItems:`Delete user, keep items (become ownerless)`,ok:`OK`,twoFa:{totpTitle:`Authenticator App (TOTP)`,totpDesc:`Use an authenticator app like Google Authenticator, Aegis or Authy.`,emailOtpTitle:`Email OTP`,emailOtpDesc:`Send a one-time code to {{email}} when you log in.`,emailOtpNoEmail:`Add an email address to your account to enable this method.`,addEmailFirst:`Your account has no email address. Ask an admin to add one before enabling Email OTP.`,setupTotp:`Set up Authenticator App`,setupAuthApp:`Set up Authenticator App`,setupInstructions:`Scan the QR code below with your authenticator app, then confirm with a code.`,manualEntry:`Can't scan? Enter this secret manually:`,scannedContinue:`I've scanned the code — continue`,enterCodeToConfirm:`Enter the 6-digit code from your authenticator app to confirm setup.`,activate:`Activate`,disableTotp:`Disable Authenticator`,disableConfirmHint:`Enter a valid TOTP code or a backup code to disable the authenticator.`,totpDisabled:`Authenticator app disabled.`,emailOtpEnabled:`Email OTP enabled.`,emailOtpDisabled:`Email OTP disabled.`,smtpRequired:`Please configure and test SMTP settings first.`,invalidCode:`Invalid code. Please try again.`,enableEmailOtp:`Enable Email OTP`,disableEmailOtp:`Disable Email OTP`,emailSetupEnterCode:`A verification code has been sent to your email address. Enter it below to confirm you own this inbox.`,verifyAndEnable:`Verify & Enable`,emailDisablePasswordHint:`Enter your account password to confirm disabling email OTP.`,passwordPlaceholder:`Enter your password`,backupCodesTitle:`Save your backup codes`,backupCodesWarning:`Save these codes somewhere safe. Each code can only be used once and they will not be shown again.`,backupCodesRemaining:`{{count}} backup codes remaining`,savedCodes:`I've saved my codes`,regenBackup:`Regenerate Backup Codes`,regenBackupHint:`Enter your current TOTP code to generate 10 new backup codes. All existing backup codes will be invalidated.`,newBackupCodes:`New backup codes`,linkedAccounts:`Linked SSO Accounts`,linkedAccountsDesc:`These external identity providers are linked to your account.`,oidcUnlinked:`Account unlinked.`},sessionPolicy:{title:`Session Policy`,description:`Maximum session lifetime for new user logins. Already-issued tokens keep their original expiry.`,preset24h:`24 hours`,preset7d:`7 days`,preset30d:`30 days`,customHoursLabel:`Custom session lifetime in hours`,hoursSuffix:`hours`,warning:`Longer sessions reduce automatic logout protection. Recommended only for trusted single-user deployments.`},oidc:{title:`SSO / OIDC Providers`,desc:`Configure OpenID Connect providers to allow single sign-on via external identity providers.`,addProvider:`Add Provider`,newProvider:`New Provider`,empty:`No OIDC providers configured yet.`,created:`Provider created.`,updated:`Provider updated.`,deleted:`Provider deleted.`,refreshIcon:`Refresh icon`,removeIcon:`Remove icon`,iconRefreshed:`Icon refreshed.`,iconRemoved:`Icon removed.`,iconFetchFailed:`Icon could not be fetched from the provider URL.`,deleteTitle:`Delete Provider`,deleteMessage:`Delete "{{name}}"? All linked user accounts will be disconnected.`,form:{name:`Display Name`,issuerUrl:`Issuer URL`,clientId:`Client ID`,clientSecret:`Client Secret`,scopes:`Scopes`,iconUrl:`Icon URL (optional)`,enabled:`Enabled`,autoCreate:`Auto-create users`,autoCreateDesc:`Automatically create a local account on first login.`,autoLink:`Auto-link existing accounts`,autoLinkDesc:`Link existing local accounts by matching email on first login.`,secretHint:`leave blank to keep current`,secretPlaceholder:`new secret`,emailClaim:`Email Claim`,emailClaimDesc:`JWT claim used as email identity. Use 'preferred_username' or 'upn' for Azure Entra ID (which does not send email_verified). Only use trusted claim names.`,emailClaimPlaceholder:`email`,emailClaimCustomClaimAutoLinkWarning:`Custom claims are safe for auto-link only when the value is tenant-administered (e.g. Azure Entra ID upn / preferred_username). Do not enable auto-link if your IdP allows users to self-assert this claim.`,requireEmailVerified:`Require email verified`,requireEmailVerifiedDesc:`Only accept the email claim when the provider marks it as verified.`,requireEmailVerifiedWarning:`Warning: email will be accepted even without verification. Use only with trusted providers.`,requireEmailVerifiedAutoLink:`Disable auto-link first to change this setting.`,defaultGroup:`Default Group`,defaultGroupDesc:`Group assigned to auto-created users. Falls back to Viewers if not set.`,defaultGroupViewersFallback:`Viewers (default)`,autologin:`Autologin`,autologinDesc:`Redirect unauthenticated visitors straight to this provider. Only one provider can carry this flag.`}},encryption:{title:`MFA Encryption Status`,enabledFromEnv:`At-rest encryption enabled (key from MFA_ENCRYPTION_KEY environment variable)`,enabledFromFile:`At-rest encryption enabled (key loaded from data directory)`,enabledGenerated:`At-rest encryption enabled with auto-generated key`,notConfigured:`At-rest encryption not configured`,notConfiguredDesc:`TOTP secrets and OIDC client_secrets are stored in plaintext. Set MFA_ENCRYPTION_KEY or restart Bambuddy with a writable data directory to auto-generate one.`,allEncrypted:`All MFA secrets are encrypted at rest.`,legacyRowsLabel:`Legacy plaintext rows`,encryptedRowsLabel:`Encrypted rows`,legacyRowsWarning:`{{count}} legacy plaintext row(s) detected. Re-save the OIDC provider or re-enroll the user’s authenticator app to migrate to encrypted storage.`,backupHint:`The auto-generated key is stored at DATA_DIR/.mfa_encryption_key and is included in local backup ZIPs. Keep your backups secure or set MFA_ENCRYPTION_KEY explicitly.`,decryptionBrokenTitle:`Encryption key missing`,decryptionBrokenError:`{{count}} encrypted record(s) cannot be decrypted because the encryption key is no longer available. Restore the previous MFA_ENCRYPTION_KEY or DATA_DIR/.mfa_encryption_key to recover.`,migrationErrorWarning:`{{count}} legacy row(s) failed to re-encrypt at startup. Check server logs and restart Bambuddy to retry.`},pipelineLimits:{title:`Slicer Pipeline limits`,maxCopiesLabel:`Max copies per run`,maxCopiesDesc:`Upper bound on the copies operators can request when running a pipeline. Server-side hard cap is 1000.`},pipelines:{title:`Slicer Pipelines`,subtitle:`Reusable preset bundles (printer + process + filaments + bed type). Save one from the Slice dialog and apply it with a single click on the next file.`,loading:`Loading pipelines…`,loadError:`Could not load pipelines.`,confirmDelete:`Delete this pipeline? This cannot be undone.`,staleWarning:`One or more referenced presets no longer exist. Re-save this pipeline from the Slice dialog to fix.`,empty:{title:`No pipelines yet.`,howto:`Open the Slice dialog for any file, pick your printer / process / filaments / bed type, then click "Save as pipeline". Your saved pipelines will appear here.`},field:{name:`Pipeline name`,description:`Description`,targetPrinter:`Target printer`,noTarget:`— No target —`,targetKind:`Target type`,targetKindSpecific:`Specific printer`,targetKindClass:`Printer class`,targetModelClass:`Printer model`,fanoutStrategy:`Fanout strategy`,fanout:{max_parallel:`Max parallel — distribute across any idle matching printer`,round_robin:`Round robin — cycle through eligible printers`,fill_one_first:`Fill one first — pin all copies to one printer`},fanoutShort:{max_parallel:`parallel`,round_robin:`round robin`,fill_one_first:`fill one first`}},action:{save:`Save`,cancel:`Cancel`,rename:`Rename`,delete:`Delete`},slot:{printer:`Printer`,process:`Process`,filament:`Filament`,filamentN:`Filament {{n}}`,filamentAll:`All {{n}} slots`,bed:`Bed`},group:{profiles:`Profiles`,filaments:`Filaments`},searchPlaceholder:`Search pipelines…`,filterTargetType:`Filter by target type`,filterTarget:`Filter by target`,filter:{all:`All targets`,noTarget:`No target set`,count:`{{shown}} / {{total}}`,noMatches:`No pipelines match the current filters.`},toast:{saved:`Pipeline saved`,saveFailed:`Save failed`,deleted:`Pipeline deleted`,deleteFailed:`Delete failed`},noTargetHint:`Set a target printer to run this`,noTargetWarning:`Set a target printer before running this pipeline.`,runs:{lastRun:`Last run`,status:{queued:`queued`,slicing:`slicing`,dispatching:`dispatching`,in_progress:`printing`,completed:`completed`,failed:`failed`,partial_failure:`partial failure`,cancelled:`cancelled`}}}},notification:{printStarted:{title:`Print Started`,body:`{{printer}}: {{filename}} has started printing`},printCompleted:{title:`Print Completed`,body:`{{printer}}: {{filename}} completed successfully`},printFailed:{title:`Print Failed`,body:`{{printer}}: {{filename}} has failed`},printStopped:{title:`Print Stopped`,body:`{{printer}}: {{filename}} was stopped`},printProgress:{title:`Print Progress`,body:`{{printer}}: {{filename}} is {{percent}}% complete`},printerOffline:{title:`Printer Offline`,body:`{{printer}} is offline`},printerError:{title:`Printer Error`,body:`{{printer}}: {{error}}`},filamentLow:{title:`Low Filament`,body:`{{printer}}: Filament is running low`},maintenanceDue:{title:`Maintenance Due`,body:`{{printer}}: {{items}} need attention`}},errors:{generic:`Something went wrong`,networkError:`Network error. Please check your connection.`,notFound:`Not found`,unauthorized:`Unauthorized`,serverError:`Server error`,validationError:`Please check your input`,printerConnectionFailed:`Failed to connect to printer`,saveFailed:`Failed to save changes`,deleteFailed:`Failed to delete`,loadFailed:`Failed to load data`},hmsErrors:{title:`Errors - {{name}}`,noErrors:`No errors`,viewOnWiki:`View on Bambu Lab Wiki`,mqttVerifyFailedRemedy:`Enable Developer Mode on the printer, restart the printer, then start the job again.`,unknownCode:`Unknown HMS code — see the Bambu Lab wiki for details.`,clearInstructions:`Clear errors on the printer to dismiss them here.`,clearErrors:`Clear Errors`,clearSuccess:`HMS errors cleared`,clearFailed:`Failed to clear HMS errors`,actionSuccess:`Action sent to printer`,actionFailed:`Failed to send action`,runoutExpectedSlot:`Filament ran out in {{ranOut}}. The printer is now waiting for compatible filament in {{expected}}. Insert a spool into {{expected}}, then select Retry.`,runoutExpectedSlotOnly:`The printer is waiting for compatible filament in {{expected}}. Insert a spool there, then select Retry.`,runoutSlotUnknown:`Filament ran out and the print is paused. Bambuddy could not determine which slot the printer now expects — check the printer screen for the requested slot.`,actions:{RESUME_PRINTING:`Resume Printing`,RESUME_PRINTING_DEFECTS:`Resume (defects acceptable)`,RESUME_PRINTING_PROBELM_SOLVED:`Resume (problem solved)`,STOP_PRINTING:`Stop Printing`,CHECK_ASSISTANT:`Check Assistant`,FILAMENT_EXTRUDED:`Filament Extruded, Continue`,RETRY_FILAMENT_EXTRUDED:`Not Extruded Yet, Retry`,CONTINUE:`Finished, Continue`,LOAD_VIRTUAL_TRAY:`Load Filament`,OK_BUTTON:`OK`,FILAMENT_LOAD_RESUME:`Filament Loaded, Resume`,JUMP_TO_LIVEVIEW:`View Liveview`,NO_REMINDER_NEXT_TIME:`No Reminder Next Time`,REFRESH_NOZZLE:`Recheck`,IGNORE_NO_REMINDER_NEXT_TIME:`Ignore. Don't Remind Next Time`,IGNORE_RESUME:`Ignore this and Resume`,PROBLEM_SOLVED_RESUME:`Problem Solved and Resume`,TURN_OFF_FIRE_ALARM:`Got it, Turn off the Fire Alarm.`,RETRY_PROBLEM_SOLVED:`Retry (problem solved)`,CANCLE:`Cancle`,STOP_DRYING:`Stop Drying`,PROCEED:`Proceed`,OK_JUMP_RACK:`OK`,ABORT:`Abort`,DISABLE_PURIFICATION:`Disable Purification for This Print`,DONT_REMIND_NEXT_TIME:`Don't Remind Me`,DBL_CHECK_CANCEL:`Cancel`,DBL_CHECK_DONE:`Done`,DBL_CHECK_RETRY:`Retry`,DBL_CHECK_RESUME:`Resume`,DBL_CHECK_OK:`Confirm`,REMOVE_CLOSE_BTN:`Close`}},mqttDebug:{title:`MQTT Debug Log`,searchPlaceholder:`Search topic or payload...`,noMessages:`No messages logged yet`,startLoggingHint:`Click "Start Logging" to begin capturing MQTT messages`,noMessagesMatch:`No messages match your filter`,adjustFilterHint:`Try adjusting your search or filter criteria`,incoming:`Incoming`,outgoing:`Outgoing`,loggingStopped:`Logging stopped`,loggingActive:`Logging active - messages will auto-refresh`,startLogging:`Start Logging`,stopLogging:`Stop Logging`,clearLog:`Clear Log`,topic:`Topic`,timestamp:`Timestamp`,direction:`Direction`,all:`All`},printerFiles:{title:`File Manager`,storageUsed:`Used:`,storageFree:`Free:`,filterPlaceholder:`Filter files...`,deleteButton:`Delete`,deleteFiles:`Delete {{count}} Files`,deleteFileConfirm:`Delete "{{name}}"? This cannot be undone.`,deleteFilesConfirm:`Delete {{count}} selected files? This cannot be undone.`,noFiles:`No files on printer`,loadingFiles:`Loading files...`,failedToLoad:`Failed to load files`,toast:{filesDeleted:`Deleted {{count}} file(s)`,deleteFailed:`Delete failed: {{error}}`}},confirm:{delete:`Are you sure you want to delete this?`,unsavedChanges:`You have unsaved changes. Are you sure you want to leave?`,clearQueue:`Are you sure you want to clear the queue?`},login:{title:`Bambuddy Login`,subtitle:`Sign in to your account`,username:`Username`,usernamePlaceholder:`Enter your username`,usernameOrEmail:`Username or Email`,usernameOrEmailPlaceholder:`Username or @ Email`,password:`Password`,passwordPlaceholder:`Enter your password`,signIn:`Sign in`,signingIn:`Logging in...`,rememberMe:`Remember Me`,forgotPassword:`Forgot your password?`,autologinFailed:`Automatic SSO sign-in failed. Pick a provider below to continue.`,localDisabledNotice:`Local sign-in is disabled. Use one of the SSO providers below.`,loginSuccess:`Logged in successfully`,loginFailed:`Login failed`,enterCredentials:`Please enter username and password`,enterEmail:`Please enter your email address`,oidcLoginFailed:`OIDC login failed`,oidcErrors:{providerError:`The identity provider returned an error`,missingParameters:`OIDC callback is missing required parameters`,invalidState:`OIDC state is invalid or has already been used`,stateExpired:`OIDC login session expired — please try again`,providerNotFound:`OIDC provider not found`,discoveryFailed:`Failed to fetch OIDC discovery document`,invalidDiscovery:`OIDC discovery document is invalid`,networkError:`Network error during OIDC token exchange`,badResponse:`Unexpected response during OIDC token exchange`,noIdToken:`OIDC provider did not return an ID token`,validationFailed:`OIDC token validation failed`,nonceMismatch:`OIDC nonce mismatch — possible replay attack`,missingSubClaim:`OIDC token is missing the sub claim`,noLinkedAccount:`No local account is linked to this OIDC identity`,accountInactive:`Your account is inactive`,userResolutionFailed:`Failed to resolve your account`,internalError:`An internal error occurred during OIDC login`,tokenExchangeFailed:`OIDC token exchange failed`},forgotPasswordTitle:`Forgot Password`,forgotPasswordMessage:`If you've forgotten your password, please contact your system administrator to reset it.`,forgotPasswordEmailMessage:`Enter your email address and we'll send you a new password.`,emailAddress:`Email Address`,emailPlaceholder:`your.email@example.com`,cancel:`Cancel`,sending:`Sending...`,sendResetEmail:`Send Reset Email`,howToReset:`How to reset your password:`,resetStep1:`Contact your Bambuddy administrator`,resetStep2:`Ask them to reset your password in User Management`,resetStep3:`They can set a new temporary password for you`,resetStep4:`Log in with the new password and change it in Settings`,gotIt:`Got it`,resetPassword:{title:`Set New Password`,subtitle:`Enter and confirm your new password below.`,newPassword:`New Password`,newPasswordPlaceholder:`At least 8 characters`,confirmPassword:`Confirm Password`,confirmPasswordPlaceholder:`Repeat new password`,saving:`Saving…`,submit:`Set New Password`,backToLogin:`Back to login`,passwordsDoNotMatch:`Passwords do not match`,passwordTooShort:`Password must be at least 8 characters`,resetFailed:`Password reset failed. The link may have expired.`},twoFA:{title:`Two-Factor Authentication`,subtitle:`Your account is protected with 2FA. Enter the verification code below.`,methodAuthenticator:`Authenticator App`,methodEmail:`Email Code`,methodBackup:`Backup Code`,instructionsTotp:`Open your authenticator app and enter the 6-digit code for Bambuddy.`,instructionsEmail:`A 6-digit code has been sent to your email address. It expires in 10 minutes.`,instructionsEmailNotSent:`Click the button below to receive a verification code via email.`,instructionsBackup:`Enter one of your 8-character backup recovery codes. Each code can only be used once.`,sendCodeButton:`Send Code via Email`,sendingCode:`Sending...`,resendCode:`Resend code`,codeLabel:`Verification Code`,backupCodeLabel:`Backup Code`,codePlaceholder:`000000`,backupCodePlaceholder:`XXXXXXXX`,verifyButton:`Verify`,verifyingButton:`Verifying...`,backToLogin:`← Back to login`,orContinueWith:`or continue with`,signInWith:`Sign in with {{provider}}`,enterCode:`Please enter the verification code`,sendCodeFailed:`Failed to send verification code`,invalidCode:`Invalid code. Please try again.`}},setup:{title:`Bambuddy Setup`,subtitle:`Configure authentication for your Bambuddy instance`,enableAuth:`Enable Authentication`,adminAccount:`Admin Account`,adminAccountDesc:`If admin users already exist, authentication will be enabled using the existing admin accounts. Leave the fields below empty to use existing admins, or enter new credentials to create a new admin user.`,adminUsername:`Admin Username`,adminPassword:`Admin Password`,optionalIfAdminExists:`(optional if admin users exist)`,adminUsernamePlaceholder:`Enter admin username (optional)`,adminPasswordPlaceholder:`Enter admin password (optional)`,confirmPassword:`Confirm Password`,confirmPasswordPlaceholder:`Confirm admin password`,settingUp:`Setting up...`,completeSetup:`Complete Setup`,toast:{authEnabledAdminCreated:`Authentication enabled and admin user created`,authEnabledExistingAdmins:`Authentication enabled using existing admin users`,setupCompleted:`Setup completed`,enterBothCredentials:`Please enter both admin username and password, or leave both empty to use existing admin users`,passwordsDoNotMatch:`Passwords do not match`,passwordTooShort:`Password must be at least 6 characters`}},changePassword:{title:`Change Password`,currentPassword:`Current Password`,currentPasswordPlaceholder:`Enter current password`,newPassword:`New Password`,newPasswordPlaceholder:`Enter new password (min 6 characters)`,confirmPassword:`Confirm New Password`,confirmPasswordPlaceholder:`Confirm new password`,passwordsDoNotMatch:`Passwords do not match`,passwordTooShort:`Password must be at least 6 characters`,changing:`Changing...`,success:`Password changed successfully`,failed:`Failed to change password`},plateAlert:{title:`Print Paused!`,message:`Objects detected on build plate. The print has been automatically paused. Please clear the plate and resume the print.`,understand:`I Understand`},camera:{title:`Camera View`,invalidPrinterId:`Invalid printer ID`,live:`Live`,snapshot:`Snapshot`,restartStream:`Restart stream`,refreshSnapshot:`Refresh snapshot`,fullscreen:`Fullscreen`,exitFullscreen:`Exit fullscreen`,connectingToCamera:`Connecting to camera...`,capturingSnapshot:`Capturing snapshot...`,connectionLost:`Connection lost`,connectionFailed:`Camera connection failed`,reconnecting:`Reconnecting in {{countdown}}s... (attempt {{attempt}}/{{max}})`,reconnectNow:`Reconnect now`,cameraUnavailable:`Camera unavailable`,cameraUnavailableDesc:`Make sure the printer is powered on and connected.`,noCamera:`No camera available`,retry:`Retry`,cameraStream:`Camera stream`,zoomOut:`Zoom out`,zoomIn:`Zoom in`,resetZoom:`Reset zoom`,recording:`Recording`,startRecording:`Start Recording`,stopRecording:`Stop Recording`,chamberLight:`Toggle chamber light`,unavailable:`Camera unavailable`,diagnose:{button:`Diagnose`,modalTitle:`Camera diagnostic`,running:`Running diagnostic...`,runFailed:`Diagnostic could not run: {{error}}`,retry:`Run again`,stage:{tcp_reachable:`Network reachability`,first_frame:`Frame capture`,live_stream_active:`Live stream active`},summary:{all_ok:`Camera is working. The diagnostic completed all stages successfully.`,live_stream_active_healthy:`Camera is currently streaming with recent frames — no test needed.`,printer_unreachable:`Printer is not reachable. Check the IP address, network connection, and that the printer is powered on.`,camera_port_closed:`Printer is reachable but the camera port is closed. Make sure LAN-only mode and Developer Mode are enabled in the printer settings.`,no_frame:`Connected to the camera but no frames were received. Try again, or check that the camera is enabled in the printer settings.`,unknown_failure:`Camera diagnostic failed for an unknown reason. Check the support log for details.`},meta:{protocol:`Protocol`,port:`Port`,profile:`Profile`}}},groups:{title:`Group Management`,subtitle:`Manage permission groups for access control`,backToSettings:`Back to Settings`,createGroup:`Create Group`,noPermission:`You do not have permission to access this page.`,system:`System`,noDescription:`No description`,usersCount:`{{count}} users`,permissionsCount:`{{count}} permissions`,edit:`Edit`,delete:`Delete`,toast:{created:`Group created successfully`,updated:`Group updated successfully`,deleted:`Group deleted successfully`,enterGroupName:`Please enter a group name`},modal:{editGroup:`Edit Group`,createGroup:`Create Group`,cancel:`Cancel`,saving:`Saving...`,creating:`Creating...`,saveChanges:`Save Changes`},form:{groupName:`Group Name`,groupNamePlaceholder:`Enter group name`,systemGroupWarning:`System group names cannot be changed`,description:`Description`,descriptionPlaceholder:`Enter description (optional)`,permissions:`Permissions ({{count}} selected)`},deleteModal:{title:`Delete Group`,message:`Are you sure you want to delete this group? Users in this group will lose these permissions.`,confirm:`Delete Group`},editor:{title:`Edit Group`,createTitle:`Create Group`,search:`Search permissions...`,selectAll:`Select All`,clearAll:`Clear All`,permissionsSelected:`{{count}} selected`,noResults:`No permissions match your search`,websocketHint:`Required for live updates. Without it, the interface falls back to periodic polling.`}},users:{title:`User Management`,subtitle:`Manage users and their access to your Bambuddy instance`,backToSettings:`Back to Settings`,createUser:`Create User`,noPermission:`You do not have permission to access this page.`,admin:`Admin`,noGroups:`No groups`,active:`Active`,inactive:`Inactive`,edit:`Edit`,delete:`Delete`,system:`System`,noGroupsAvailable:`No groups available`,table:{username:`Username`,groups:`Groups`,status:`Status`,actions:`Actions`},toast:{created:`User created successfully`,updated:`User updated successfully`,deleted:`User deleted successfully`,fillRequired:`Please fill in all required fields`,passwordsDoNotMatch:`Passwords do not match`,passwordTooShort:`Password must be at least 6 characters`,ldapProvisioned:`Provisioned LDAP user "{{username}}"`},modal:{createUser:`Create User`,editUser:`Edit User`,cancel:`Cancel`,creating:`Creating...`,saving:`Saving...`,saveChanges:`Save Changes`,advancedAuthSubtitle:`with Advanced Authentication`,tabsAriaLabel:`User source`,localTab:`Local`,ldapTab:`LDAP`,ldapSearchLabel:`Search directory`,ldapSearchPlaceholder:`Type a username, name, or email...`,ldapMinChars:`Type at least 2 characters to search`,ldapTypeToSearch:`Start typing to search the LDAP directory`,ldapSearching:`Searching directory...`,ldapNoResults:`No matching users in the directory`,ldapSearchError:`Directory search failed. Check the LDAP server status.`,ldapAlreadyProvisioned:`Already provisioned`,ldapSelectedLabel:`Selected`,ldapProvision:`Provision user`,ldapProvisioning:`Provisioning...`,ldapErrorProvision:`Provisioning failed. Check the LDAP server status and try again.`},form:{username:`Username`,usernamePlaceholder:`Enter username`,email:`Email`,emailPlaceholder:`user@example.com`,password:`Password`,passwordPlaceholder:`Enter password`,confirmPassword:`Confirm Password`,confirmPasswordPlaceholder:`Confirm password`,newPasswordPlaceholder:`Enter new password`,confirmNewPasswordPlaceholder:`Confirm new password`,leaveBlankToKeep:`leave blank to keep current`,groups:`Groups`,optional:`optional`,autoGeneratedPassword:`A secure password will be automatically generated and emailed to the user.`,passwordManagedByAdvancedAuth:`Password is managed by Advanced Authentication. Use "Reset Password" to send a new password to the user via email.`,resetPassword:`Reset Password`,resettingPassword:`Resetting Password...`},deleteModal:{title:`Delete User`,message:`Are you sure you want to delete this user? This action cannot be undone.`,confirm:`Delete User`}},streamOverlay:{title:`Stream Overlay`,invalidPrinterId:`Invalid printer ID`,cameraStream:`Camera stream`,progress:`Progress`,eta:`ETA`,printerIdle:`Printer is idle`,printerOffline:`Printer offline`,status:{printing:`Printing`,paused:`Paused`,finished:`Finished`,failed:`Failed`,idle:`Idle`,unknown:`Unknown`}},profiles:{title:`Profiles`,subtitle:`Manage your slicer presets and pressure advance calibrations`,tabs:{bambuCloud:`Bambu Cloud`,orcaCloud:`Orca Cloud`,local:`Local Profiles`,kprofiles:`K-Profiles`},orcaCloud:{connectedAs:`Connected as`,connectedShort:`Connected to Orca Cloud`,logout:`Disconnect`,noLogoutPermission:`You do not have permission to disconnect`,noConnectPermission:`You do not have permission to connect to Orca Cloud`,retry:`Retry`,connectButton:`Connect Orca Cloud`,connect:{title:`Connect to Orca Cloud`,description:`Sign in to your Orca Cloud account to sync your slicer profiles into Bambuddy.`},device:{title:`Approve Bambuddy in Orca Cloud`,instruction:`Open Orca Cloud and approve this code. Bambuddy connects automatically once you approve.`,codeLabel:`Your pairing code`,openButton:`Open Orca Cloud approval page`,manualHint:`Or go to {{url}} and enter the code above.`,waiting:`Waiting for you to approve…`,cancel:`Cancel`},profiles:{title:`Your Orca Cloud profiles ({{count}})`,refresh:`Refresh`,empty:`No profiles found in your Orca Cloud account yet.`},toast:{disconnected:`Disconnected from Orca Cloud`},errors:{startFailed:`Could not start Orca Cloud pairing.`,denied:`The pairing was denied in Orca Cloud.`,expired:`The pairing code expired. Click Connect to try again.`,pollFailed:`Lost the connection while waiting for approval. Please try again.`}},localProfiles:{title:`Local Profiles`,subtitle:`Import and manage slicer presets from OrcaSlicer`,import:`Import Profiles`,importDesc:`Drop .bbscfg, .bbsflmt, .orca_filament, .zip, or .json files here`,importing:`Importing...`,search:`Search local presets...`,noPresets:`No local presets yet`,noSearchResults:`No presets match your search`,badge:`Local`,edit:`Edit`,delete:`Delete`,cancel:`Cancel`,deleteConfirmTitle:`Delete Preset`,deleteConfirm:`Are you sure you want to delete this preset? This cannot be undone.`,source:`Source`,inheritsFrom:`Inherits`,filamentType:`Type`,vendor:`Vendor`,compatiblePrinters:`Printers`,nozzleTemp:`Nozzle Temp`,cost:`Cost`,density:`Density`,pressureAdvance:`Pressure Advance`,filament:`Filament`,process:`Process`,printer:`Printer`,toast:{importSuccess:`{{count}} preset(s) imported`,importSkipped:`{{count}} preset(s) skipped (duplicates)`,importError:`{{count}} error(s) during import`,deleted:`Preset deleted`,updated:`Preset updated`}},connectedAs:`Connected as`,signInExpiredTitle:`Bambu Cloud sign-in expired`,signInExpiredBody:`Bambu Lab no longer accepts the stored token. Sign in again to restore cloud profiles, MakerWorld imports and firmware checks.`,logout:`Logout`,noLogoutPermission:`You do not have permission to logout`,failedToLoad:`Failed to load profiles`,retry:`Retry`,time:{justNow:`Just now`,minsAgo:`{{count}}m ago`,hoursAgo:`{{count}}h ago`,daysAgo:`{{count}}d ago`},toast:{loggedOut:`Logged out`},login:{title:`Connect to Bambu Cloud`,subtitle:`Sync your slicer presets across devices`,email:`Email`,password:`Password`,region:`Region`,regionGlobal:`Global`,regionChina:`China`,verificationCode:`Verification Code`,totpCode:`Authenticator Code`,checkEmail:`Check your email ({{email}}) for a 6-digit code`,enterTotpHint:`Enter the 6-digit code from your authenticator app`,accessToken:`Access Token`,accessTokenHint:`Paste your Bambu Cloud access token. China-region accounts must use this path (phone-bound — email login unavailable). See the wiki for how to retrieve the token from MakerWorld cookies.`,back:`Back`,loginButton:`Login`,verifyButton:`Verify`,setTokenButton:`Set Token`,useToken:`Use access token instead`,useEmail:`Login with email instead`,toast:{loggedIn:`Logged in successfully`,codeSent:`Verification code sent to your email`,enterTotp:`Enter code from your authenticator app`,tokenSet:`Token set successfully`}},presets:{myPreset:`My preset (editable)`,duplicate:`Duplicate`,editable:`Editable`,failedToLoadDetails:`Failed to load preset details`,deleteConfirm:`Delete this preset?`,deleteWarning:`This will permanently delete "{{name}}" from Bambu Cloud. This cannot be undone.`,noDuplicatePermission:`You do not have permission to duplicate presets`,noEditPermission:`You do not have permission to edit presets`,noDeletePermission:`You do not have permission to delete presets`,types:{filament:`Filament preset`,printer:`Printer preset`,process:`Process preset`},toast:{deleted:`Preset deleted`,created:`Preset created`,updated:`Preset updated`,duplicated:`Preset duplicated`,fieldAdded:`Field "{{key}}" added`,exported:`Preset exported`},baseLabel:`Base: {{name}}`,currentLabel:`Current: {{name}}`,newPreset:`New Preset`,editPreset:`Edit Preset`,duplicatePreset:`Duplicate Preset`,createNewPreset:`Create New Preset`,customizeSettings:`Customize settings for your new preset`,compareWithBase:`Compare with base preset`,compare:`Compare`,basePreset:`Base Preset`,selectBasePreset:`Select base preset...`,presetName:`Preset Name`,myCustomPreset:`My custom preset`,inheritsFrom:`Inherits from`,dropJsonToImport:`Drop JSON to import`,tabs:{common:`Common`,allFields:`All Fields`},availableFields:`Available Fields`,searchFieldsPlaceholder:`Search fields...`,noMatchingFields:`No matching fields`,allFieldsAdded:`All fields added`,addCustomField:`Add custom field`,yourOverrides:`Your Overrides`,noOverridesYet:`No overrides yet`,clickFieldsToAdd:`Click fields on the left to add them`,saveAsTemplate:`Save as template`,jsonTip:`Tip: Drag & drop a .json file anywhere on this modal to import settings`},cloudView:{searchPlaceholder:`Search presets...`,templates:`Templates`,refresh:`Refresh`,newPreset:`New Preset`,clearFilters:`Clear filters`,compareMode:`Compare Mode`,selectAnotherPreset:`Select another {{type}} preset`,clickTwoPresets:`Click two presets of the same type to compare`,selectFirst:`1. Select first`,selectSecond:`2. Select second`,compareNow:`Compare Now`,lastSynced:`Last synced:`,showingCount:`Showing {{showing}} of {{total}} presets`,noPresetsFound:`No presets found`,columns:{filament:`Filament`,process:`Process`,printer:`Printer`},noFilamentPresets:`No filament presets`,noProcessPresets:`No process presets`,noPrinterPresets:`No printer presets`,filters:{type:`Type`,owner:`Owner`,printer:`Printer`,nozzle:`Nozzle`,filament:`Filament`,layer:`Layer`,all:`All`,myPresets:`My Presets`,builtIn:`Built-in`,process:`Process`},noTemplatesPermission:`You do not have permission to manage templates`,noRefreshPermission:`You do not have permission to refresh profiles`,noCreatePermission:`You do not have permission to create presets`},templates:{title:`Quick Templates`,noTemplates:`No templates yet`,createFirst:`Create templates from the preset editor`,typeFilter:`Type:`,deleteTitle:`Delete Template`,deleteWarning:`This action cannot be undone`,deleteConfirm:`Are you sure you want to delete "{{name}}"?`,namePlaceholder:`Template name`,descriptionPlaceholder:`Description`,settingsJson:`Settings (JSON)`,fieldsCount:`{{count}} fields`,shownInModals:`Shown in modals`,hiddenInModals:`Hidden in modals`,apply:`Apply`,toast:{deleted:`Template deleted`,updated:`Template updated`,created:`Template created`,applied:`Template applied`}}},support:{debugLoggingActive:`Debug logging is active`,manageLogs:`Manage`,collectItem7:`Printer connectivity and firmware versions`,collectItem8:`Integration status (Spoolman, MQTT, HA)`,collectItem9:`Network interfaces (subnets only)`,collectItem10:`Python package versions`,collectItem11:`Database health checks`,collectItem12:`Docker environment details`,bundleGenerating:`Generating bundle...`,bundleStepConnection:`Running printer connectivity checks`,bundleStepVirtualPrinters:`Running virtual-printer setup checks`,bundleStepLogScan:`Scanning recent logs for known issues`,bundleStepBuild:`Building the support bundle ZIP`},fileManager:{title:`File Manager`,subtitle:`Organize and manage your print files`,uploadFiles:`Upload Files`,newFolder:`New Folder`,folderName:`Folder Name`,folderNamePlaceholder:`e.g., Functional Parts`,renameFile:`Rename File`,renameFolder:`Rename Folder`,invalidFilenameChar:`The character "{{char}}" is not allowed in print filenames. The printer SD card rejects: < > : " / \\ | ? *`,moveFiles:`Move {{count}} File(s)`,rootNoFolder:`Root (No Folder)`,current:`current`,linkFolder:`Link Folder`,linkFolderDescription:`Link "{{name}}" to a project or archive for quick access.`,project:`Project`,archive:`Archive`,noProjectsFound:`No projects found`,noArchivesFound:`No archives found`,unlink:`Unlink`,link:`Link`,dragDropFiles:`Drag & drop files here`,dropFilesHere:`Drop files here`,releaseToUpload:`Release to upload`,orClickToBrowse:`or click to browse`,allFileTypesSupported:`All file types supported. ZIP files will be extracted.`,zipFilesDetected:`ZIP files detected`,zipExtractOptions:`ZIP files will be extracted. Choose how to handle folder structure:`,preserveZipStructure:`Preserve folder structure from ZIP`,createFolderFromZip:`Create folder from ZIP filename`,stlThumbnailGeneration:`STL thumbnail generation`,zipMayContainStl:`ZIP files may contain STL files. Thumbnails can be generated during extraction.`,thumbnailsCanBeGenerated:`Thumbnails can be generated for STL files. Large models may take longer to process.`,generateThumbnailsForStl:`Generate thumbnails for STL files`,threemfDetected:`3MF files detected`,threemfExtractionInfo:`Printer model, material, color, and print settings will be automatically extracted from 3MF files.`,willBeExtracted:`Will be extracted`,filesExtracted:`{{count}} files extracted`,uploadComplete:`Upload complete: {{succeeded}} succeeded`,uploadFailed:`Upload failed`,zipFilesFailed:`{{count}} files failed`,uploading:`Uploading...`,changeLink:`Change Link...`,linkTo:`Link to...`,linkToProjectOrArchive:`Link to project or archive`,generateThumbnail:`Generate Thumbnail`,generateThumbnails:`Generate Thumbnails`,generateThumbnailsForMissing:`Generate thumbnails for STL files missing them`,gridView:`Grid view`,listView:`List view`,lowDiskSpaceWarning:`Low disk space warning`,lowDiskSpaceDetails:`Only {{free}} free of {{total}} total. Threshold is set to {{threshold}} GB in settings.`,files:`Files`,folders:`Folders`,size:`Size`,free:`Free`,allFiles:`All Files`,allExternal:`External`,externalIsEmpty:`No external files`,externalEmptyDescription:`Files in your linked external folders will appear here.`,wrap:`Wrap`,enableTextWrapping:`Enable text wrapping`,disableTextWrapping:`Disable text wrapping`,collapse:`Collapse`,collapseFoldersByDefault:`Collapse folders by default`,expandFoldersByDefault:`Expand folders by default`,folderSort:`Sort folders`,folderSortByName:`By name`,folderSortByActivity:`By recent activity`,dragToResizeTooltip:`Drag to resize, double-click to reset`,searchFiles:`Search files...`,searchSubfoldersHint:`Including subfolders`,readme:{truncated:`Truncated`,show:`Show README`,hide:`Hide README`,label:`README`},tags:{title:`Tags`,subtitle:`Label files for cross-cutting filtering — toys, kid-safe, PETG-only, anything.`,manage:`Tags`,manageTitle:`Manage tag catalog`,add:`New tag`,edit:`Rename tag`,name:`Name`,fileCount:`Files`,empty:`No tags yet. Create one to start labelling files.`,noMatches:`No matching tags.`,createPlaceholder:`e.g. toys, kid-safe, petg`,createButton:`Create`,nameRequired:`Name is required.`,searchPlaceholder:`Filter tags...`,created:`Tag created.`,updated:`Tag renamed.`,deleted:`Tag removed.`,saveFailed:`Could not save tag.`,deleteFailed:`Could not remove tag.`,applyFailed:`Could not apply tags.`,applyAdd:`Add tags`,applyRemove:`Remove tags`,applyAddSuccess:`Added {{count}} tag(s) across {{files}} file(s).`,applyRemoveSuccess:`Removed {{count}} tag(s) across {{files}} file(s).`,actionAdd:`Add to selected files`,actionRemove:`Remove from selected files`,tagAction:`Tag`,bulkTitle:`Tag {{count}} selected file(s)`,bulkTooltip:`Add or remove tags on every selected file.`,noPermission:`You do not have permission to tag files.`,filterLabel:`Filtering by:`,clearAll:`Clear all`,confirmDelete:`Delete tag "{{name}}"?`,confirmDeleteMessage:`This removes the tag from the catalog. Files keep their other tags.`,confirmDeleteInUseMessage:`This tag is on {{count}} file(s). Deleting removes the chip from all of them; files themselves are untouched.`,editAria:`Edit {{name}}`,deleteAria:`Delete {{name}}`},allTypes:`All types`,prints:`Prints`,ascending:`Ascending`,descending:`Descending`,showModified:`Show modified dates`,hideModified:`Hide modified dates`,lastModified:`Last modified`,lastActivity:`Last activity`,resultsCount:`{{showing}} of {{total}} files`,selectAll:`Select All`,deselectAll:`Deselect All`,selected:`{{count}} selected`,adding:`Adding...`,loadingFiles:`Loading files...`,folderIsEmpty:`Folder is empty`,noFilesYet:`No files yet`,folderEmptyDescription:`Upload files or move files into this folder to get started.`,noFilesDescription:`Upload files to start organizing your print-related files.`,noMatchingFiles:`No matching files`,noMatchingFilesDescription:`No files match your current search or filter criteria.`,clearFilters:`Clear filters`,printedCount:`Printed {{count}}x`,uploadedBy:`Uploaded By`,deleteFolder:`Delete Folder`,deleteFile:`Delete File`,deleteFilesCount:`Delete {{count}} Files`,deleteFolderConfirm:`Are you sure you want to delete this folder? All files inside will also be deleted.`,deleteFileConfirm:`Are you sure you want to delete this file?`,deleteFilesConfirm:`Are you sure you want to delete {{count}} selected files? This action cannot be undone.`,deleting:`Deleting...`,noPermissionRenameFolder:`You do not have permission to rename folders`,noPermissionLinkFolder:`You do not have permission to link folders`,noPermissionDeleteFolder:`You do not have permission to delete folders`,onlyEmptyFoldersDeletable:`You can only delete empty folders`,noPermissionPrint:`You do not have permission to print`,noPermissionAddToQueue:`You do not have permission to add to queue`,noPermissionSlice:`You do not have permission to slice files`,noPermissionDownload:`You do not have permission to download files`,noPermissionRenameFile:`You do not have permission to rename this file`,noPermissionGenerateThumbnail:`You do not have permission to generate thumbnails`,noPermissionDeleteFile:`You do not have permission to delete this file`,noPermissionCreateFolder:`You do not have permission to create folders`,noPermissionUpload:`You do not have permission to upload files`,noPermissionMoveFiles:`You do not have permission to move files`,noPermissionDeleteFiles:`You do not have permission to delete files`,linkExternal:`Link External`,linkExternalFolder:`Link External Folder`,linkExternalFolderDescription:`Mount a host directory (NAS, USB, network share) into the File Manager. Files are not copied — they are accessed directly from the original path.`,externalFolderNamePlaceholder:`e.g., NAS Prints`,externalPath:`Host Path`,externalPathHelp:`Absolute path to the directory on the Docker host. Must be bind-mounted into the container.`,readOnly:`Read Only`,readOnlyHelp:`prevents uploads and deletions`,showHiddenFiles:`Show hidden files (dotfiles)`,externalFolder:`External Folder`,scanFolder:`Scan`,toast:{folderCreated:`Folder created`,folderDeleted:`Folder deleted`,fileDeleted:`File deleted`,filesDeleted:`Deleted {{count}} files`,filesMoved:`Files moved`,folderLinked:`Folder linked`,folderUnlinked:`Folder unlinked`,externalFolderLinked:`External folder linked and scanned`,folderScanned:`Scan complete: {{added}} added, {{removed}} removed`,addedToQueue:`Added {{count}} file(s) to queue`,addedToQueuePartial:`Added {{added}} file(s), {{failed}} failed`,failedToAddToQueue:`Failed to add files: {{error}}`,fileRenamed:`File renamed`,folderRenamed:`Folder renamed`,thumbnailsGenerated:`Generated {{count}} thumbnail(s)`,thumbnailsGeneratedPartial:`Generated {{succeeded}} thumbnail(s), {{failed}} failed`,noStlMissingThumbnails:`No STL files missing thumbnails`,failedToGenerateThumbnails:`Failed to generate thumbnails: {{error}}`,thumbnailGenerated:`Thumbnail generated`,failedToGenerateThumbnail:`Failed to generate thumbnail: {{error}}`}},projects:{title:`Projects`,subtitle:`Organize and track your 3D printing projects`,newProject:`New Project`,editProject:`Edit Project`,deleteProject:`Delete Project`,projectName:`Project Name`,description:`Description`,noProjects:`No projects yet`,noProjectsFiltered:`No {{status}} projects`,noProjectsFilteredHelp:`You don't have any {{status}} projects. Projects will appear here when their status changes.`,createFirst:`Create your first project to start organizing related prints, tracking progress, and managing your builds.`,createFirstButton:`Create Your First Project`,create:`Create`,files:`Files`,prints:`Prints`,plates:`plates`,parts:`parts`,lastModified:`Last Modified`,deleteConfirm:`Are you sure you want to delete this project? Archives and queue items will be unlinked but not deleted.`,addFiles:`Add Files`,removeFile:`Remove File`,viewDetails:`View Details`,namePlaceholder:`e.g., Voron 2.4 Build`,descriptionPlaceholder:`Optional description...`,urlLabel:`URL`,urlPlaceholder:`https://makerworld.com/...`,urlInvalid:`URL must start with http:// or https://`,openExternalUrl:`Open project URL`,coverImageLabel:`Cover photo`,coverImageAlt:`Project cover photo`,coverImageUpload:`Upload`,coverImageReplace:`Replace`,coverImageRemove:`Remove`,color:`Color`,targetPlates:`Target Plates`,targetPlatesPlaceholder:`e.g., 25`,targetPlatesHelp:`Number of print jobs`,targetParts:`Target Parts`,targetPartsPlaceholder:`e.g., 150`,targetPartsHelp:`Total objects needed`,targetSets:`Copies per File`,targetSetsPlaceholder:`e.g., 10`,targetSetsHelp:`Times each printable file should be printed`,tagsLabel:`Tags (comma-separated)`,tagsPlaceholder:`e.g., voron, functional, gift`,dueDate:`Due Date`,priority:`Priority`,priorityLow:`Low`,priorityNormal:`Normal`,priorityHigh:`High`,priorityUrgent:`Urgent`,statusActive:`Active`,statusCompleted:`Completed`,statusArchived:`Archived`,done:`Done`,completed:`completed`,failed:`failed`,inQueue:`in queue`,noPrintsYet:`No prints yet`,printJobs:`Print jobs (plates)`,partsPrinted:`Parts printed`,failedParts:`Failed parts`,import:`Import`,export:`Export`,importProject:`Import project`,exportAll:`Export all projects`,loading:`Loading projects...`,noEditPermission:`You do not have permission to edit projects`,noDeletePermission:`You do not have permission to delete projects`,noCreatePermission:`You do not have permission to create projects`,noImportPermission:`You do not have permission to import projects`,noExportPermission:`You do not have permission to export projects`,toast:{created:`Project created`,updated:`Project updated`,deleted:`Project deleted`,imported:`Project imported`,multipleImported:`{{count}} projects imported`,importFailed:`Import failed`,exported:`Projects exported (metadata only)`}},projectDetail:{notFound:`Project not found`,backToProjects:`Back to Projects`,export:`Export`,exportProject:`Export project`,noExportPermission:`You do not have permission to export projects`,noEditPermission:`You do not have permission to edit projects`,partOf:`Part of:`,priorityLabel:`Priority:`,noPrints:`No prints in this project yet`,status:{active:`Active`,completed:`Completed`,archived:`Archived`},priority:{low:`Low`,normal:`Normal`,high:`High`,urgent:`Urgent`},dueDate:{overdue:`Overdue`,today:`Due today`,daysLeft:`{{count}} days left`},progress:{platesProgress:`Plates Progress`,partsProgress:`Parts Progress`,setsProgress:`Complete Sets`,sets:`sets`,setsHint:`A set is complete once every printable file has reached this count`,printJobs:`print jobs`,parts:`parts`,percentComplete:`{{percent}}% complete`,remaining:`{{count}} remaining`},stats:{printJobs:`Print Jobs`,total:`total`,failed:`{{count}} failed`,partsPrinted:`{{count}} parts printed`,printTime:`Print Time`,filamentUsed:`Filament Used`},cost:{title:`Cost Tracking`,filamentCost:`Filament Cost`,energy:`Energy`,totalCost:`Total Cost`,total:`Total`,includesBom:`incl. BOM`,budget:`Budget`,remaining:`Remaining`},subProjects:{title:`Sub-projects ({{count}})`},notes:{title:`Notes`,noEditPermission:`You do not have permission to edit notes`,placeholder:`Add notes about this project...`,empty:`No notes yet. Click Edit to add notes.`},files:{title:`Files`,linkFolders:`Link folders from the File Manager`,forQuickAccess:`to this project for quick access.`,fileCount:`{{count}} file(s)`,empty:`No folders linked. Go to File Manager and link a folder to this project.`,printedCount:`Printed {{count}} time(s)`,progressTooltip:`{{done}} of {{target}} completed prints`,noFiles:`No files in this folder.`},bom:{title:`Bill of Materials`,acquired:`{{completed}}/{{total}} acquired`,showAll:`Show all`,hideDone:`Hide done`,addPart:`Add Part`,noAddPermission:`You do not have permission to add parts`,partNamePlaceholder:`Part name (e.g., M3x8 screws)`,partName:`Part name`,qty:`Qty`,price:`Price ({{currency}})`,sourcingUrlPlaceholder:`Sourcing URL (optional)`,remarksPlaceholder:`Remarks (optional)`,deletePart:`Delete Part`,deleteConfirm:`Are you sure you want to delete "{{name}}"?`,noUpdatePermission:`You do not have permission to update parts`,noEditPermission:`You do not have permission to edit parts`,noDeletePermission:`You do not have permission to delete parts`,totalCost:`Total cost:`,empty:`No parts in the bill of materials. Add hardware, electronics, or other components to track what needs to be sourced.`},timeline:{title:`Activity Timeline`,empty:`No activity yet.`},template:{saveAsTemplate:`Save as Template`,noCreatePermission:`You do not have permission to create templates`},queue:{title:`Queue`,viewAll:`View all`,printing:`{{count}} printing`,queued:`{{count}} queued`},prints:{title:`Prints ({{count}})`},toast:{projectUpdated:`Project updated`,partAdded:`Part added`,partRemoved:`Part removed`,exportFailed:`Export failed`,projectExported:`Project exported`,templateCreated:`Template created`}},system:{title:`System Information`,version:`Version`,uptime:`Uptime`,cpuUsage:`CPU Usage`,memoryUsage:`Memory Usage`,diskUsage:`Disk Usage`,networkInfo:`Network Info`,logs:`Logs`,debugMode:`Debug Mode`,enableDebug:`Enable Debug Logging`,disableDebug:`Disable Debug Logging`,downloadLogs:`Download Logs`,clearLogs:`Clear Logs`,dockerInfo:`Docker Info`,containerName:`Container Name`,imageName:`Image Name`,platform:`Platform`,architecture:`Architecture`},sponsors:{sectionTitle:`Independent & community-funded`,tagline:`Bambuddy is free and stays that way because people choose to support it. No VC, no cloud lock-in.`,viewSupporters:`View supporters`,toastPrints:`You've completed {{count}} prints with Bambuddy. Bambuddy stays free thanks to its supporters.`,toastCost:`You've tracked {{total}} in filament with Bambuddy. See who keeps the project independent.`,toastArchives:`{{count}} prints archived with Bambuddy. See who keeps it independent.`,toastAnniversary:`One year with Bambuddy! See who keeps the project independent.`,toastVersionUpdate:`Updated to v{{version}}. Bambuddy stays free thanks to its supporters.`,toastBusiness:`Running Bambuddy on {{count}} printers? There's a support plan for teams — priority fixes, invoicing, and a direct line to the maintainer.`,businessCta:`Bambuddy for business`,businessTitle:`Bambuddy for business`,businessTagline:`You're running {{count}} printers. Priority support, commercial licensing and invoicing are available for teams and print farms.`},library:{title:`Filament Library`,addFilament:`Add Filament`,editFilament:`Edit Filament`,deleteFilament:`Delete Filament`,vendor:`Vendor`,material:`Material`,color:`Color`,kFactor:`K Factor`,temperature:`Temperature`,noFilaments:`No filaments in library`,deleteConfirm:`Are you sure you want to delete this filament?`,importFromPrinter:`Import from Printer`,exportToFile:`Export to File`,runWithPipeline:{actionLabel:`Run with pipeline`,noPermission:`You do not have permission to run pipelines`,modalTitle:`Run with pipeline`,confirmTitle:`Confirm run`,confirmIntro:`Pre-flight found issues with this run`,sourceHint:`Source`,pipelineHint:`Pipeline`,targetHint:`Target`,pipelineListAria:`Available pipelines`,runAnyway:`Run anyway`,loading:`Loading…`,empty:`No pipelines saved yet. Open the Slice dialog and click "Save as pipeline" to create one.`,noTarget:`No target printer set`,noTargetMessage:`This pipeline has no target printer set. Open it in Settings to pick one.`,copies:`Copies`,copiesHint:`max {{n}}`,classTarget:`Any {{model}}`,toast:{started:`Pipeline run started`,failed:`Could not start run`},issue:{printerNotSet:`No target printer set on this pipeline.`,printerNotFound:`Target printer no longer exists.`,printerDisabled:`Target printer is disabled.`,printerOffline:`Target printer is offline.`,filamentType:`Filament slot {{slot}}: expected {{expected}}, AMS has {{actual}}`,filamentColor:`Filament slot {{slot}}: colour differs (expected {{expected}}, AMS has {{actual}})`,amsSlotMissing:`AMS slot {{slot}} not available on this printer`,filamentUnverified:`Filament slot {{slot}} comes from a cloud / standard preset and could not be statically verified.`,noClassMatches:`No printers in this install match the pipeline's target model class ({{expected}}).`,classNotSet:`Pipeline target is set to a printer class but no model was chosen.`}}},slice:{title:`Slice model`,action:`Slice`,actionAll:`Slice all {{count}} plates`,actionAllTitle:`Slice every plate into one multi-plate output (single archive). Filament selection covers every slot the project defines.`,allPlatesToggle:`Slice all {{count}} plates`,slicing:`Slicing…`,printer:`Printer profile`,process:`Process profile`,filament:`Filament profile`,filamentSlot:`Filament {{index}} ({{type}})`,selectPreset:`— Select a preset —`,loadingPresets:`Loading presets…`,analyzingPlateFilaments:`Analyzing plate filaments…`,analyzingPlateFilamentsHint:`Running a preview slice to discover which AMS slots this plate uses. Cached after — re-opening is instant.`,previewToast:`Analyzing {{name}} — {{elapsed}}`,previewWithProgress:`Analyzing {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}`,notUsedByPlate:`— not used by this plate`,noPresetsForSlot:`No presets available`,otherPrinters:`Other printers`,presetsLoadFailed:`Failed to load presets. Open Settings → Profiles to import them first.`,refreshPresets:`Refresh`,refreshPresetsTitle:`Refresh presets — fetch the latest cloud and bundled listings (use after deleting a preset in Bambu Studio or Bambu Handy)`,allPresetsRequired:`All presets must be selected`,useEmbedded:`Use the file's built-in settings`,useEmbeddedHint:`Slice it the way the designer set it up (walls, infill, filament) instead of the profiles above. Offered because your printer matches the file's.`,designSettings:`Keep the designer's settings`,designSettingsHint:`This file changes {{count}} print setting(s) from the stock profile.`,designSettingsSelected:`{{selected}} of {{total}} selected`,designSettingsPrinterCoupled:`printer-specific`,designSettingsPrinterCoupledHint:`Tuned for the printer this file was designed for — may be wrong or out of range on yours.`,enqueuing:`Submitting slice job…`,queued:`Queued…`,failed:`Slicing failed. Check the slicer sidecar logs.`,startedToast:`Slicing {{name}} in the background…`,queuedToast:`Queued: {{name}} — {{elapsed}}`,runningToast:`Slicing {{name}} — {{elapsed}}`,runningWithProgress:`{{name}} — {{stage}} ({{percent}}%) — {{elapsed}}`,runningWithProgressMultiPlate:`Plate {{plateIndex}} of {{plateCount}} • {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}`,completedToast:`Sliced {{name}}`,failedTitle:`Slicing failed`,failedToast:`Slicing {{name}} failed: {{detail}}`,tier:{local:`Imported`,cloud:`Bambu Cloud`,orcaCloud:`Orca Cloud`,standard:`Standard`},cloud:{notAuthenticated:`Sign in to Bambu Cloud (Settings → Profiles → Bambu Cloud) to see your cloud presets.`,expired:`Bambu Cloud session expired — sign in again to refresh your cloud presets.`,unreachable:`Bambu Cloud is unreachable right now. Local and standard presets still work.`},orcaCloud:{notAuthenticated:`Sign in to Orca Cloud (Profiles → Orca Cloud) to see your Orca presets.`,expired:`Orca Cloud session expired — sign in again to refresh your Orca presets.`,unreachable:`Orca Cloud is unreachable right now. Other presets still work.`},bedType:{label:`Build plate`,auto:`Auto (use process preset)`,coolPlate:`Cool Plate`,coolPlateSuperTack:`Cool Plate SuperTack`,engineering:`Engineering Plate`,highTemp:`High Temp Plate`,texturedPEI:`Textured PEI Plate`,smoothPEI:`Smooth PEI Plate`},pipelines:{label:`Pipeline`,applyAria:`Apply pipeline`,applyPrompt:`Apply pipeline…`,empty:`No saved pipelines`,saveButton:`Save as pipeline`,saveTitle:`Save the current four-slot selection as a reusable pipeline`,namePlaceholder:`Pipeline name`,nameAria:`New pipeline name`,toast:{applied:`Applied "{{name}}"`,saved:`Pipeline saved`,saveFailed:`Save failed`}}},spoolman:{title:`Spoolman Integration`,enabled:`Spoolman Enabled`,url:`Spoolman URL`,connected:`Connected`,disconnected:`Not Connected`,testConnection:`Test Connection`,sync:`Sync`,syncing:`Syncing...`,lastSync:`Last Sync`,linkToSpoolman:`Link to Spoolman`,openInSpoolman:`Open in Spoolman`,unlinkSpool:`Unlink Spool`,unlinkConfirmTitle:`Unassign Spool?`,unlinkConfirmMessage:`This will remove the spool from this slot. The spool data itself will remain unchanged.`,selectSpool:`Select Spool`,noUnlinkedSpools:`No unassigned spools available`,linkSuccess:`Spool assigned successfully`,linkFailed:`Failed to assign spool`,unlinkSuccess:`Spool unassigned successfully`,unlinkFailed:`Failed to unassign spool`,linkedSpool:`Assigned spool`,spoolId:`Spool ID`,fillSourceLabel:`(Spoolman)`,weight:`Weight`,remaining:`Remaining`,disableWeightSync:`Disable AMS Estimated Weight Sync`,disableWeightSyncDesc:`Don't update remaining capacity from AMS estimates. Use this if you prefer Spoolman's usage tracking over AMS percentage-based estimates. New spools will still use the AMS estimate as their initial weight.`,reportPartialUsage:`Report Partial Usage for Failed Prints`,reportPartialUsageDesc:`When a print fails or is cancelled, report the estimated filament used up to that point based on layer progress.`},locations:{title:`Storage Locations`,subtitle:`Manage shelves, drawers, and other physical storage spots for your spools`,add:`Add Location`,addShort:`Add`,edit:`Edit Location`,name:`Name`,spools:`Spools`,empty:`No storage locations yet. Create your first shelf or drawer.`,manage:`Locations`,createPlaceholder:`e.g. Shelf A, Drawer 1`,nameRequired:`Location name is required`,created:`Location created`,updated:`Location updated`,deleted:`Location deleted`,saveFailed:`Failed to save location`,deleteFailed:`Failed to delete location`,deleteBlocked:`Remove all spools from this location before deleting`,confirmDelete:`Delete "{{name}}"?`,confirmDeleteMessage:`This location will be removed from the catalog. Spools must be moved first.`},inventory:{title:`Spool Inventory`,subtitle:`Manage your spools`,addToInventory:`Add to Inventory`,addToInventoryPending:`Adding...`,addToInventorySuccess:`Spool added to inventory`,addToInventoryFailed:`Failed to add spool to inventory`,unknownSpoolTitle:`New filament detected`,unknownSpoolMessage:`A spool with an unknown RFID tag was detected at {{location}}. Add it to your inventory now?`,unknownSpoolSlot:`Slot`,bulk:{selectAllVisible:`Select all visible`,selectRow:`Select row`,selectGroup:`Select group`,selectionCount:`{{count}} selected`,edit:`Edit`,printLabels:`Print labels`,resetUsage:`Reset usage`,restore:`Restore`,archive:`Archive`,delete:`Delete`,clearSelection:`Clear selection`,editTitle:`Bulk edit spools`,editSubtitle:`Applies to {{count}} selected spools. Only fields you tick get updated.`,editHint:`Type into a field to mark it for update — only ticked rows are sent. Leaving a field empty leaves the spools unchanged (clearing fields is per-spool only).`,useCustom:`Use "{{value}}"`,toggleField:`Toggle update for this field`,changeCount:`{{count}} fields will be updated.`,applyPending:`Applying...`,applyButton:`Apply to {{count}} spools`,deleteTitle:`Delete selected spools`,archiveTitle:`Archive selected spools`,restoreTitle:`Restore selected spools`,resetUsageTitle:`Reset usage on selected spools`,deleteMessage:`Permanently delete {{count}} spools? This cannot be undone.`,archiveMessage:`Archive {{count}} spools? They can be restored later.`,restoreMessage:`Restore {{count}} archived spools?`,resetUsageMessage:`Reset the "Total Consumed" counter on {{count}} spools? Remaining weight is preserved.`,updateSuccess:`{{count}} spools updated`,updateFailed:`Bulk update failed`,updatePartial:`{{ok}} spools updated, {{failed}} failed`,updateAllFailed:`All {{count}} spool updates failed — selection kept so you can retry`,deleteSuccess:`{{count}} spools deleted`,deleteFailed:`Bulk delete failed`,deletePartial:`{{ok}} spools deleted, {{failed}} failed`,deleteAllFailed:`All {{count}} spool deletions failed — selection kept so you can retry`,archiveSuccess:`{{count}} spools archived`,archiveFailed:`Bulk archive failed`,archivePartial:`{{ok}} spools archived, {{failed}} failed`,archiveAllFailed:`All {{count}} spool archives failed — selection kept so you can retry`,restoreSuccess:`{{count}} spools restored`,restoreFailed:`Bulk restore failed`,restorePartial:`{{ok}} spools restored, {{failed}} failed`,restoreAllFailed:`All {{count}} spool restores failed — selection kept so you can retry`,invalidHex:`Enter 6 hex characters (RRGGBB) or 8 (RRGGBBAA). The field will not be applied otherwise.`},spoolmanMixedContentTitle:`Spoolman can't load over HTTPS — mixed-content blocked by your browser`,spoolmanMixedContentBody:`Bambuddy is served over HTTPS (via your reverse proxy), but your Spoolman URL is still plain HTTP. Browsers block mixed content for security, so the embedded Spoolman UI can't render. Spoolman needs to be reachable over HTTPS for this to work.`,spoolmanMixedContentFixReverseProxy:`Put Spoolman behind the same reverse proxy as Bambuddy (Traefik / Nginx / Caddy) with HTTPS, then update the Spoolman URL in Settings to the new HTTPS address.`,spoolmanMixedContentFixOpenNewTab:`As a workaround, open Spoolman in a new browser tab over HTTP — mixed-content rules only apply to embedded frames, so a standalone tab still works.`,spoolmanOpenInNewTab:`Open Spoolman in a new tab`,labels:{title:`Print spool labels`,selectedCount:`{{count}} selected`,pickSpools:`Pick which spools to print labels for:`,monochrome:`Monochrome (black & white printer)`,monochromeHint:`Drops the colour swatch and widens the text`,searchPlaceholder:`Search name, brand, or #ID`,filterByMaterial:`Material:`,allMaterials:`All`,selectVisible:`Select all visible ({{count}})`,deselectVisible:`Deselect visible`,clearAll:`Clear all`,noSpoolsToShow:`No spools to show. Adjust your filter and try again.`,noMatches:`No spools match the current search or filter.`,printOne:`Print label for this spool`,printLabels:`Print labels…`,bulkTitle:`Pick spools to print labels for from the {{count}} currently shown`,noSpoolsTitle:`No spools to label`,error:`Could not generate labels: {{msg}}`,sortBy:{label:`Sort:`,id:`By ID`,color:`By colour`},templates:{amsHolderSmall:{label:`AMS holder — small (74 × 33 mm)`,hint:`Single label per page; matches the printable label from MakerWorld model 752566 (AMS Filament Label Holder).`},amsHolderLarge:{label:`AMS holder — large (75 × 55 mm)`,hint:`Single label per page; fits the cardstock-insert variant of the AMS Filament Label Holder. Roomy enough for swatch, brand, material, ID, and QR code.`},box40x30:{label:`Box label (40 × 30 mm)`,hint:`Single label per page; common DK/Brother roll size, good for filament-bag and storage-bin labels.`},box:{label:`Box label (62 × 29 mm)`,hint:`Single label per page; sized for Brother PT/QL and Dymo small labels.`},averyL7160:{label:`Avery L7160 — A4 sheet (38.1 × 63.5 mm × 21)`,hint:`EU sheet stock; 21 labels per A4 page.`},avery5160:{label:`Avery 5160 — US Letter sheet (25.4 × 66.7 mm × 30)`,hint:`US sheet stock; 30 labels per Letter page.`}}},csv:{importButton:`Import CSV`,exportButton:`Export CSV`,modalTitle:`Import spools from CSV`,selectFile:`Choose a CSV file or drag it here`,dragHint:`Header: material (required), brand, subtype, color_name, rgba, …`,parsing:`Reading file…`,previewError:`Could not read the CSV file`,validCount:`{{count}} valid`,errorCount:`{{count}} error`,skippedCount:`{{count}} skipped`,colRow:`Row`,colStatus:`Status`,colColor:`Color`,colorResolved:`Color filled from catalog`,colorCrossMaterial:`Color taken from a different material — no exact match in catalog`,duplicateExisting:`A spool with this material, brand and color already exists — it will still be imported as a new spool`,spoolmanHint:`In Spoolman mode, use Spoolman's built-in CSV import/export.`,importValidRows:`Import {{count}} valid rows`,noValidRows:`No valid rows`,importing:`Importing…`,importSuccess:`{{count}} spools imported`,importError:`Import failed`,exportError:`Export failed`},addSpool:`Add Spool`,editSpool:`Edit Spool`,copySpool:`Copy Spool`,material:`Material`,selectMaterial:`Select material...`,subtype:`Subtype`,brand:`Brand`,searchBrand:`Search brand...`,useCustomBrand:`Use "{{brand}}"`,useCustomMaterial:`Use custom material: {{material}}`,suggestedOptions:`Suggested`,allOptions:`All`,colorName:`Color Name`,colorNamePlaceholder:`Jade White, Fire Red...`,color:`Color`,hexColor:`Hex Color`,pickColor:`Pick custom color`,labelWeight:`Label Weight`,coreWeight:`Empty Spool Weight`,searchSpoolWeight:`Search spool weight...`,weightUsed:`Used`,currentWeight:`Remaining Weight`,measuredWeight:`Measured Weight`,spoolName:`Spool`,costPerKg:`Cost per kg`,storageLocation:`Storage Location`,storageLocationPlaceholder:`e.g. Shelf A, Drawer 1`,openInInventory:`Open in Inventory`,measuredWeightError:`Measured weight must be between {{min}}g and {{max}}g.`,slicerFilament:`Slicer Filament`,slicerFilamentName:`Slicer Preset Name`,slicerPreset:`Slicer Preset`,searchPresets:`Search filament presets...`,selectedPreset:`Selected`,noPresetsFound:`No presets found`,tempOverrides:`Temperature Overrides`,note:`Note`,notePlaceholder:`Any additional notes about this spool...`,category:`Category`,categoryPlaceholder:`e.g. Production, Prototype, Client A`,categoryNone:`Uncategorized`,storageLocationNone:`No location set`,lowStockThresholdOverride:`Low-stock threshold (this spool)`,lowStockThresholdOverrideHelp:`Leave blank to use the global threshold ({{global}}%).`,clearRfid:`Clear RFID Tag`,rfidCleared:`RFID tag cleared`,archive:`Archive`,restore:`Restore`,noSpools:`No spools yet. Add your first spool to get started.`,noAvailableSpools:`No spools available. Add a spool to your inventory or unassign one from another slot first.`,kProfiles:`K-Profiles`,addKProfile:`Add K-Profile`,assignSpool:`Assign Spool`,unassignSpool:`Unassign`,assignSuccess:`Spool assigned and AMS slot configured`,assignPendingInsert:`Assigned. Slot will configure when you insert the spool.`,assignFailed:`Failed to assign spool`,selectSpool:`Select a spool to assign to this slot`,assigned:`Assigned`,assigning:`Assigning...`,searchSpools:`Search spools...`,showAllSpools:`Show all spools`,spoolmanSpools:`Spoolman Spools`,allMaterials:`All Materials`,filterByBrand:`Filter by brand...`,showArchived:`Show archived`,quickAdd:`Quick Add (Stock)`,quantity:`Quantity`,stock:`Stock`,configured:`Configured`,spoolsCreated:`{{count}} spools created`,spoolsPartiallyCreated:`{{created}} of {{total}} spools created (some failed)`,spoolCreated:`Spool created`,spoolUpdated:`Spool updated`,spoolDeleted:`Spool deleted`,deepLinkSpoolNotFound:`Spool not found`,deepLinkFetchFailed:`Could not load spool — try again`,spoolArchived:`Spool archived`,spoolRestored:`Spool restored`,kProfileSaveFailed:`K-profile settings could not be saved`,syncWeightSpoolNotFound:`Spool not found — it may have been deleted`,syncWeightSpoolmanUnreachable:`Spoolman is unreachable — try again later`,syncWeightFailed:`Failed to sync weight`,spoolmanUnreachable:`Spoolman is not reachable — please try again later`,deleteSpoolNotFound:`Spool not found — it may have already been deleted`,deleteFailed:`Failed to delete spool`,archiveSpoolNotFound:`Spool not found — it may have already been deleted`,archiveFailed:`Failed to archive spool`,restoreSpoolNotFound:`Spool not found — it may have already been deleted`,restoreFailed:`Failed to restore spool`,saveFailed:`Failed to save changes`,tagClearFailed:`Failed to clear tag`,deleteConfirm:`Are you sure you want to delete this spool? This cannot be undone.`,archiveConfirm:`Are you sure you want to archive this spool?`,advancedSettings:`Advanced Settings`,filamentInfoTab:`Filament Info`,paProfileTab:`PA Profile`,filamentInfo:`Filament`,additional:`Additional`,loadingPresets:`Loading cloud presets...`,cloudConnected:`Cloud connected`,cloudNotConnected:`Cloud not connected (using defaults)`,recentColors:`Recent`,searchColors:`Search colors...`,searchResults:`Search results`,allColors:`All colors`,commonColors:`Common colors`,showLess:`Show less`,showAll:`Show all`,noColorsFound:`No colors match your search`,noResults:`No matches found`,extraColorsLabel:`Extra colors`,extraColorsPlaceholder:`EC984C,#6CD4BC,A66EB9,D87694`,extraColorsHint:`Paste 2 to 8 hex stops, separated by commas. Renders as a gradient.`,extraColorsInvalid:`Ignored invalid hex: {{tokens}}`,colorEffectLabel:`Effect`,colorEffect:{none:`None`,sparkle:`Sparkle`,wood:`Wood`,marble:`Marble`,glow:`Glow`,matte:`Matte`,silk:`Silk`,galaxy:`Galaxy`,rainbow:`Rainbow`,metal:`Metal`,translucent:`Translucent`,gradient:`Gradient`,dualColor:`Dual Color`,triColor:`Tri Color`,multicolor:`Multicolor`},selectMaterialFirst:`Please select a material first in the Filament Info tab.`,noPrintersConfigured:`No printers configured. Add printers to use PA profiles.`,matchingFilter:`Matching`,anyBrand:`Any brand`,anyVariant:`Any variant`,autoSelect:`Auto-select`,matches:`matches`,match:`match`,noMatches:`No matches`,connected:`Connected`,offline:`Offline`,printerOffline:`Printer is offline. Connect to view calibration profiles.`,noKProfilesMatch:`No K-profiles match the selected filament.`,leftNozzle:`Left Nozzle`,rightNozzle:`Right Nozzle`,profilesSelected:`calibration profile(s) selected`,totalInventory:`Total Inventory`,totalConsumed:`Total Consumed`,byMaterial:`By Material`,inPrinter:`In Printer`,lowStock:`Low Stock`,sinceTracking:`Since tracking started`,resetConsumedCounter:`Reset counter`,resetConsumedCounterTooltip:`Zero the consumed-grams counter for this spool. Remaining weight is not changed.`,resetConsumedCounterConfirm:`Reset this spool's consumed-grams counter to 0? Future prints will track from zero again. The spool itself, its remaining weight calculation, and your settings are not changed.`,resetAllConsumedCounters:`Reset all counters`,resetAllConsumedCountersTooltip:`Zero the consumed-grams counter on every spool. Remaining weights are not changed.`,resetAllConsumedCountersConfirm:`Reset the consumed-grams counter to 0 on all {{count}} spools (archived ones included)? This clears the "Total Consumed" stat so future prints track from zero. Spools and remaining weights are not changed.`,consumedCounterReset:`Counter reset`,allConsumedCountersReset:`Counter reset for {{count}} spool(s)`,resetConsumedCounterFailed:`Failed to reset counter`,loadedInAms:`Loaded in AMS/Ext`,remaining:`Remaining`,weightCheck:`Weight Check`,lastWeighed:`Last weighed`,neverWeighed:`Never weighed`,search:`Search spools...`,showing:`Showing`,to:`to`,of:`of`,show:`Show`,spools:`spools`,spool:`spool`,page:`Page`,noSpoolsMatch:`No results found`,noSpoolsMatchDesc:`Try adjusting your search or filters to find what you're looking for.`,active:`Active`,archived:`Archived`,all:`All`,used:`Used`,new:`New`,clearFilters:`Clear filters`,table:`Table`,cards:`Cards`,net:`Net`,groupSimilar:`Group`,groupedSpools:`{{count}} identical spools`,groupedRows:`rows`,columns:`Columns`,configureColumns:`Configure Columns`,configureColumnsDesc:`Drag to reorder columns or use arrows. Toggle visibility with the eye icon.`,visible:`visible`,reset:`Reset`,cancel:`Cancel`,applyChanges:`Apply Changes`,moveUp:`Move up`,moveDown:`Move down`,hideColumn:`Hide column`,showColumn:`Show column`,linkToSpool:`Link to Spool`,tagLinked:`Tag linked to spool`,tagLinkFailed:`Failed to link tag`,tagAlreadyLinked:`Tag already linked to another spool`,unknownTag:`Unknown RFID tag detected`,usageHistory:`Usage History`,noUsageHistory:`No usage recorded yet`,printName:`Print Name`,weightConsumed:`Weight Consumed`,clearHistory:`Clear`,historyCleared:`Usage history cleared`,fillSourceLabel:`(Inv)`,lowStockThresholdError:`Threshold must be between 0.1 and 99.9`,assignMismatchTitle:`Material mismatch`,assignMismatchMessage:`The selected spool material "{{spoolMaterial}}" does not match the tray material "{{trayMaterial}}" for {{location}}. Assign anyway?`,assignMismatchConfirm:`Assign Anyway`,assignPartialMismatchMessage:`The spool material "{{spoolMaterial}}" is similar to but not exactly matching "{{trayMaterial}}" in {{location}}. Do you want to proceed?`,assignProfileMismatchMessage:`The spool profile "{{spoolProfile}}" does not match the tray profile "{{trayProfile}}" in {{location}}. Do you want to proceed?`,assignReconfigureNote:`The AMS slot will be reconfigured to use the spool's profile.`,spoolmanFilamentCatalog:`Spoolman Filament Catalog`,pickFromSpoolmanCatalog:`Pick from Spoolman catalog…`,spoolmanFilamentSelected:`Filament selected from Spoolman catalog`,spoolmanFilamentUnlinked:`Filament catalog link cleared`,noSpoolmanFilaments:`No filaments found in Spoolman catalog`,spoolmanFilamentColorSwatch:`Filament color`,spoolWeightManagedBySpoolman:`Empty spool weight is managed per filament type in Spoolman`,spoolmanCatalogLoadFailed:`Failed to load Spoolman filament catalog`},timelapse:{title:`Timelapse`,create:`Create Timelapse`,download:`Download`,delete:`Delete`,preview:`Preview`,frameRate:`Frame Rate`,quality:`Quality`,processing:`Processing...`,noTimelapses:`No timelapses available`},ams:{title:`AMS`,slot:`Slot`,empty:`Empty`,emptySlot:`Empty slot`,slotEmpty:`Empty`,slotUnconfigured:`?`,emptySlotReset:`No filament assigned`,unknown:`Unknown`,humidity:`Humidity`,temperature:`Temperature`,filamentType:`Filament Type`,filamentColor:`Color`,remaining:`Remaining`,history:`AMS History`,noHistory:`No history available`,configureSlot:`Configure Slot`,externalSpool:`External Spool`,profile:`Profile`,kFactor:`K Factor`,fill:`Fill`,configure:`Configure`,used:`used`,remainingUnit:`remaining`},printModal:{selectPrinter:`Select Printer`,selectPlate:`Select Plate`,filamentMapping:`Filament Mapping`,useArchiveMapping:`Mapping`,useArchiveMappingTooltip:`Select every slot from the AMS mapping saved with this archive (from the slicer), instead of matching by type/color.`,clickToChangeSlot:`Click to change slot assignment`,reRead:`Re-read`,plateN:`Plate {{n}}`,plateFilamentsUnreadable:`The filaments of a selected plate could not be read, so it can't be mapped. Deselect it to queue the others.`,totalCost:`Total cost:`,slotRemainingShort:` - {{grams}}g left`,printSettings:`Print Settings`,bedLeveling:`Bed Leveling`,flowCalibration:`Flow Calibration`,vibrationCalibration:`Vibration Calibration`,layerInspection:`First Layer Inspection`,timelapse:`Timelapse`,cancel:`Cancel`,noPrintersAvailable:`No printers available`,printerBusy:`Printer is busy`,printerOffline:`Printer is offline`,sameTypeDifferentColor:`Same type, different color`,filamentTypeNotLoaded:`Filament type not loaded`,whenToPrint:`When to print`,asap:`ASAP`,queue:`Queue`,schedule:`Schedule`,dateTime:`Date & Time`,invalidDateTime:`Please enter a valid date and time`,openCalendar:`Open calendar`,requireManualStart:`Require manual start`,requirePreviousSuccess:`Only start if previous print succeeded`,autoOffAfter:`Power off printer when done`,helpAsap:`Print will be added to the top of the queue and start as soon as an eligible printer is idle.`,helpSchedule:`Print will start at the scheduled time if the printer is idle. If busy, it will wait until the printer becomes available.`,helpQueue:`Print will be added to the back of the queue.`,leftNozzle:`L`,rightNozzle:`R`,leftNozzleTooltip:`Left nozzle`,rightNozzleTooltip:`Right nozzle`,filamentOverride:`Filament Override`,filamentOverrideHint:`Optionally override filaments for model-based assignment. The scheduler will match against your selected filaments instead of the original 3MF values.`,originalFilament:`Original`,overrideWith:`Override with`,resetToOriginal:`Reset to original`,insufficientFilamentTitle:`Not enough filament`,waitingForAmsStatus:`Waiting for AMS status from {{printer}}…`,insufficientFilamentMessage:`Some assigned spools have less filament remaining than this print needs:`,insufficientFilamentLine:`{{printer}} - {{slot}}: needs {{required}}g, remaining {{remaining}}g`,printAnyway:`Print anyway`,forceColorMatch:`Force color match`,staggerPrinterStarts:`Stagger printer starts`,staggerGroupSize:`Group size`,staggerInterval:`Interval (min)`,staggerPreview:`{{printers}} printers → {{groups}} groups of {{size}}, starting every {{interval}} min`,staggerLastGroup:`last group: {{count}}`,staggerTotal:`total: {{minutes}} min`,staggerToPrinters:`Stagger to {{count}} printers`,gcodeInjection:`Inject auto-print G-code`},backup:{includesEncryptionKey:`Local backups include the MFA encryption key file (DATA_DIR/.mfa_encryption_key) so a backup ZIP is self-contained. Treat the ZIP as sensitive — anyone with the file can decrypt the OIDC client secrets and TOTP secrets stored inside.`,title:`Backup & Restore`,createBackup:`Create Backup`,restoreBackup:`Restore Backup`,restoreDescription:`Replace all data from a backup file`,downloadBackup:`Download Backup`,uploadBackup:`Upload Backup`,lastBackup:`Last Backup`,autoBackup:`Auto Backup`,backupNow:`Backup Now`,restoreWarning:`Warning: Restoring a backup will overwrite all current data.`,includeArchives:`Include Archives`,includeSettings:`Include Settings`,includeProfiles:`Include Profiles`,backupSuccess:`Backup created successfully`,restoreSuccess:`Backup restored successfully`,backupFailed:`Backup failed`,restoreFailed:`Restore failed`,restoreNote:`Virtual Printer will be stopped during restore`,githubBackup:`Git Backup`,enabled:`Enabled`,cloudLoginRequired:`Bambu Cloud login required. Sign in under Profiles → Cloud Profiles to enable GitHub backup.`,cloudLoginRequiredShort:`Cloud login required`,githubDescription:`Automatically sync your profiles to a private GitHub repository for backup and version history.`,repoIsPrivate:`Repository is private — safe to back up to.`,repoIsPublicWarning:`Repository is PUBLIC. Bambuddy backups include MQTT credentials, Home Assistant tokens, Prometheus tokens, your Bambu Cloud email, and printer access codes via K-profiles. Saving is blocked until you make the repository private in your provider's settings.`,repoVisibilityUnknown:`Could not determine repository visibility. Bambuddy refuses to back up to anything not confirmed private; saving will be blocked.`,repositoryUrl:`Repository URL`,repoUrlPlaceholderGitHub:`https://github.com/username/repo-name`,repoUrlPlaceholderGitea:`https://gitea.example.com/username/repo-name`,repoUrlPlaceholderForgejo:`https://forgejo.example.com/username/repo-name`,repoUrlPlaceholderGitLab:`https://gitlab.com/username/repo-name`,allowInsecureHttp:`Allow insecure HTTP`,allowInsecureHttpHint:`Enable for self-hosted instances on private networks without TLS`,personalAccessToken:`Personal Access Token`,tokenSaved:`(saved)`,enterNewToken:`Enter new token to update`,tokenHint:`Fine-grained token with Contents read/write permission`,branch:`Branch`,provider:`Git Provider`,providerGitHub:`GitHub`,providerGitLab:`GitLab`,providerGitea:`Gitea`,providerForgejo:`Forgejo`,manualOnly:`Manual only`,hourly:`Hourly`,daily:`Daily`,weekly:`Weekly`,includeInBackup:`Include in backup`,kProfiles:`K-Profiles`,kProfilesDescription:`Pressure advance calibration from connected printers`,noPrintersConnected:`No printers connected`,printersConnected:`{{connected}}/{{total}} connected`,cloudProfiles:`Cloud Profiles`,cloudProfilesDescription:`Filament, printer, and process presets from Bambu Cloud and Orca Cloud`,cloudProfilesAccounts:`Connected accounts — Bambu Cloud: {{bambu}}, Orca Cloud: {{orca}}`,appSettings:`App Settings`,appSettingsDescription:`Bambuddy configuration (complete database)`,spoolInventory:`Spool Inventory`,spoolInventoryDescription:`Filament spools, usage history, and cost tracking`,printArchives:`Print Archives`,printArchivesDescription:`Print history metadata (no gcode/3MF files)`,lastBackupAt:`Last backup:`,noBackupsYet:`No backups yet`,next:`Next:`,startingBackup:`Starting backup...`,test:`Test`,enableBackup:`Enable Backup`,testConnection:`Test Connection`,enterRepoUrl:`Enter repository URL`,enterRepoAndToken:`Enter repository URL and access token`,repoRequired:`Repository URL is required`,tokenRequired:`Access token is required`,githubBackupEnabled:`GitHub backup enabled`,tokenUpdated:`Token updated`,settingsSaved:`Settings saved`,failedToSave:`Failed to save: {{message}}`,backupCompleteFiles:`Backup complete - {{count}} files updated`,backupSkippedNoChanges:`Backup skipped - no changes`,backupFailed2:`Backup failed: {{message}}`,clearedLogs:`Cleared {{count}} logs`,failedToClearLogs:`Failed to clear logs: {{message}}`,history:`History`,clear:`Clear`,date:`Date`,status:`Status`,commit:`Commit`,localBackup:`Local Backup`,localBackupDescription:`Create a complete backup of your Bambuddy data including the database, archives, uploads, and all files.`,downloadBackupLabel:`Download Backup`,completeBackupZip:`Complete backup: database + all files (ZIP)`,download:`Download`,preparingBackup:`Preparing backup...`,creatingArchive:`Creating backup archive... This may take a while for large archives.`,downloadingFile:`Downloading backup file...`,backupDownloaded:`Backup downloaded successfully`,failedToCreateBackup:`Failed to create backup: {{message}}`,restore:`Restore`,restoreReplacesAll:`Restore replaces all data.`,restoreReplacesAllDetail:`Your current database and files will be completely replaced. A restart is required after restore.`,restoreConfirmTitle:`Restore Backup`,restoreConfirmMessage:`Are you sure you want to restore from "{{filename}}"? This will completely replace your current database and all files. The application will need to be restarted after restore.`,restoreConfirmButton:`Restore Backup`,uploadingFile:`Uploading backup file...`,backupRestoredRestart:`Backup restored. Please restart Bambuddy.`,failedToRestore:`Failed to restore backup. Please check the file format.`,reloadNow:`Reload Now`,creatingBackup:`Creating Backup`,restoringBackup:`Restoring Backup`,preparing:`Preparing...`,processing:`Processing...`,doNotClosePage:`Please do not close this page or navigate away. This operation may take several minutes for large backups.`,restoring:`Restoring...`,restoreComplete:`Restore Complete`,restoreFailed2:`Restore Failed`,importSettings:`Import settings from a backup file`,pleaseWaitRestoring:`Please wait while your data is being restored`,selectBackupFile:`Click to select backup file (.json or .zip)`,duplicateHandling:`How duplicate handling works:`,matchPrinters:`Printers`,matchPrintersBy:`matched by serial number`,matchSmartPlugs:`Smart Plugs`,matchSmartPlugsBy:`matched by IP address`,matchNotificationProviders:`Notification Providers`,matchNotificationProvidersBy:`matched by name`,matchFilaments:`Filaments`,matchFilamentsBy:`matched by name + type + brand`,matchArchives:`Archives`,matchArchivesBy:`matched by content hash (always skipped)`,matchPendingUploads:`Pending Uploads`,matchPendingUploadsBy:`matched by filename`,matchSettingsTemplates:`Settings & Templates`,matchSettingsTemplatesBy:`always overwritten`,replaceExisting:`Replace existing data`,keepExisting:`Keep existing data`,overwriteDescription:`Overwrite items that already exist with backup data`,keepDescription:`Only restore items that don't already exist`,overwriteCaution:`Caution:`,overwriteWarning:`Overwriting will replace your current configurations with data from the backup. Printer access codes are never overwritten for security.`,cancel:`Cancel`,processingBackup:`Processing backup file...`,itemsRestored:`Items Restored`,itemsSkipped:`Items Skipped`,restored:`Restored`,skippedAlreadyExist:`Skipped (already exist)`,filesCategory:`Files (3MF, thumbnails, etc.)`,andMore:`...and {{count}} more`,newApiKeysGenerated:`New API Keys Generated`,keysShownOnce:`These keys are only shown once. Copy them now!`,copy:`Copy`,noDataFound:`No data was found to restore in the backup file.`,close:`Close`,scheduledBackup:`Scheduled Backups`,scheduledBackupDescription:`Automatically create backup snapshots on a schedule. Output directory can be mounted to a NAS or external storage.`,frequency:`Frequency`,backupTime:`Time`,retention:`Retention`,retentionDescription:`Number of backups to keep`,outputPath:`Output Path`,outputPathPlaceholder:`Default: {{path}}`,outputPathDescription:`Leave empty for default location`,runNow:`Run Now`,backupFiles:`Backup Files`,noScheduledBackups:`No backups yet`,deleteBackup:`Delete`,deleteBackupConfirm:`Delete this backup file?`,backupRunning:`Backup in progress...`,scheduledBackupComplete:`Backup completed successfully`,scheduledBackupFailed:`Backup failed`,nextBackup:`Next backup`,backupSize:`Size`,localTimeHint:`Local time ({{tz}})`,defaultPathLabel:`Default:`,pathCheck:{title:`Bambuddy cannot write to this directory`,howToFix:`How to fix:`,sandboxed:`The Bambuddy service cannot write to {{path}}. Its systemd unit runs with ProtectSystem=strict, which makes every directory outside the install, data and log directories read-only for the service - even one you can write to from your own shell.`,read_only:`{{path}} is on a read-only filesystem.`,permission_denied:`Bambuddy is not allowed to write to {{path}}. Check the directory owner and permissions.`,no_space:`The filesystem holding {{path}} is full.`,not_a_directory:`{{path}} exists but is not a directory.`,missing:`{{path}} does not exist and could not be created.`,error:`Bambuddy cannot write to {{path}}.`,ephemeralTitle:`These backups will not survive a container restart`,container_ephemeral:`{{path}} is inside the Bambuddy container, not on the host. Backups written there are lost when the container is recreated. Mount the directory from the host:`},categories:{settings:`Settings`,notification_providers:`Notification Providers`,notification_templates:`Notification Templates`,smart_plugs:`Smart Plugs`,printers:`Printers`,filaments:`Filaments`,maintenance_types:`Maintenance Types`,archives:`Archives`,projects:`Projects`,pending_uploads:`Pending Uploads`,external_links:`External Links`,api_keys:`API Keys`}},tags:{title:`Tags`,addTag:`Add Tag`,editTag:`Edit Tag`,deleteTag:`Delete Tag`,tagName:`Tag Name`,tagColor:`Tag Color`,noTags:`No tags`,deleteConfirm:`Are you sure you want to delete this tag?`,manageTags:`Manage Tags`},uploadModal:{title:`Upload 3MF Files`,dragDrop:`Drag & drop .3mf files here`,or:`or`,browseFiles:`Browse Files`,extractionInfo:`The printer model will be automatically extracted from the 3MF file metadata.`,uploaded:`uploaded`,failed:`failed`,uploading:`Uploading...`,upload:`Upload`,uploadFailed:`Upload failed`},editArchive:{title:`Edit Archive`,name:`Name`,namePlaceholder:`Print name`,printer:`Printer`,noPrinter:`No printer`,project:`Project`,noProject:`No project`,itemsPrinted:`Items Printed`,itemsPrintedHelp:`Number of items produced in this print job`,notes:`Notes`,notesPlaceholder:`Add notes about this print...`,externalLink:`External Link`,externalLinkPlaceholder:`https://printables.com/model/...`,externalLinkHelp:`Link to Printables, Thingiverse, or other source`,tags:`Tags`,tagsPlaceholder:`Add tags...`,addMoreTags:`Add more tags...`,matchingTags:`Matching "{{query}}"`,existingTags:`Existing tags`,clickToAdd:`(click to add)`,status:`Status`,failureReason:`Failure Reason`,selectReason:`Select reason...`,photos:`Photos of Printed Result`,photosHelp:`Click + to add photos of your printed result`,printResult:`Print result`,saving:`Saving...`,failureReasons:{adhesionFailure:`Adhesion failure`,spaghettiDetached:`Spaghetti / Detached`,layerShift:`Layer shift`,cloggedNozzle:`Clogged nozzle`,filamentRunout:`Filament runout`,warping:`Warping`,stringing:`Stringing`,underExtrusion:`Under-extrusion`,powerFailure:`Power failure`,userCancelled:`User cancelled`,other:`Other`},statuses:{completed:`Completed`,failed:`Failed`,aborted:`Cancelled`,printing:`Printing`}},kProfiles:{title:`K-Profiles`,noPrintersConfigured:`No Printers Configured`,addPrinterInSettings:`Add a printer in Settings to manage K-profiles`,noActivePrinters:`No Active Printers`,enablePrinterConnection:`Enable a printer connection to view its K-profiles`,loadingProfiles:`Loading K-Profiles...`,printerOffline:`Printer Offline`,printerOfflineDesc:`The selected printer is not connected. Power it on to view K-profiles.`,noMatchingProfiles:`No Matching Profiles`,noMatchingProfilesDesc:`No profiles match your search criteria`,noKProfiles:`No K-Profiles`,noKProfilesDesc:`No pressure advance profiles found for {{diameter}}mm nozzle`,createFirstProfile:`Create First Profile`,printer:`Printer`,nozzle:`Nozzle`,refresh:`Refresh`,addProfile:`Add Profile`,export:`Export`,import:`Import`,select:`Select`,selectAll:`Select All`,delete:`Delete`,searchPlaceholder:`Search by name or filament...`,allExtruders:`All Extruders`,leftOnly:`Left Only`,rightOnly:`Right Only`,allFlow:`All Flow`,hfOnly:`HF Only`,sOnly:`S Only`,sortName:`Sort: Name`,sortKValue:`Sort: K-Value`,sortFilament:`Sort: Filament`,leftExtruder:`Left Extruder`,rightExtruder:`Right Extruder`,modal:{addTitle:`Add K-Profile`,editTitle:`Edit K-Profile`,profileName:`Profile Name`,profileNamePlaceholder:`My PLA Profile`,kValue:`K-Value`,kValuePlaceholder:`0.020`,kValueHelp:`Typical range: 0.01 - 0.06 for PLA, 0.02 - 0.10 for PETG`,filament:`Filament`,selectFilament:`Select filament...`,source:{local:`Imported`,orcaCloud:`Orca Cloud`,bambuCloud:`Bambu Cloud`,builtin:`Built-in`},noFilamentsHelp:`No filaments available. Sign in to Bambu Cloud, or import presets under Profiles → Local Profiles.`,searchFilaments:`Search filaments...`,noFilamentMatches:`No filament matches that search`,flowType:`Flow Type`,highFlow:`High Flow`,standard:`Standard`,nozzleSize:`Nozzle Size`,extruder:`Extruder`,extruders:`Extruders`,left:`Left`,right:`Right`,notes:`Notes (stored locally)`,notesPlaceholder:`Add notes about this profile...`,notesHelp:`Notes are saved in Bambuddy, not on the printer`,syncing:`Syncing with printer...`,savingExtruder:`Saving to extruder {{current}}/{{total}}...`,pleaseWait:`Please wait`},deleteConfirm:{title:`Delete Profile`,cannotUndo:`This cannot be undone`,message:`Are you sure you want to delete "{{name}}" from the printer?`},bulkDelete:{title:`Delete Profiles`,cannotUndo:`This cannot be undone`,message:`Are you sure you want to delete {{count}} selected profiles from the printer?`},toast:{profileSaved:`K-profile saved`,profilesSaved:`K-profile saved to {{count}} extruders`,selectAtLeastOneExtruder:`Please select at least one extruder`,selectFilament:`Select a filament first`,filamentNotResolvable:`No Bambu filament ID for {{name}} — the printer cannot store a profile for it`,profileDeleted:`K-profile deleted`,profilesDeleted:`Deleted {{count}} profiles`,exportedProfiles:`Exported {{count}} profiles`,importedProfiles:`Imported {{count}} of {{total}} profiles`,noProfilesToExport:`No profiles to export`,invalidFileFormat:`Invalid file format`,failedToParseImport:`Failed to parse import file`,failedToSaveBatch:`Failed to save K-profiles`,noteSaved:`Note saved`,failedToSaveNote:`Failed to save note`},permission:{noRead:`You do not have permission to refresh profiles`,noCreate:`You do not have permission to add profiles`,noUpdate:`You do not have permission to update K-profiles`,noDelete:`You do not have permission to delete K-profiles`,noExport:`You do not have permission to export profiles`,noImport:`You do not have permission to import profiles`}},virtualPrinter:{title:`Virtual Printer`,running:`Running`,stopped:`Stopped`,description:{default:`Enable a virtual printer that appears in Bambu Studio and OrcaSlicer. Files sent to this printer will be archived directly without printing.`,proxy:`Enable a proxy that relays slicer traffic to a real printer, allowing remote printing over any network.`},enable:{title:`Enable Virtual Printer`,visibleInSlicer:`Visible as "Bambuddy" in slicer discovery`,proxyingTo:`Proxying to {{name}}`,notActive:`Not active`},model:{title:`Printer Model`,description:`Select which printer model to emulate.`,restartWarning:`Changing the model will restart the virtual printer`},accessCode:{title:`Access Code`,isSet:`Access code is set`,notSet:`No access code set - required to enable`,placeholder:`Enter 8-char code`,placeholderChange:`Enter new code to change`,hint:`Must be exactly 8 characters. Used by slicers to authenticate.`,charCount:`({{count}}/8)`,inheritedFromTarget:`Inherited from target`,derivedFromTargetHint:`Uses the target printer's access code. The bridge forwards slicer auth to the real printer, so the codes must match — edit the printer's access code to change this value.`,reveal:`Show access code`,hide:`Hide access code`},targetPrinter:{title:`Target Printer`,configured:`Proxy target configured`,notConfigured:`No target printer selected - required for proxy mode`,placeholder:`Select a printer...`,hint:`Select the printer to proxy slicer traffic to. The printer must be in LAN mode.`,noPrinters:`No printers configured. Add a printer first to use proxy mode.`},remoteInterface:{title:`Network Interface Override`,configured:`Interface override active`,optional:`Optional - use if auto-detected IP is wrong (e.g. multiple NICs, Docker, VPN)`,placeholder:`Auto-detect (default)...`,hint:`Override the IP address advertised via SSDP and used in the TLS certificate. Useful when Bambuddy has multiple network interfaces.`},mode:{title:`Mode`,archive:`Archive`,archiveDesc:`Archive files immediately`,review:`Review`,reviewDesc:`Review before archiving`,queue:`Queue`,queueDesc:`Archive and add to queue`,proxy:`Proxy`,proxyDesc:`Relay to real printer`},autoDispatch:{title:`Auto-dispatch`,description:`Automatically start prints when added to queue. When off, prints wait for manual dispatch.`},queueForceColorMatch:{title:`Force color match`,description:`Refuse to dispatch onto a printer that does not have the exact filament type and color loaded. Off by default — without this, the queue uses model-only matching and may pick a printer with the wrong color loaded.`},saveAmsMapping:{title:`Save AMS mapping`,description:`Persist the slicer's own AMS-slot pick (from the project_file MQTT command) onto the archive, so a later reprint reuses the exact physical spool instead of re-deriving one from the file's type/color. Off by default.`},gcodeInjection:{title:`G-code injection`,description:`Apply the per-model G-code snippets configured in Settings to jobs from this VP. Off by default.`},tailscaleDisabled:{title:`Tailscale integration`,description:`Enable to mark this VP as exposed over Tailscale. Shows the host's Tailscale address so you know which IP to paste into the slicer. The CA-import step is unchanged — this toggle has no effect on certificates.`},setupRequired:{title:`Setup Required`,description:`The virtual printer feature requires additional system configuration before it will work. This includes port forwarding, firewall rules, and platform-specific settings.`,readGuide:`Read the setup guide before enabling`},archiveNameSource:{title:`Archive name source`,description:`Choose how new archives are named when files arrive via the virtual printer. "Metadata" uses the slicer-embedded Title from the 3MF (default). "Filename" uses the filename Bambu Studio sent over FTP. Note: Bambu Studio overwrites the name you type in the "send to printer" dialog with the 3MF's Title field whenever one is present, so both modes often produce the same string.`,metadata:`Metadata`,filename:`Filename`},caCert:{title:`Slicer certificate`,description:`Virtual printers use a TLS certificate signed by the Bambuddy CA. Import this CA certificate into your slicer's trust store once so it accepts the connection — no need to copy it from the command line.`,copy:`Copy`,copied:`Copied`,download:`Download`,fingerprint:`SHA-256`},howItWorks:{title:`How it works`,step1:`On the same LAN, virtual printers appear in your slicer (Bambu Studio / OrcaSlicer) automatically via discovery. From other networks, add them manually by IP address and access code.`,step2:`In Archive, Review, and Queue modes, use the "Send" button in your slicer to upload 3MF files to Bambuddy. The slicer will show "Print success" — the file is stored, not printed.`,step3:`In Proxy mode, the virtual printer relays all traffic to a real printer — prints start immediately as if connected directly.`},status:{title:`Status Details`,printerName:`Printer Name`,model:`Model`,serialNumber:`Serial Number`,mode:`Mode`,pendingFiles:`Pending Files`,targetPrinter:`Target Printer`,ftpPort:`FTP Port`,mqttPort:`MQTT Port`,ftpConnections:`FTP Connections`,mqttConnections:`MQTT Connections`},toast:{updated:`Virtual printer settings updated`,failedToUpdate:`Failed to update settings`,copyFailed:`Failed to copy — try selecting the text manually`,accessCodeRequired:`Please set an access code first`,targetPrinterRequired:`Please select a target printer first`,bindIpRequired:`Please set a bind IP first`,accessCodeEmpty:`Access code cannot be empty`,accessCodeLength:`Access code must be exactly 8 characters`,targetCodeChangedRebind:`Access code now matches the new target printer. Re-add this device in your slicer to pick up the new code.`,created:`Virtual printer created`,failedToCreate:`Failed to create virtual printer`,deleted:`Virtual printer deleted`,failedToDelete:`Failed to delete virtual printer`},list:{title:`Virtual Printers`,add:`Add`,addFirst:`Add Virtual Printer`,empty:`No virtual printers configured. Add one to get started.`},bindIp:{title:`Bind Interface`,placeholder:`Select interface...`,hint:`Network interface for this virtual printer to bind to. Must be unique per printer.`},proxy:{accessCodeHint:`In proxy mode, use your target printer's access code in the slicer. The connection is forwarded transparently to the real printer.`},addDialog:{title:`Add Virtual Printer`,name:`Name`,hint:`You can configure access code, target printer, and other settings after creating.`,create:`Create`},deleteConfirm:{title:`Delete Virtual Printer`,message:`Are you sure you want to delete "{{name}}"? This will stop all services for this printer.`}},modelViewer:{openInSlicer:`Open in Slicer`,tabs:{model:`3D Model`,gcode:`G-code Preview`},notAvailable:`not available`,notSliced:`not sliced`,plates:`Plates`,allPlates:`All Plates`,plateNumber:`Plate {{number}}`,plateCount:`{{count}} plate`,plateCount_other:`{{count}} plates`,objectCount:`{{count}} object`,objectCount_other:`{{count}} objects`,filamentCount:`{{count}} filament`,filamentCount_other:`{{count}} filaments`,eta:`ETA {{minutes}} min`,noPreview:`No preview available for this file`,pagination:{pageOf:`Page {{current}} of {{total}}`,prev:`Prev`,next:`Next`},errors:{failedToLoad:`Failed to load file`,noMeshes:`No meshes found in 3MF file`,unsupportedFormat:`Unsupported file format`}},maintenanceDescriptions:{lubricateCarbonRods:`Apply lubricant to carbon rods for smooth motion`,lubricateRails:`Apply lubricant to linear rails for smooth motion`,cleanNozzle:`Clean hotend and nozzle to prevent clogs`,checkBelts:`Verify belt tension for accurate prints`,cleanBuildPlate:`Clean build plate for better adhesion`,checkExtruder:`Inspect extruder gears for wear`,checkCooling:`Ensure cooling fans are working properly`,generalInspection:`General printer inspection`,cleanCarbonRods:`Clean carbon rods to reduce friction`,lubricateSteelRods:`Apply lubricant to steel rods for smooth motion`,cleanSteelRods:`Clean steel rods to reduce friction`,cleanLinearRails:`Wipe linear rails to remove dust and debris`,checkPtfeTube:`Inspect PTFE tube for wear or damage`,replaceHepaFilter:`Replace HEPA filter for air quality`,replaceCarbonFilter:`Replace activated carbon filter`,lubricateLeftNozzleRail:`Lubricate left nozzle rail (H2 series)`},smartPlugs:{offline:`Offline`,admin:`Admin`,openPlugAdminPage:`Open plug admin page`,deleteSmartPlug:`Delete Smart Plug`,turnOnSmartPlug:`Turn On Smart Plug`,turnOffSmartPlug:`Turn Off Smart Plug`,turnOn:`Turn On`,turnOff:`Turn Off`,addSmartPlug:{scanningNetwork:`Scanning network...`,chooseEntity:`Choose an entity...`,connectionFailed:`Connection failed`,searchEntities:`Search entities...`,searchPowerSensors:`Search power sensors...`,searchEnergySensors:`Search energy sensors...`,placeholders:{plugName:`Living Room Plug`,mqttStateOnValue:`ON, true, 1`,mqttSameAsPower:`Same as power topic, or different`}},linkedTo:`Linked to:`,monitorOnly:`Monitor Only`,alerts:`Alerts`,scheduleOn:`On {{time}}`,scheduleOff:`Off {{time}}`,on:`On`,off:`Off`,power:`Power`,kwhToday:`kWh Today`,settings:`Settings`,automationSettings:`Automation Settings`,showInSwitchbar:`Show in Switchbar`,quickAccessSidebar:`Quick access from sidebar`,enabled:`Enabled`,enableAutomation:`Enable automation for this plug`,autoOn:`Auto On`,autoOnDescription:`Turn on when print starts`,autoOff:`Auto Off`,autoOffDescription:`Turn off when print completes (one-shot)`,autoOffPersistent:`Keep Enabled`,autoOffPersistentDescription:`Stay enabled between prints instead of one-shot`,controlsPrinterPower:`Powers the printer`,controlsPrinterPowerDescription:`Turn off if this plug only powers an accessory (filter fan, lights). Otherwise switching it off marks the printer offline.`,autoOffAfterDrying:`Auto Off After Drying`,autoOffAfterDryingDescription:`Turn off when AMS drying completes`,delayAfterDryingMinutes:`Drying delay (minutes)`,turnOffDelayMode:`Turn Off Delay Mode`,time:`Time`,temp:`Temp`,delayMinutes:`Delay (minutes)`,tempThreshold:`Temperature threshold (°C)`,tempThresholdDescription:`Turns off when nozzle cools below this temperature`,edit:`Edit`,deleteConfirm:`Are you sure you want to delete "{{name}}"? This cannot be undone.`,turnOnConfirm:`Are you sure you want to turn on "{{name}}"?`,turnOffConfirm:`Are you sure you want to turn off "{{name}}"? This will cut power to the connected device.`,failedToTurn:`Failed to turn {{action}} "{{name}}"`,unknown:`Unknown`,addTitle:`Add Smart Plug`,editTitle:`Edit Smart Plug`,stopScanning:`Stop Scanning`,discoverTasmota:`Discover Tasmota Devices`,foundDevices:`Found {{count}} device(s) - click to select:`,noDevicesFound:`No Tasmota devices found on your network`,haNotConfigured:`Home Assistant is not configured. Set it up in`,haSettingsPath:`Settings → Network → Home Assistant`,selectEntity:`Select Entity *`,ipAddress:`IP Address *`,nameLabel:`Name *`,username:`Username`,password:`Password`,authHint:`Leave empty if your Tasmota device doesn't require authentication`,linkToPrinter:`Link to Printer`,noPrinter:`No printer (manual control only)`,linkingDescription:`Linking enables automatic on/off when prints start/complete`,powerAlerts:`Power Alerts`,alertAbove:`Alert if above (W)`,alertBelow:`Alert if below (W)`,alertDescription:`Get notified when power consumption crosses these thresholds. Leave empty to disable that direction.`,dailySchedule:`Daily Schedule`,turnOnAt:`Turn On at`,turnOffAt:`Turn Off at`,scheduleDescription:`Automatically turn the plug on/off at these times daily. Leave empty to skip that action.`,showOnPrinterCard:`Show on Printer Card`,displayOnPrinterCard:`Display button on printer card`,connectedResult:`Connected!`,deviceLabel:`Device: {{name}} - `,stateLabel:`State: {{state}}`,test:`Test`,delete:`Delete`,save:`Save`,add:`Add`,cancel:`Cancel`,failedToStartScan:`Failed to start scan`,nameRequired:`Name is required`,entityRequired:`Entity is required for Home Assistant plugs`,mqttTopicRequired:`At least one MQTT topic must be configured for power, energy, or state monitoring`,loadingEntities:`Loading entities...`,loading:`Loading...`,failedToLoadEntities:`Failed to load entities: {{error}}`,noEntitiesMatching:`No entities found matching "{{search}}"`,noEntitiesAvailable:`No entities available`,searchingEntities:`Searching all entities ({{count}} found)`,showingEntities:`Showing switch, light, input_boolean ({{count}} available)`,energyMonitoringOptional:`Energy Monitoring (Optional)`,energyMonitoringHint:`Search and select sensors that provide power/energy data.`,powerSensorW:`Power Sensor (W)`,energyTodayKwh:`Energy Today (kWh)`,totalEnergyKwh:`Total Energy (kWh)`,noMatchingSensors:`No matching sensors`,none:`None`,mqttNotConfigured:`MQTT broker not configured. Set broker address in`,mqttSettingsPath:`Settings → Network → MQTT Publishing`,mqttNotConfiguredSuffix:`(you don't need to enable publishing, just fill in the broker details).`,mqttMonitorOnlyDescription:`MQTT plugs receive power/energy data via MQTT subscription. On/off control is not available - use your MQTT broker or home automation system.`,powerMonitoring:`Power Monitoring`,energyMonitoring:`Energy Monitoring`,stateMonitoring:`State Monitoring`,optional:`optional`,topic:`Topic`,jsonPath:`JSON Path`,multiplier:`Multiplier`,onValue:`ON Value`,mqttPowerHint:`JSON path extracts value from JSON payload (e.g., "power_l1"). Leave empty if topic publishes raw numeric values. +`+e.stack}}var me=Object.prototype.hasOwnProperty,he=t.unstable_scheduleCallback,ge=t.unstable_cancelCallback,_e=t.unstable_shouldYield,ve=t.unstable_requestPaint,ye=t.unstable_now,be=t.unstable_getCurrentPriorityLevel,xe=t.unstable_ImmediatePriority,Se=t.unstable_UserBlockingPriority,Ce=t.unstable_NormalPriority,we=t.unstable_LowPriority,Te=t.unstable_IdlePriority,Ee=t.log,De=t.unstable_setDisableYieldValue,Oe=null,ke=null;function Ae(e){if(typeof Ee==`function`&&De(e),ke&&typeof ke.setStrictMode==`function`)try{ke.setStrictMode(Oe,e)}catch{}}var je=Math.clz32?Math.clz32:Pe,Me=Math.log,Ne=Math.LN2;function Pe(e){return e>>>=0,e===0?32:31-(Me(e)/Ne|0)|0}var Fe=256,Ie=262144,Le=4194304;function Re(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function ze(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=Re(n))):i=Re(o):i=Re(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=Re(n))):i=Re(o)):i=Re(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function Be(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function Ve(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function He(){var e=Le;return Le<<=1,!(Le&62914560)&&(Le=4194304),e}function Ue(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function We(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function Ge(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0`u`||window.document===void 0||window.document.createElement===void 0),nn=!1;if(tn)try{var rn={};Object.defineProperty(rn,"passive",{get:function(){nn=!0}}),window.addEventListener(`test`,rn,rn),window.removeEventListener(`test`,rn,rn)}catch{nn=!1}var an=null,on=null,sn=null;function cn(){if(sn)return sn;var e,t=on,n=t.length,r,i=`value`in an?an.value:an.textContent,a=i.length;for(e=0;e=Bn),Un=` `,Wn=!1;function Gn(e,t){switch(e){case`keyup`:return Rn.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function Kn(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var qn=!1;function Jn(e,t){switch(e){case`compositionend`:return Kn(t);case`keypress`:return t.which===32?(Wn=!0,Un):null;case`textInput`:return e=t.data,e===Un&&Wn?null:e;default:return null}}function Yn(e,t){if(qn)return e===`compositionend`||!zn&&Gn(e,t)?(e=cn(),sn=on=an=null,qn=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=_r(n)}}function yr(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?yr(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function br(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=At(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=At(e.document)}return t}function xr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var Sr=tn&&`documentMode`in document&&11>=document.documentMode,Cr=null,wr=null,Tr=null,Er=!1;function Dr(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Er||Cr==null||Cr!==At(r)||(r=Cr,`selectionStart`in r&&xr(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),Tr&&gr(Tr,r)||(Tr=r,r=Dd(wr,`onSelect`),0>=o,i-=o,yi=1<<32-je(t)+i|n<h?(g=d,d=null):g=d.sibling;var _=p(i,d,s[h],c);if(_===null){d===null&&(d=g);break}e&&d&&_.alternate===null&&t(i,d),a=o(_,a,h),u===null?l=_:u.sibling=_,u=_,d=g}if(h===s.length)return n(i,d),Oi&&xi(i,h),l;if(d===null){for(;hg?(_=h,h=null):_=h.sibling;var y=p(a,h,v.value,l);if(y===null){h===null&&(h=_);break}e&&h&&y.alternate===null&&t(a,h),s=o(y,s,g),d===null?u=y:d.sibling=y,d=y,h=_}if(v.done)return n(a,h),Oi&&xi(a,g),u;if(h===null){for(;!v.done;g++,v=c.next())v=f(a,v.value,l),v!==null&&(s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return Oi&&xi(a,g),u}for(h=r(h);!v.done;g++,v=c.next())v=m(h,a,g,v.value,l),v!==null&&(e&&v.alternate!==null&&h.delete(v.key===null?g:v.key),s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return e&&h.forEach(function(e){return t(a,e)}),Oi&&xi(a,g),u}function b(e,r,o,c){if(typeof o==`object`&&o&&o.type===y&&o.key===null&&(o=o.props.children),typeof o==`object`&&o){switch(o.$$typeof){case _:a:{for(var l=o.key;r!==null;){if(r.key===l){if(l=o.type,l===y){if(r.tag===7){n(e,r.sibling),c=a(r,o.props.children),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===O&&Sa(l)===r.type){n(e,r.sibling),c=a(r,o.props),ka(c,o),c.return=e,e=c;break a}n(e,r);break}else t(e,r);r=r.sibling}o.type===y?(c=oi(o.props.children,e.mode,c,o.key),c.return=e,e=c):(c=ai(o.type,o.key,o.props,null,e.mode,c),ka(c,o),c.return=e,e=c)}return s(e);case v:a:{for(l=o.key;r!==null;){if(r.key===l)if(r.tag===4&&r.stateNode.containerInfo===o.containerInfo&&r.stateNode.implementation===o.implementation){n(e,r.sibling),c=a(r,o.children||[]),c.return=e,e=c;break a}else{n(e,r);break}else t(e,r);r=r.sibling}c=li(o,e.mode,c),c.return=e,e=c}return s(e);case O:return o=Sa(o),b(e,r,o,c)}if(F(o))return h(e,r,o,c);if(M(o)){if(l=M(o),typeof l!=`function`)throw Error(i(150));return o=l.call(o),g(e,r,o,c)}if(typeof o.then==`function`)return b(e,r,Oa(o),c);if(o.$$typeof===C)return b(e,r,Xi(e,o),c);Aa(e,o)}return typeof o==`string`&&o!==``||typeof o==`number`||typeof o==`bigint`?(o=``+o,r!==null&&r.tag===6?(n(e,r.sibling),c=a(r,o),c.return=e,e=c):(n(e,r),c=si(o,e.mode,c),c.return=e,e=c),s(e)):n(e,r)}return function(e,t,n,r){try{Da=0;var i=b(e,t,n,r);return Ea=null,i}catch(t){if(t===ga||t===va)throw t;var a=ti(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var Ma=ja(!0),Na=ja(!1),Pa=!1;function Fa(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Ia(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function La(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Ra(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,Fl&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=Qr(e),Zr(e,null,n),t}return Jr(e,r,t,n),Qr(e)}function za(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,qe(e,n)}}function Ba(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var Va=!1;function Ha(){if(Va){var e=sa;if(e!==null)throw e}}function Ua(e,t,n,r){Va=!1;var i=e.updateQueue;Pa=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var f=s.lane&-536870913,m=f!==s.lane;if(m?(Rl&f)===f:(r&f)===f){f!==0&&f===oa&&(Va=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var h=e,g=s;f=t;var _=n;switch(g.tag){case 1:if(h=g.payload,typeof h==`function`){d=h.call(_,d,f);break a}d=h;break a;case 3:h.flags=h.flags&-65537|128;case 0:if(h=g.payload,f=typeof h==`function`?h.call(_,d,f):h,f==null)break a;d=p({},d,f);break a;case 2:Pa=!0}}f=s.callback,f!==null&&(e.flags|=64,m&&(e.flags|=8192),m=i.callbacks,m===null?i.callbacks=[f]:m.push(f))}else m={lane:f,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=m,c=d):u=u.next=m,o|=f;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;m=s,s=m.next,m.next=null,i.lastBaseUpdate=m,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),Kl|=o,e.lanes=o,e.memoizedState=d}}function Wa(e,t){if(typeof e!=`function`)throw Error(i(191,e));e.call(t)}function Ga(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=I.T,s={};I.T=s,ks(e,!1,t,n);try{var c=i(),l=I.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?Os(e,t,ua(c,r),mu(e)):Os(e,t,r,mu(e))}catch(n){Os(e,t,{then:function(){},status:`rejected`,reason:n},mu())}finally{L.p=a,o!==null&&s.types!==null&&(o.types=s.types),I.T=o}}function vs(){}function ys(e,t,n,r){if(e.tag!==5)throw Error(i(476));var a=bs(e).queue;_s(e,a,t,R,n===null?vs:function(){return xs(e),n(r)})}function bs(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:R,baseState:R,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Y,lastRenderedState:R},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Y,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function xs(e){var t=bs(e);t.next===null&&(t=e.alternate.memoizedState),Os(e,t.next.queue,{},mu())}function Ss(){return Yi(Zf)}function Cs(){return To().memoizedState}function ws(){return To().memoizedState}function Ts(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=mu();e=La(n);var r=Ra(t,e,n);r!==null&&(gu(r,t,n),za(r,t,n)),t={cache:na()},e.payload=t;return}t=t.return}}function Es(e,t,n){var r=mu();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},As(e)?js(t,n):(n=Yr(e,t,n,r),n!==null&&(gu(n,e,r),Ms(n,t,r)))}function Ds(e,t,n){Os(e,t,n,mu())}function Os(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(As(e))js(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,hr(s,o))return Jr(e,t,i,0),Il===null&&qr(),!1}catch{}if(n=Yr(e,t,i,r),n!==null)return gu(n,e,r),Ms(n,t,r),!0}return!1}function ks(e,t,n,r){if(r={lane:2,revertLane:dd(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},As(e)){if(t)throw Error(i(479))}else t=Yr(e,n,r,2),t!==null&&gu(t,e,2)}function As(e){var t=e.alternate;return e===oo||t!==null&&t===oo}function js(e,t){uo=lo=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Ms(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,qe(e,n)}}var Ns={readContext:Yi,use:Oo,useCallback:_o,useContext:_o,useEffect:_o,useImperativeHandle:_o,useLayoutEffect:_o,useInsertionEffect:_o,useMemo:_o,useReducer:_o,useRef:_o,useState:_o,useDebugValue:_o,useDeferredValue:_o,useTransition:_o,useSyncExternalStore:_o,useId:_o,useHostTransitionStatus:_o,useFormState:_o,useActionState:_o,useOptimistic:_o,useMemoCache:_o,useCacheRefresh:_o};Ns.useEffectEvent=_o;var Ps={readContext:Yi,use:Oo,useCallback:function(e,t){return wo().memoizedState=[e,t===void 0?null:t],e},useContext:Yi,useEffect:rs,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),ts(4194308,4,us.bind(null,t,e),n)},useLayoutEffect:function(e,t){return ts(4194308,4,e,t)},useInsertionEffect:function(e,t){ts(4,2,e,t)},useMemo:function(e,t){var n=wo();t=t===void 0?null:t;var r=e();if(fo){Ae(!0);try{e()}finally{Ae(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=wo();if(n!==void 0){var i=n(t);if(fo){Ae(!0);try{n(t)}finally{Ae(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=Es.bind(null,oo,e),[r.memoizedState,e]},useRef:function(e){var t=wo();return e={current:e},t.memoizedState=e},useState:function(e){e=zo(e);var t=e.queue,n=Ds.bind(null,oo,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:fs,useDeferredValue:function(e,t){return hs(wo(),e,t)},useTransition:function(){var e=zo(!1);return e=_s.bind(null,oo,e.queue,!0,!1),wo().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=oo,a=wo();if(Oi){if(n===void 0)throw Error(i(407));n=n()}else{if(n=t(),Il===null)throw Error(i(349));Rl&127||Po(r,t,n)}a.memoizedState=n;var o={value:n,getSnapshot:t};return a.queue=o,rs(Io.bind(null,r,o,e),[e]),r.flags|=2048,$o(9,{destroy:void 0},Fo.bind(null,r,o,n,t),null),n},useId:function(){var e=wo(),t=Il.identifierPrefix;if(Oi){var n=bi,r=yi;n=(r&~(1<<32-je(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=po++,0<\/script>`,o=o.removeChild(o.firstChild);break;case`select`:o=typeof r.is==`string`?s.createElement(`select`,{is:r.is}):s.createElement(`select`),r.multiple?o.multiple=!0:r.size&&(o.size=r.size);break;default:o=typeof r.is==`string`?s.createElement(a,{is:r.is}):s.createElement(a)}}o[et]=t,o[tt]=r;a:for(s=t.child;s!==null;){if(s.tag===5||s.tag===6)o.appendChild(s.stateNode);else if(s.tag!==4&&s.tag!==27&&s.child!==null){s.child.return=s,s=s.child;continue}if(s===t)break a;for(;s.sibling===null;){if(s.return===null||s.return===t)break a;s=s.return}s.sibling.return=s.return,s=s.sibling}t.stateNode=o;a:switch(Id(o,a,r),a){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&Oc(t)}}return Nc(t),kc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&Oc(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(i(166));if(e=ie.current,Fi(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,a=Ei,a!==null)switch(a.tag){case 27:case 5:r=a.memoizedProps}e[et]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||Nd(e.nodeValue,n)),e||Mi(t,!0)}else e=Hd(e).createTextNode(r),e[et]=t,t.stateNode=e}return Nc(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=Fi(t),n!==null){if(e===null){if(!r)throw Error(i(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(i(557));e[et]=t}else Ii(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;Nc(t),e=!1}else n=Li(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(ro(t),t):(ro(t),null);if(t.flags&128)throw Error(i(558))}return Nc(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(a=Fi(t),r!==null&&r.dehydrated!==null){if(e===null){if(!a)throw Error(i(318));if(a=t.memoizedState,a=a===null?null:a.dehydrated,!a)throw Error(i(317));a[et]=t}else Ii(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;Nc(t),a=!1}else a=Li(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=a),a=!0;if(!a)return t.flags&256?(ro(t),t):(ro(t),null)}return ro(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,a=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(a=r.alternate.memoizedState.cachePool.pool),o=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(o=r.memoizedState.cachePool.pool),o!==a&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),jc(t,t.updateQueue),Nc(t),null);case 4:return oe(),e===null&&Cd(t.stateNode.containerInfo),Nc(t),null;case 10:return Ui(t.type),Nc(t),null;case 19:if(ee(io),r=t.memoizedState,r===null)return Nc(t),null;if(a=(t.flags&128)!=0,o=r.rendering,o===null)if(a)Mc(r,!1);else{if(Gl!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(o=K(e),o!==null){for(t.flags|=128,Mc(r,!1),e=o.updateQueue,t.updateQueue=e,jc(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)ii(n,e),n=n.sibling;return te(io,io.current&1|2),Oi&&xi(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&ye()>nu&&(t.flags|=128,a=!0,Mc(r,!1),t.lanes=4194304)}else{if(!a)if(e=K(o),e!==null){if(t.flags|=128,a=!0,e=e.updateQueue,t.updateQueue=e,jc(t,e),Mc(r,!0),r.tail===null&&r.tailMode===`hidden`&&!o.alternate&&!Oi)return Nc(t),null}else 2*ye()-r.renderingStartTime>nu&&n!==536870912&&(t.flags|=128,a=!0,Mc(r,!1),t.lanes=4194304);r.isBackwards?(o.sibling=t.child,t.child=o):(e=r.last,e===null?t.child=o:e.sibling=o,r.last=o)}return r.tail===null?(Nc(t),null):(e=r.tail,r.rendering=e,r.tail=e.sibling,r.renderingStartTime=ye(),e.sibling=null,n=io.current,te(io,a?n&1|2:n&1),Oi&&xi(t,r.treeForkCount),e);case 22:case 23:return ro(t),Xa(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(Nc(t),t.subtreeFlags&6&&(t.flags|=8192)):Nc(t),n=t.updateQueue,n!==null&&jc(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&ee(fa),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),Ui(ta),Nc(t),null;case 25:return null;case 30:return null}throw Error(i(156,t.tag))}function Fc(e,t){switch(wi(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Ui(ta),oe(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return se(t),null;case 31:if(t.memoizedState!==null){if(ro(t),t.alternate===null)throw Error(i(340));Ii()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(ro(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(i(340));Ii()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return ee(io),null;case 4:return oe(),null;case 10:return Ui(t.type),null;case 22:case 23:return ro(t),Xa(),e!==null&&ee(fa),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return Ui(ta),null;case 25:return null;default:return null}}function Ic(e,t){switch(wi(t),t.tag){case 3:Ui(ta),oe();break;case 26:case 27:case 5:se(t);break;case 4:oe();break;case 31:t.memoizedState!==null&&ro(t);break;case 13:ro(t);break;case 19:ee(io);break;case 10:Ui(t.type);break;case 22:case 23:ro(t),Xa(),e!==null&&ee(fa);break;case 24:Ui(ta)}}function Lc(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){Ku(t,t.return,e)}}function Rc(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){Ku(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){Ku(t,t.return,e)}}function zc(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{Ga(t,n)}catch(t){Ku(e,e.return,t)}}}function Bc(e,t,n){n.props=Vs(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){Ku(e,t,n)}}function Vc(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){Ku(e,t,n)}}function Hc(e,t){var n=e.ref,r=e.refCleanup;if(n!==null)if(typeof r==`function`)try{r()}catch(n){Ku(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){Ku(e,t,n)}else n.current=null}function Uc(e){var t=e.type,n=e.memoizedProps,r=e.stateNode;try{a:switch(t){case`button`:case`input`:case`select`:case`textarea`:n.autoFocus&&r.focus();break a;case`img`:n.src?r.src=n.src:n.srcSet&&(r.srcset=n.srcSet)}}catch(t){Ku(e,e.return,t)}}function Wc(e,t,n){try{var r=e.stateNode;Ld(r,e.type,n,t),r[tt]=t}catch(t){Ku(e,e.return,t)}}function Gc(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Zd(e.type)||e.tag===4}function Kc(e){a:for(;;){for(;e.sibling===null;){if(e.return===null||Gc(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Zd(e.type)||e.flags&2||e.child===null||e.tag===4)continue a;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function qc(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?(n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n).insertBefore(e,t):(t=n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n,t.appendChild(e),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=Kt));else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode,t=null),e=e.child,e!==null))for(qc(e,t,n),e=e.sibling;e!==null;)qc(e,t,n),e=e.sibling}function Jc(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode),e=e.child,e!==null))for(Jc(e,t,n),e=e.sibling;e!==null;)Jc(e,t,n),e=e.sibling}function Yc(e){var t=e.stateNode,n=e.memoizedProps;try{for(var r=e.type,i=t.attributes;i.length;)t.removeAttributeNode(i[0]);Id(t,r,n),t[et]=e,t[tt]=n}catch(t){Ku(e,e.return,t)}}var Xc=!1,X=!1,Zc=!1,Qc=typeof WeakSet==`function`?WeakSet:Set,$c=null;function el(e,t){if(e=e.containerInfo,Bd=op,e=br(e),xr(e)){if(`selectionStart`in e)var n={start:e.selectionStart,end:e.selectionEnd};else a:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var a=r.anchorOffset,o=r.focusNode;r=r.focusOffset;try{n.nodeType,o.nodeType}catch{n=null;break a}var s=0,c=-1,l=-1,u=0,d=0,f=e,p=null;b:for(;;){for(var m;f!==n||a!==0&&f.nodeType!==3||(c=s+a),f!==o||r!==0&&f.nodeType!==3||(l=s+r),f.nodeType===3&&(s+=f.nodeValue.length),(m=f.firstChild)!==null;)p=f,f=m;for(;;){if(f===e)break b;if(p===n&&++u===a&&(c=s),p===o&&++d===r&&(l=s),(m=f.nextSibling)!==null)break;f=p,p=f.parentNode}f=m}n=c===-1||l===-1?null:{start:c,end:l}}else n=null}n||={start:0,end:0}}else n=null;for(Vd={focusedElem:e,selectionRange:n},op=!1,$c=t;$c!==null;)if(t=$c,e=t.child,t.subtreeFlags&1028&&e!==null)e.return=t,$c=e;else for(;$c!==null;){switch(t=$c,o=t.alternate,e=t.flags,t.tag){case 0:if(e&4&&(e=t.updateQueue,e=e===null?null:e.events,e!==null))for(n=0;n title`))),Id(o,r,n),o[et]=e,pt(o),r=o;break a;case`link`:var s=Bf(`link`,`href`,a).get(r+(n.href||``));if(s){for(var c=0;cg&&(o=g,g=h,h=o);var _=vr(s,h),v=vr(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,I.T=null,n=uu,uu=null;var o=ou,s=cu;if(au=0,su=ou=null,cu=0,Fl&6)throw Error(i(331));var c=Fl;if(Fl|=4,Al(o.current),Sl(o,o.current,s,n),Fl=c,od(0,!1),ke&&typeof ke.onPostCommitFiberRoot==`function`)try{ke.onPostCommitFiberRoot(Oe,o)}catch{}return!0}finally{L.p=a,I.T=r,Hu(e,t)}}function Gu(e,t,n){t=di(n,t),t=qs(e.stateNode,t,2),e=Ra(e,t,2),e!==null&&(We(e,2),ad(e))}function Ku(e,t,n){if(e.tag===3)Gu(e,e,n);else for(;t!==null;){if(t.tag===3){Gu(t,e,n);break}else if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(iu===null||!iu.has(r))){e=di(n,e),n=Js(2),r=Ra(t,n,2),r!==null&&(Ys(n,r,t,e),We(r,2),ad(r));break}}t=t.return}}function qu(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new Pl;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(Ul=!0,i.add(n),e=Ju.bind(null,e,t,n),t.then(e,e))}function Ju(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,Il===e&&(Rl&n)===n&&(Gl===4||Gl===3&&(Rl&62914560)===Rl&&300>ye()-eu?!(Fl&2)&&Cu(e,0):Jl|=n,Xl===Rl&&(Xl=0)),ad(e)}function Yu(e,t){t===0&&(t=He()),e=Xr(e,t),e!==null&&(We(e,t),ad(e))}function Xu(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),Yu(e,n)}function Zu(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,a=e.memoizedState;a!==null&&(n=a.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(i(314))}r!==null&&r.delete(t),Yu(e,n)}function Qu(e,t){return he(e,t)}var $u=null,ed=null,td=!1,nd=!1,rd=!1,id=0;function ad(e){e!==ed&&e.next===null&&(ed===null?$u=ed=e:ed=ed.next=e),nd=!0,td||(td=!0,Q())}function od(e,t){if(!rd&&nd){rd=!0;do for(var n=!1,r=$u;r!==null;){if(!t)if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-je(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,ud(r,a))}else a=Rl,a=ze(r,r===Il?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||Be(r,a)||(n=!0,ud(r,a));r=r.next}while(n);rd=!1}}function sd(){cd()}function cd(){nd=td=!1;var e=0;id!==0&&Kd()&&(e=id);for(var t=ye(),n=null,r=$u;r!==null;){var i=r.next,a=ld(r,t);a===0?(r.next=null,n===null?$u=i:n.next=i,i===null&&(ed=n)):(n=r,(e!==0||a&3)&&(nd=!0)),r=i}au!==0&&au!==5||od(e,!1),id!==0&&(id=0)}function ld(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&Rd(d)&&(c=c.responseEnd,o+=u*(c`u`?null:document;function xf(e,t,n){var r=bf;if(r&&typeof t==`string`&&t){var i=Mt(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),hf.has(i)||(hf.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),Id(t,`link`,e),pt(t),r.head.appendChild(t)))}}function Sf(e){_f.D(e),xf(`dns-prefetch`,e,null)}function Cf(e,t){_f.C(e,t),xf(`preconnect`,e,t)}function wf(e,t,n){_f.L(e,t,n);var r=bf;if(r&&e&&t){var i=`link[rel="preload"][as="`+Mt(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+Mt(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+Mt(n.imageSizes)+`"]`)):i+=`[href="`+Mt(e)+`"]`;var a=i;switch(t){case`style`:a=kf(e);break;case`script`:a=Nf(e)}mf.has(a)||(e=p({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),mf.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(Af(a))||t===`script`&&r.querySelector(Pf(a))||(t=r.createElement(`link`),Id(t,`link`,e),pt(t),r.head.appendChild(t)))}}function Tf(e,t){_f.m(e,t);var n=bf;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+Mt(r)+`"][href="`+Mt(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=Nf(e)}if(!mf.has(a)&&(e=p({rel:`modulepreload`,href:e},t),mf.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(Pf(a)))return}r=n.createElement(`link`),Id(r,`link`,e),pt(r),n.head.appendChild(r)}}}function Ef(e,t,n){_f.S(e,t,n);var r=bf;if(r&&e){var i=ft(r).hoistableStyles,a=kf(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(Af(a)))s.loading=5;else{e=p({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=mf.get(a))&&Lf(e,n);var c=o=r.createElement(`link`);pt(c),Id(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,If(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function Df(e,t){_f.X(e,t);var n=bf;if(n&&e){var r=ft(n).hoistableScripts,i=Nf(e),a=r.get(i);a||(a=n.querySelector(Pf(i)),a||(e=p({src:e,async:!0},t),(t=mf.get(i))&&Rf(e,t),a=n.createElement(`script`),pt(a),Id(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function tee(e,t){_f.M(e,t);var n=bf;if(n&&e){var r=ft(n).hoistableScripts,i=Nf(e),a=r.get(i);a||(a=n.querySelector(Pf(i)),a||(e=p({src:e,async:!0,type:`module`},t),(t=mf.get(i))&&Rf(e,t),a=n.createElement(`script`),pt(a),Id(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Of(e,t,n,r){var a=(a=ie.current)?gf(a):null;if(!a)throw Error(i(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(t=kf(n.href),n=ft(a).hoistableStyles,r=n.get(t),r||(r={type:`style`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=kf(n.href);var o=ft(a).hoistableStyles,s=o.get(e);if(s||(a=a.ownerDocument||a,s={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},o.set(e,s),(o=a.querySelector(Af(e)))&&!o._p&&(s.instance=o,s.state.loading=5),mf.has(e)||(n={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},mf.set(e,n),o||Mf(a,e,n,s.state))),t&&r===null)throw Error(i(528,``));return s}if(t&&r!==null)throw Error(i(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(t=Nf(n),n=ft(a).hoistableScripts,r=n.get(t),r||(r={type:`script`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(i(444,e))}}function kf(e){return`href="`+Mt(e)+`"`}function Af(e){return`link[rel="stylesheet"][`+e+`]`}function jf(e){return p({},e,{"data-precedence":e.precedence,precedence:null})}function Mf(e,t,n,r){e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)?r.loading=1:(t=e.createElement(`link`),r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2}),Id(t,`link`,n),pt(t),e.head.appendChild(t))}function Nf(e){return`[src="`+Mt(e)+`"]`}function Pf(e){return`script[async]`+e}function Ff(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+Mt(n.href)+`"]`);if(r)return t.instance=r,pt(r),r;var a=p({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),pt(r),Id(r,`style`,a),If(r,n.precedence,e),t.instance=r;case`stylesheet`:a=kf(n.href);var o=e.querySelector(Af(a));if(o)return t.state.loading|=4,t.instance=o,pt(o),o;r=jf(n),(a=mf.get(a))&&Lf(r,a),o=(e.ownerDocument||e).createElement(`link`),pt(o);var s=o;return s._p=new Promise(function(e,t){s.onload=e,s.onerror=t}),Id(o,`link`,r),t.state.loading|=4,If(o,n.precedence,e),t.instance=o;case`script`:return o=Nf(n.src),(a=e.querySelector(Pf(o)))?(t.instance=a,pt(a),a):(r=n,(a=mf.get(o))&&(r=p({},n),Rf(r,a)),e=e.ownerDocument||e,a=e.createElement(`script`),pt(a),Id(a,`link`,r),e.head.appendChild(a),t.instance=a);case`void`:return null;default:throw Error(i(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,If(r,n.precedence,e));return t.instance}function If(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function Hf(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function Uf(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Wf(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=kf(r.href),a=t.querySelector(Af(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=qf.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,pt(a);return}a=t.ownerDocument||t,r=jf(r),(i=mf.get(i))&&Lf(r,i),a=a.createElement(`link`),pt(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),Id(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=qf.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var Gf=0;function Kf(e,t){return e.stylesheets&&e.count===0&&Yf(e,e.stylesheets),0Gf?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function qf(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Yf(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Jf=null;function Yf(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Jf=new Map,t.forEach(Xf,e),Jf=null,qf.call(e))}function Xf(e,t){if(!(t.state.loading&4)){var n=Jf.get(e);if(n)var r=n.get(null);else{n=new Map,Jf.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=_()})),y=l(f()),b=v(),x=e=>typeof e==`string`,S=()=>{let e,t,n=new Promise((n,r)=>{e=n,t=r});return n.resolve=e,n.reject=t,n},C=e=>e==null?``:``+e,w=(e,t,n)=>{e.forEach(e=>{t[e]&&(n[e]=t[e])})},T=/###/g,E=e=>e&&e.indexOf(`###`)>-1?e.replace(T,`.`):e,D=e=>!e||x(e),O=(e,t,n)=>{let r=x(t)?t.split(`.`):t,i=0;for(;i{let{obj:r,k:i}=O(e,t,Object);if(r!==void 0||t.length===1){r[i]=n;return}let a=t[t.length-1],o=t.slice(0,t.length-1),s=O(e,o,Object);for(;s.obj===void 0&&o.length;)a=`${o[o.length-1]}.${a}`,o=o.slice(0,o.length-1),s=O(e,o,Object),s?.obj&&s.obj[`${s.k}.${a}`]!==void 0&&(s.obj=void 0);s.obj[`${s.k}.${a}`]=n},A=(e,t,n,r)=>{let{obj:i,k:a}=O(e,t,Object);i[a]=i[a]||[],i[a].push(n)},j=(e,t)=>{let{obj:n,k:r}=O(e,t);if(n&&Object.prototype.hasOwnProperty.call(n,r))return n[r]},M=(e,t,n)=>{let r=j(e,n);return r===void 0?j(t,n):r},N=(e,t,n)=>{for(let r in t)r!==`__proto__`&&r!==`constructor`&&(r in e?x(e[r])||e[r]instanceof String||x(t[r])||t[r]instanceof String?n&&(e[r]=t[r]):N(e[r],t[r],n):e[r]=t[r]);return e},P=e=>e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,`\\$&`),F={"&":`&`,"<":`<`,">":`>`,'"':`"`,"'":`'`,"/":`/`},I=e=>x(e)?e.replace(/[&<>"'\/]/g,e=>F[e]):e,L=class{constructor(e){this.capacity=e,this.regExpMap=new Map,this.regExpQueue=[]}getRegExp(e){let t=this.regExpMap.get(e);if(t!==void 0)return t;let n=new RegExp(e);return this.regExpQueue.length===this.capacity&&this.regExpMap.delete(this.regExpQueue.shift()),this.regExpMap.set(e,n),this.regExpQueue.push(e),n}},R=[` `,`,`,`?`,`!`,`;`],z=new L(20),B=(e,t,n)=>{t||=``,n||=``;let r=R.filter(e=>t.indexOf(e)<0&&n.indexOf(e)<0);if(r.length===0)return!0;let i=z.getRegExp(`(${r.map(e=>e===`?`?`\\?`:e).join(`|`)})`),a=!i.test(e);if(!a){let t=e.indexOf(n);t>0&&!i.test(e.substring(0,t))&&(a=!0)}return a},V=(e,t,n=`.`)=>{if(!e)return;if(e[t])return Object.prototype.hasOwnProperty.call(e,t)?e[t]:void 0;let r=t.split(n),i=e;for(let e=0;e-1&&oe?.replace(`_`,`-`),te={type:`logger`,log(e){this.output(`log`,e)},warn(e){this.output(`warn`,e)},error(e){this.output(`error`,e)},output(e,t){console?.[e]?.apply?.(console,t)}},ne=new class e{constructor(e,t={}){this.init(e,t)}init(e,t={}){this.prefix=t.prefix||`i18next:`,this.logger=e||te,this.options=t,this.debug=t.debug}log(...e){return this.forward(e,`log`,``,!0)}warn(...e){return this.forward(e,`warn`,``,!0)}error(...e){return this.forward(e,`error`,``)}deprecate(...e){return this.forward(e,`warn`,`WARNING DEPRECATED: `,!0)}forward(e,t,n,r){return r&&!this.debug?null:(x(e[0])&&(e[0]=`${n}${this.prefix} ${e[0]}`),this.logger[t](e))}create(t){return new e(this.logger,{prefix:`${this.prefix}:${t}:`,...this.options})}clone(t){return t||=this.options,t.prefix=t.prefix||this.prefix,new e(this.logger,t)}},re=class{constructor(){this.observers={}}on(e,t){return e.split(` `).forEach(e=>{this.observers[e]||(this.observers[e]=new Map);let n=this.observers[e].get(t)||0;this.observers[e].set(t,n+1)}),this}off(e,t){if(this.observers[e]){if(!t){delete this.observers[e];return}this.observers[e].delete(t)}}emit(e,...t){this.observers[e]&&Array.from(this.observers[e].entries()).forEach(([e,n])=>{for(let r=0;r{for(let i=0;i-1&&this.options.ns.splice(t,1)}getResource(e,t,n,r={}){let i=r.keySeparator===void 0?this.options.keySeparator:r.keySeparator,a=r.ignoreJSONStructure===void 0?this.options.ignoreJSONStructure:r.ignoreJSONStructure,o;e.indexOf(`.`)>-1?o=e.split(`.`):(o=[e,t],n&&(Array.isArray(n)?o.push(...n):x(n)&&i?o.push(...n.split(i)):o.push(n)));let s=j(this.data,o);return!s&&!t&&!n&&e.indexOf(`.`)>-1&&(e=o[0],t=o[1],n=o.slice(2).join(`.`)),s||!a||!x(n)?s:V(this.data?.[e]?.[t],n,i)}addResource(e,t,n,r,i={silent:!1}){let a=i.keySeparator===void 0?this.options.keySeparator:i.keySeparator,o=[e,t];n&&(o=o.concat(a?n.split(a):n)),e.indexOf(`.`)>-1&&(o=e.split(`.`),r=t,t=o[1]),this.addNamespaces(t),k(this.data,o,r),i.silent||this.emit(`added`,e,t,n,r)}addResources(e,t,n,r={silent:!1}){for(let r in n)(x(n[r])||Array.isArray(n[r]))&&this.addResource(e,t,r,n[r],{silent:!0});r.silent||this.emit(`added`,e,t,n)}addResourceBundle(e,t,n,r,i,a={silent:!1,skipCopy:!1}){let o=[e,t];e.indexOf(`.`)>-1&&(o=e.split(`.`),r=n,n=t,t=o[1]),this.addNamespaces(t);let s=j(this.data,o)||{};a.skipCopy||(n=JSON.parse(JSON.stringify(n))),r?N(s,n,i):s={...s,...n},k(this.data,o,s),a.silent||this.emit(`added`,e,t,n)}removeResourceBundle(e,t){this.hasResourceBundle(e,t)&&delete this.data[e][t],this.removeNamespaces(t),this.emit(`removed`,e,t)}hasResourceBundle(e,t){return this.getResource(e,t)!==void 0}getResourceBundle(e,t){return t||=this.options.defaultNS,this.getResource(e,t)}getDataByLanguage(e){return this.data[e]}hasLanguageSomeTranslations(e){let t=this.getDataByLanguage(e);return!!(t&&Object.keys(t)||[]).find(e=>t[e]&&Object.keys(t[e]).length>0)}toJSON(){return this.data}},H={processors:{},addPostProcessor(e){this.processors[e.name]=e},handle(e,t,n,r,i){return e.forEach(e=>{t=this.processors[e]?.process(t,n,r,i)??t}),t}},ae=Symbol(`i18next/PATH_KEY`);function oe(){let e=[],t=Object.create(null),n;return t.get=(r,i)=>(n?.revoke?.(),i===ae?e:(e.push(i),n=Proxy.revocable(r,t),n.proxy)),Proxy.revocable(Object.create(null),t).proxy}function U(e,t){let{[ae]:n}=e(oe());return n.join(t?.keySeparator??`.`)}var se={},ce=e=>!x(e)&&typeof e!=`boolean`&&typeof e!=`number`,le=class e extends re{constructor(e,t={}){super(),w([`resourceStore`,`languageUtils`,`pluralResolver`,`interpolator`,`backendConnector`,`i18nFormat`,`utils`],e,this),this.options=t,this.options.keySeparator===void 0&&(this.options.keySeparator=`.`),this.logger=ne.create(`translator`)}changeLanguage(e){e&&(this.language=e)}exists(e,t={interpolation:{}}){let n={...t};if(e==null)return!1;let r=this.resolve(e,n);if(r?.res===void 0)return!1;let i=ce(r.res);return!(n.returnObjects===!1&&i)}extractFromKey(e,t){let n=t.nsSeparator===void 0?this.options.nsSeparator:t.nsSeparator;n===void 0&&(n=`:`);let r=t.keySeparator===void 0?this.options.keySeparator:t.keySeparator,i=t.ns||this.options.defaultNS||[],a=n&&e.indexOf(n)>-1,o=!this.options.userDefinedKeySeparator&&!t.keySeparator&&!this.options.userDefinedNsSeparator&&!t.nsSeparator&&!B(e,n,r);if(a&&!o){let t=e.match(this.interpolator.nestingRegexp);if(t&&t.length>0)return{key:e,namespaces:x(i)?[i]:i};let a=e.split(n);(n!==r||n===r&&this.options.ns.indexOf(a[0])>-1)&&(i=a.shift()),e=a.join(r)}return{key:e,namespaces:x(i)?[i]:i}}translate(t,n,r){let i=typeof n==`object`?{...n}:n;if(typeof i!=`object`&&this.options.overloadTranslationOptionHandler&&(i=this.options.overloadTranslationOptionHandler(arguments)),typeof i==`object`&&(i={...i}),i||={},t==null)return``;typeof t==`function`&&(t=U(t,{...this.options,...i})),Array.isArray(t)||(t=[String(t)]);let a=i.returnDetails===void 0?this.options.returnDetails:i.returnDetails,o=i.keySeparator===void 0?this.options.keySeparator:i.keySeparator,{key:s,namespaces:c}=this.extractFromKey(t[t.length-1],i),l=c[c.length-1],u=i.nsSeparator===void 0?this.options.nsSeparator:i.nsSeparator;u===void 0&&(u=`:`);let d=i.lng||this.language,f=i.appendNamespaceToCIMode||this.options.appendNamespaceToCIMode;if(d?.toLowerCase()===`cimode`)return f?a?{res:`${l}${u}${s}`,usedKey:s,exactUsedKey:s,usedLng:d,usedNS:l,usedParams:this.getUsedParamsDetails(i)}:`${l}${u}${s}`:a?{res:s,usedKey:s,exactUsedKey:s,usedLng:d,usedNS:l,usedParams:this.getUsedParamsDetails(i)}:s;let p=this.resolve(t,i),m=p?.res,h=p?.usedKey||s,g=p?.exactUsedKey||s,_=[`[object Number]`,`[object Function]`,`[object RegExp]`],v=i.joinArrays===void 0?this.options.joinArrays:i.joinArrays,y=!this.i18nFormat||this.i18nFormat.handleAsObject,b=i.count!==void 0&&!x(i.count),S=e.hasDefaultValue(i),C=b?this.pluralResolver.getSuffix(d,i.count,i):``,w=i.ordinal&&b?this.pluralResolver.getSuffix(d,i.count,{ordinal:!1}):``,T=b&&!i.ordinal&&i.count===0,E=T&&i[`defaultValue${this.options.pluralSeparator}zero`]||i[`defaultValue${C}`]||i[`defaultValue${w}`]||i.defaultValue,D=m;y&&!m&&S&&(D=E);let O=ce(D),k=Object.prototype.toString.apply(D);if(y&&D&&O&&_.indexOf(k)<0&&!(x(v)&&Array.isArray(D))){if(!i.returnObjects&&!this.options.returnObjects){this.options.returnedObjectHandler||this.logger.warn(`accessing an object - but returnObjects options is not enabled!`);let e=this.options.returnedObjectHandler?this.options.returnedObjectHandler(h,D,{...i,ns:c}):`key '${s} (${this.language})' returned an object instead of string.`;return a?(p.res=e,p.usedParams=this.getUsedParamsDetails(i),p):e}if(o){let e=Array.isArray(D),t=e?[]:{},n=e?g:h;for(let e in D)if(Object.prototype.hasOwnProperty.call(D,e)){let r=`${n}${o}${e}`;S&&!m?t[e]=this.translate(r,{...i,defaultValue:ce(E)?E[e]:void 0,joinArrays:!1,ns:c}):t[e]=this.translate(r,{...i,joinArrays:!1,ns:c}),t[e]===r&&(t[e]=D[e])}m=t}}else if(y&&x(v)&&Array.isArray(m))m=m.join(v),m&&=this.extendTranslation(m,t,i,r);else{let e=!1,n=!1;!this.isValidLookup(m)&&S&&(e=!0,m=E),this.isValidLookup(m)||(n=!0,m=s);let a=(i.missingKeyNoValueFallbackToKey||this.options.missingKeyNoValueFallbackToKey)&&n?void 0:m,c=S&&E!==m&&this.options.updateMissing;if(n||e||c){if(this.logger.log(c?`updateKey`:`missingKey`,d,l,s,c?E:m),o){let e=this.resolve(s,{...i,keySeparator:!1});e&&e.res&&this.logger.warn(`Seems the loaded translations were in flat JSON format instead of nested. Either set keySeparator: false on init or make sure your translations are published in nested format.`)}let e=[],t=this.languageUtils.getFallbackCodes(this.options.fallbackLng,i.lng||this.language);if(this.options.saveMissingTo===`fallback`&&t&&t[0])for(let n=0;n{let r=S&&n!==m?n:a;this.options.missingKeyHandler?this.options.missingKeyHandler(e,l,t,r,c,i):this.backendConnector?.saveMissing&&this.backendConnector.saveMissing(e,l,t,r,c,i),this.emit(`missingKey`,e,l,t,m)};this.options.saveMissing&&(this.options.saveMissingPlurals&&b?e.forEach(e=>{let t=this.pluralResolver.getSuffixes(e,i);T&&i[`defaultValue${this.options.pluralSeparator}zero`]&&t.indexOf(`${this.options.pluralSeparator}zero`)<0&&t.push(`${this.options.pluralSeparator}zero`),t.forEach(t=>{n([e],s+t,i[`defaultValue${t}`]||E)})}):n(e,s,E))}m=this.extendTranslation(m,t,i,p,r),n&&m===s&&this.options.appendNamespaceToMissingKey&&(m=`${l}${u}${s}`),(n||e)&&this.options.parseMissingKeyHandler&&(m=this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey?`${l}${u}${s}`:s,e?m:void 0,i))}return a?(p.res=m,p.usedParams=this.getUsedParamsDetails(i),p):m}extendTranslation(e,t,n,r,i){if(this.i18nFormat?.parse)e=this.i18nFormat.parse(e,{...this.options.interpolation.defaultVariables,...n},n.lng||this.language||r.usedLng,r.usedNS,r.usedKey,{resolved:r});else if(!n.skipInterpolation){n.interpolation&&this.interpolator.init({...n,interpolation:{...this.options.interpolation,...n.interpolation}});let a=x(e)&&(n?.interpolation?.skipOnVariables===void 0?this.options.interpolation.skipOnVariables:n.interpolation.skipOnVariables),o;if(a){let t=e.match(this.interpolator.nestingRegexp);o=t&&t.length}let s=n.replace&&!x(n.replace)?n.replace:n;if(this.options.interpolation.defaultVariables&&(s={...this.options.interpolation.defaultVariables,...s}),e=this.interpolator.interpolate(e,s,n.lng||this.language||r.usedLng,n),a){let t=e.match(this.interpolator.nestingRegexp),r=t&&t.length;oi?.[0]===e[0]&&!n.context?(this.logger.warn(`It seems you are nesting recursively key: ${e[0]} in key: ${t[0]}`),null):this.translate(...e,t),n)),n.interpolation&&this.interpolator.reset()}let a=n.postProcess||this.options.postProcess,o=x(a)?[a]:a;return e!=null&&o?.length&&n.applyPostProcessor!==!1&&(e=H.handle(o,e,t,this.options&&this.options.postProcessPassResolved?{i18nResolved:{...r,usedParams:this.getUsedParamsDetails(n)},...n}:n,this)),e}resolve(e,t={}){let n,r,i,a,o;return x(e)&&(e=[e]),e.forEach(e=>{if(this.isValidLookup(n))return;let s=this.extractFromKey(e,t),c=s.key;r=c;let l=s.namespaces;this.options.fallbackNS&&(l=l.concat(this.options.fallbackNS));let u=t.count!==void 0&&!x(t.count),d=u&&!t.ordinal&&t.count===0,f=t.context!==void 0&&(x(t.context)||typeof t.context==`number`)&&t.context!==``,p=t.lngs?t.lngs:this.languageUtils.toResolveHierarchy(t.lng||this.language,t.fallbackLng);l.forEach(e=>{this.isValidLookup(n)||(o=e,!se[`${p[0]}-${e}`]&&this.utils?.hasLoadedNamespace&&!this.utils?.hasLoadedNamespace(o)&&(se[`${p[0]}-${e}`]=!0,this.logger.warn(`key "${r}" for languages "${p.join(`, `)}" won't get resolved as namespace "${o}" was not yet loaded`,`This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!`)),p.forEach(r=>{if(this.isValidLookup(n))return;a=r;let o=[c];if(this.i18nFormat?.addLookupKeys)this.i18nFormat.addLookupKeys(o,c,r,e,t);else{let e;u&&(e=this.pluralResolver.getSuffix(r,t.count,t));let n=`${this.options.pluralSeparator}zero`,i=`${this.options.pluralSeparator}ordinal${this.options.pluralSeparator}`;if(u&&(t.ordinal&&e.indexOf(i)===0&&o.push(c+e.replace(i,this.options.pluralSeparator)),o.push(c+e),d&&o.push(c+n)),f){let r=`${c}${this.options.contextSeparator||`_`}${t.context}`;o.push(r),u&&(t.ordinal&&e.indexOf(i)===0&&o.push(r+e.replace(i,this.options.pluralSeparator)),o.push(r+e),d&&o.push(r+n))}}let s;for(;s=o.pop();)this.isValidLookup(n)||(i=s,n=this.getResource(r,e,s,t))}))})}),{res:n,usedKey:r,exactUsedKey:i,usedLng:a,usedNS:o}}isValidLookup(e){return e!==void 0&&!(!this.options.returnNull&&e===null)&&!(!this.options.returnEmptyString&&e===``)}getResource(e,t,n,r={}){return this.i18nFormat?.getResource?this.i18nFormat.getResource(e,t,n,r):this.resourceStore.getResource(e,t,n,r)}getUsedParamsDetails(e={}){let t=[`defaultValue`,`ordinal`,`context`,`replace`,`lng`,`lngs`,`fallbackLng`,`ns`,`keySeparator`,`nsSeparator`,`returnObjects`,`returnDetails`,`joinArrays`,`postProcess`,`interpolation`],n=e.replace&&!x(e.replace),r=n?e.replace:e;if(n&&e.count!==void 0&&(r.count=e.count),this.options.interpolation.defaultVariables&&(r={...this.options.interpolation.defaultVariables,...r}),!n){r={...r};for(let e of t)delete r[e]}return r}static hasDefaultValue(e){for(let t in e)if(Object.prototype.hasOwnProperty.call(e,t)&&t.substring(0,12)===`defaultValue`&&e[t]!==void 0)return!0;return!1}},W=class{constructor(e){this.options=e,this.supportedLngs=this.options.supportedLngs||!1,this.logger=ne.create(`languageUtils`)}getScriptPartFromCode(e){if(e=ee(e),!e||e.indexOf(`-`)<0)return null;let t=e.split(`-`);return t.length===2||(t.pop(),t[t.length-1].toLowerCase()===`x`)?null:this.formatLanguageCode(t.join(`-`))}getLanguagePartFromCode(e){if(e=ee(e),!e||e.indexOf(`-`)<0)return e;let t=e.split(`-`);return this.formatLanguageCode(t[0])}formatLanguageCode(e){if(x(e)&&e.indexOf(`-`)>-1){let t;try{t=Intl.getCanonicalLocales(e)[0]}catch{}return t&&this.options.lowerCaseLng&&(t=t.toLowerCase()),t||(this.options.lowerCaseLng?e.toLowerCase():e)}return this.options.cleanCode||this.options.lowerCaseLng?e.toLowerCase():e}isSupportedCode(e){return(this.options.load===`languageOnly`||this.options.nonExplicitSupportedLngs)&&(e=this.getLanguagePartFromCode(e)),!this.supportedLngs||!this.supportedLngs.length||this.supportedLngs.indexOf(e)>-1}getBestMatchFromCodes(e){if(!e)return null;let t;return e.forEach(e=>{if(t)return;let n=this.formatLanguageCode(e);(!this.options.supportedLngs||this.isSupportedCode(n))&&(t=n)}),!t&&this.options.supportedLngs&&e.forEach(e=>{if(t)return;let n=this.getScriptPartFromCode(e);if(this.isSupportedCode(n))return t=n;let r=this.getLanguagePartFromCode(e);if(this.isSupportedCode(r))return t=r;t=this.options.supportedLngs.find(e=>{if(e===r||!(e.indexOf(`-`)<0&&r.indexOf(`-`)<0)&&(e.indexOf(`-`)>0&&r.indexOf(`-`)<0&&e.substring(0,e.indexOf(`-`))===r||e.indexOf(r)===0&&r.length>1))return e})}),t||=this.getFallbackCodes(this.options.fallbackLng)[0],t}getFallbackCodes(e,t){if(!e)return[];if(typeof e==`function`&&(e=e(t)),x(e)&&(e=[e]),Array.isArray(e))return e;if(!t)return e.default||[];let n=e[t];return n||=e[this.getScriptPartFromCode(t)],n||=e[this.formatLanguageCode(t)],n||=e[this.getLanguagePartFromCode(t)],n||=e.default,n||[]}toResolveHierarchy(e,t){let n=this.getFallbackCodes((t===!1?[]:t)||this.options.fallbackLng||[],e),r=[],i=e=>{e&&(this.isSupportedCode(e)?r.push(e):this.logger.warn(`rejecting language code not found in supportedLngs: ${e}`))};return x(e)&&(e.indexOf(`-`)>-1||e.indexOf(`_`)>-1)?(this.options.load!==`languageOnly`&&i(this.formatLanguageCode(e)),this.options.load!==`languageOnly`&&this.options.load!==`currentOnly`&&i(this.getScriptPartFromCode(e)),this.options.load!==`currentOnly`&&i(this.getLanguagePartFromCode(e))):x(e)&&i(this.formatLanguageCode(e)),n.forEach(e=>{r.indexOf(e)<0&&i(this.formatLanguageCode(e))}),r}},ue={zero:0,one:1,two:2,few:3,many:4,other:5},de={select:e=>e===1?`one`:`other`,resolvedOptions:()=>({pluralCategories:[`one`,`other`]})},fe=class{constructor(e,t={}){this.languageUtils=e,this.options=t,this.logger=ne.create(`pluralResolver`),this.pluralRulesCache={}}addRule(e,t){this.rules[e]=t}clearCache(){this.pluralRulesCache={}}getRule(e,t={}){let n=ee(e===`dev`?`en`:e),r=t.ordinal?`ordinal`:`cardinal`,i=JSON.stringify({cleanedCode:n,type:r});if(i in this.pluralRulesCache)return this.pluralRulesCache[i];let a;try{a=new Intl.PluralRules(n,{type:r})}catch{if(!Intl)return this.logger.error(`No Intl support, please use an Intl polyfill!`),de;if(!e.match(/-|_/))return de;let n=this.languageUtils.getLanguagePartFromCode(e);a=this.getRule(n,t)}return this.pluralRulesCache[i]=a,a}needsPlural(e,t={}){let n=this.getRule(e,t);return n||=this.getRule(`dev`,t),n?.resolvedOptions().pluralCategories.length>1}getPluralFormsOfKey(e,t,n={}){return this.getSuffixes(e,n).map(e=>`${t}${e}`)}getSuffixes(e,t={}){let n=this.getRule(e,t);return n||=this.getRule(`dev`,t),n?n.resolvedOptions().pluralCategories.sort((e,t)=>ue[e]-ue[t]).map(e=>`${this.options.prepend}${t.ordinal?`ordinal${this.options.prepend}`:``}${e}`):[]}getSuffix(e,t,n={}){let r=this.getRule(e,n);return r?`${this.options.prepend}${n.ordinal?`ordinal${this.options.prepend}`:``}${r.select(t)}`:(this.logger.warn(`no plural rule found for: ${e}`),this.getSuffix(`dev`,t,n))}},pe=(e,t,n,r=`.`,i=!0)=>{let a=M(e,t,n);return!a&&i&&x(n)&&(a=V(e,n,r),a===void 0&&(a=V(t,n,r))),a},me=e=>e.replace(/\$/g,`$$$$`),he=class{constructor(e={}){this.logger=ne.create(`interpolator`),this.options=e,this.format=e?.interpolation?.format||(e=>e),this.init(e)}init(e={}){e.interpolation||={escapeValue:!0};let{escape:t,escapeValue:n,useRawValueToEscape:r,prefix:i,prefixEscaped:a,suffix:o,suffixEscaped:s,formatSeparator:c,unescapeSuffix:l,unescapePrefix:u,nestingPrefix:d,nestingPrefixEscaped:f,nestingSuffix:p,nestingSuffixEscaped:m,nestingOptionsSeparator:h,maxReplaces:g,alwaysFormat:_}=e.interpolation;this.escape=t===void 0?I:t,this.escapeValue=n===void 0?!0:n,this.useRawValueToEscape=r===void 0?!1:r,this.prefix=i?P(i):a||`{{`,this.suffix=o?P(o):s||`}}`,this.formatSeparator=c||`,`,this.unescapePrefix=l?``:u||`-`,this.unescapeSuffix=this.unescapePrefix?``:l||``,this.nestingPrefix=d?P(d):f||P(`$t(`),this.nestingSuffix=p?P(p):m||P(`)`),this.nestingOptionsSeparator=h||`,`,this.maxReplaces=g||1e3,this.alwaysFormat=_===void 0?!1:_,this.resetRegExp()}reset(){this.options&&this.init(this.options)}resetRegExp(){let e=(e,t)=>e?.source===t?(e.lastIndex=0,e):new RegExp(t,`g`);this.regexp=e(this.regexp,`${this.prefix}(.+?)${this.suffix}`),this.regexpUnescape=e(this.regexpUnescape,`${this.prefix}${this.unescapePrefix}(.+?)${this.unescapeSuffix}${this.suffix}`),this.nestingRegexp=e(this.nestingRegexp,`${this.nestingPrefix}((?:[^()"']+|"[^"]*"|'[^']*'|\\((?:[^()]|"[^"]*"|'[^']*')*\\))*?)${this.nestingSuffix}`)}interpolate(e,t,n,r){let i,a,o,s=this.options&&this.options.interpolation&&this.options.interpolation.defaultVariables||{},c=e=>{if(e.indexOf(this.formatSeparator)<0){let i=pe(t,s,e,this.options.keySeparator,this.options.ignoreJSONStructure);return this.alwaysFormat?this.format(i,void 0,n,{...r,...t,interpolationkey:e}):i}let i=e.split(this.formatSeparator),a=i.shift().trim(),o=i.join(this.formatSeparator).trim();return this.format(pe(t,s,a,this.options.keySeparator,this.options.ignoreJSONStructure),o,n,{...r,...t,interpolationkey:a})};this.resetRegExp();let l=r?.missingInterpolationHandler||this.options.missingInterpolationHandler,u=r?.interpolation?.skipOnVariables===void 0?this.options.interpolation.skipOnVariables:r.interpolation.skipOnVariables;return[{regex:this.regexpUnescape,safeValue:e=>me(e)},{regex:this.regexp,safeValue:e=>this.escapeValue?me(this.escape(e)):me(e)}].forEach(t=>{for(o=0;i=t.regex.exec(e);){let n=i[1].trim();if(a=c(n),a===void 0)if(typeof l==`function`){let t=l(e,i,r);a=x(t)?t:``}else if(r&&Object.prototype.hasOwnProperty.call(r,n))a=``;else if(u){a=i[0];continue}else this.logger.warn(`missed to pass in variable ${n} for interpolating ${e}`),a=``;else !x(a)&&!this.useRawValueToEscape&&(a=C(a));let s=t.safeValue(a);if(e=e.replace(i[0],s),u?(t.regex.lastIndex+=a.length,t.regex.lastIndex-=i[0].length):t.regex.lastIndex=0,o++,o>=this.maxReplaces)break}}),e}nest(e,t,n={}){let r,i,a,o=(e,t)=>{let n=this.nestingOptionsSeparator;if(e.indexOf(n)<0)return e;let r=e.split(RegExp(`${n}[ ]*{`)),i=`{${r[1]}`;e=r[0],i=this.interpolate(i,a);let o=i.match(/'/g),s=i.match(/"/g);((o?.length??0)%2==0&&!s||s.length%2!=0)&&(i=i.replace(/'/g,`"`));try{a=JSON.parse(i),t&&(a={...t,...a})}catch(t){return this.logger.warn(`failed parsing options string in nesting for key ${e}`,t),`${e}${n}${i}`}return a.defaultValue&&a.defaultValue.indexOf(this.prefix)>-1&&delete a.defaultValue,e};for(;r=this.nestingRegexp.exec(e);){let s=[];a={...n},a=a.replace&&!x(a.replace)?a.replace:a,a.applyPostProcessor=!1,delete a.defaultValue;let c=/{.*}/.test(r[1])?r[1].lastIndexOf(`}`)+1:r[1].indexOf(this.formatSeparator);if(c!==-1&&(s=r[1].slice(c).split(this.formatSeparator).map(e=>e.trim()).filter(Boolean),r[1]=r[1].slice(0,c)),i=t(o.call(this,r[1].trim(),a),a),i&&r[0]===e&&!x(i))return i;x(i)||(i=C(i)),i||=(this.logger.warn(`missed to resolve ${r[1]} for nesting ${e}`),``),s.length&&(i=s.reduce((e,t)=>this.format(e,t,n.lng,{...n,interpolationkey:r[1].trim()}),i.trim())),e=e.replace(r[0],i),this.regexp.lastIndex=0}return e}},ge=e=>{let t=e.toLowerCase().trim(),n={};if(e.indexOf(`(`)>-1){let r=e.split(`(`);t=r[0].toLowerCase().trim();let i=r[1].substring(0,r[1].length-1);t===`currency`&&i.indexOf(`:`)<0?n.currency||=i.trim():t===`relativetime`&&i.indexOf(`:`)<0?n.range||=i.trim():i.split(`;`).forEach(e=>{if(e){let[t,...r]=e.split(`:`),i=r.join(`:`).trim().replace(/^'+|'+$/g,``),a=t.trim();n[a]||(n[a]=i),i===`false`&&(n[a]=!1),i===`true`&&(n[a]=!0),isNaN(i)||(n[a]=parseInt(i,10))}})}return{formatName:t,formatOptions:n}},_e=e=>{let t={};return(n,r,i)=>{let a=i;i&&i.interpolationkey&&i.formatParams&&i.formatParams[i.interpolationkey]&&i[i.interpolationkey]&&(a={...a,[i.interpolationkey]:void 0});let o=r+JSON.stringify(a),s=t[o];return s||(s=e(ee(r),i),t[o]=s),s(n)}},ve=e=>(t,n,r)=>e(ee(n),r)(t),ye=class{constructor(e={}){this.logger=ne.create(`formatter`),this.options=e,this.init(e)}init(e,t={interpolation:{}}){this.formatSeparator=t.interpolation.formatSeparator||`,`;let n=t.cacheInBuiltFormats?_e:ve;this.formats={number:n((e,t)=>{let n=new Intl.NumberFormat(e,{...t});return e=>n.format(e)}),currency:n((e,t)=>{let n=new Intl.NumberFormat(e,{...t,style:`currency`});return e=>n.format(e)}),datetime:n((e,t)=>{let n=new Intl.DateTimeFormat(e,{...t});return e=>n.format(e)}),relativetime:n((e,t)=>{let n=new Intl.RelativeTimeFormat(e,{...t});return e=>n.format(e,t.range||`day`)}),list:n((e,t)=>{let n=new Intl.ListFormat(e,{...t});return e=>n.format(e)})}}add(e,t){this.formats[e.toLowerCase().trim()]=t}addCached(e,t){this.formats[e.toLowerCase().trim()]=_e(t)}format(e,t,n,r={}){let i=t.split(this.formatSeparator);if(i.length>1&&i[0].indexOf(`(`)>1&&i[0].indexOf(`)`)<0&&i.find(e=>e.indexOf(`)`)>-1)){let e=i.findIndex(e=>e.indexOf(`)`)>-1);i[0]=[i[0],...i.splice(1,e)].join(this.formatSeparator)}return i.reduce((e,t)=>{let{formatName:i,formatOptions:a}=ge(t);if(this.formats[i]){let t=e;try{let o=r?.formatParams?.[r.interpolationkey]||{},s=o.locale||o.lng||r.locale||r.lng||n;t=this.formats[i](e,s,{...a,...r,...o})}catch(e){this.logger.warn(e)}return t}else this.logger.warn(`there was no format function for ${i}`);return e},e)}},be=(e,t)=>{e.pending[t]!==void 0&&(delete e.pending[t],e.pendingCount--)},xe=class extends re{constructor(e,t,n,r={}){super(),this.backend=e,this.store=t,this.services=n,this.languageUtils=n.languageUtils,this.options=r,this.logger=ne.create(`backendConnector`),this.waitingReads=[],this.maxParallelReads=r.maxParallelReads||10,this.readingCalls=0,this.maxRetries=r.maxRetries>=0?r.maxRetries:5,this.retryTimeout=r.retryTimeout>=1?r.retryTimeout:350,this.state={},this.queue=[],this.backend?.init?.(n,r.backend,r)}queueLoad(e,t,n,r){let i={},a={},o={},s={};return e.forEach(e=>{let r=!0;t.forEach(t=>{let o=`${e}|${t}`;!n.reload&&this.store.hasResourceBundle(e,t)?this.state[o]=2:this.state[o]<0||(this.state[o]===1?a[o]===void 0&&(a[o]=!0):(this.state[o]=1,r=!1,a[o]===void 0&&(a[o]=!0),i[o]===void 0&&(i[o]=!0),s[t]===void 0&&(s[t]=!0)))}),r||(o[e]=!0)}),(Object.keys(i).length||Object.keys(a).length)&&this.queue.push({pending:a,pendingCount:Object.keys(a).length,loaded:{},errors:[],callback:r}),{toLoad:Object.keys(i),pending:Object.keys(a),toLoadLanguages:Object.keys(o),toLoadNamespaces:Object.keys(s)}}loaded(e,t,n){let r=e.split(`|`),i=r[0],a=r[1];t&&this.emit(`failedLoading`,i,a,t),!t&&n&&this.store.addResourceBundle(i,a,n,void 0,void 0,{skipCopy:!0}),this.state[e]=t?-1:2,t&&n&&(this.state[e]=0);let o={};this.queue.forEach(n=>{A(n.loaded,[i],a),be(n,e),t&&n.errors.push(t),n.pendingCount===0&&!n.done&&(Object.keys(n.loaded).forEach(e=>{o[e]||(o[e]={});let t=n.loaded[e];t.length&&t.forEach(t=>{o[e][t]===void 0&&(o[e][t]=!0)})}),n.done=!0,n.errors.length?n.callback(n.errors):n.callback())}),this.emit(`loaded`,o),this.queue=this.queue.filter(e=>!e.done)}read(e,t,n,r=0,i=this.retryTimeout,a){if(!e.length)return a(null,{});if(this.readingCalls>=this.maxParallelReads){this.waitingReads.push({lng:e,ns:t,fcName:n,tried:r,wait:i,callback:a});return}this.readingCalls++;let o=(o,s)=>{if(this.readingCalls--,this.waitingReads.length>0){let e=this.waitingReads.shift();this.read(e.lng,e.ns,e.fcName,e.tried,e.wait,e.callback)}if(o&&s&&r{this.read.call(this,e,t,n,r+1,i*2,a)},i);return}a(o,s)},s=this.backend[n].bind(this.backend);if(s.length===2){try{let n=s(e,t);n&&typeof n.then==`function`?n.then(e=>o(null,e)).catch(o):o(null,n)}catch(e){o(e)}return}return s(e,t,o)}prepareLoading(e,t,n={},r){if(!this.backend)return this.logger.warn(`No backend was added via i18next.use. Will not load resources.`),r&&r();x(e)&&(e=this.languageUtils.toResolveHierarchy(e)),x(t)&&(t=[t]);let i=this.queueLoad(e,t,n,r);if(!i.toLoad.length)return i.pending.length||r(),null;i.toLoad.forEach(e=>{this.loadOne(e)})}load(e,t,n){this.prepareLoading(e,t,{},n)}reload(e,t,n){this.prepareLoading(e,t,{reload:!0},n)}loadOne(e,t=``){let n=e.split(`|`),r=n[0],i=n[1];this.read(r,i,`read`,void 0,void 0,(n,a)=>{n&&this.logger.warn(`${t}loading namespace ${i} for language ${r} failed`,n),!n&&a&&this.logger.log(`${t}loaded namespace ${i} for language ${r}`,a),this.loaded(e,n,a)})}saveMissing(e,t,n,r,i,a={},o=()=>{}){if(this.services?.utils?.hasLoadedNamespace&&!this.services?.utils?.hasLoadedNamespace(t)){this.logger.warn(`did not save key "${n}" as the namespace "${t}" was not yet loaded`,`This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!`);return}if(!(n==null||n===``)){if(this.backend?.create){let s={...a,isUpdate:i},c=this.backend.create.bind(this.backend);if(c.length<6)try{let i;i=c.length===5?c(e,t,n,r,s):c(e,t,n,r),i&&typeof i.then==`function`?i.then(e=>o(null,e)).catch(o):o(null,i)}catch(e){o(e)}else c(e,t,n,r,o,s)}!e||!e[0]||this.store.addResource(e[0],t,n,r)}}},Se=()=>({debug:!1,initAsync:!0,ns:[`translation`],defaultNS:[`translation`],fallbackLng:[`dev`],fallbackNS:!1,supportedLngs:!1,nonExplicitSupportedLngs:!1,load:`all`,preload:!1,simplifyPluralSuffix:!0,keySeparator:`.`,nsSeparator:`:`,pluralSeparator:`_`,contextSeparator:`_`,partialBundledLanguages:!1,saveMissing:!1,updateMissing:!1,saveMissingTo:`fallback`,saveMissingPlurals:!0,missingKeyHandler:!1,missingInterpolationHandler:!1,postProcess:!1,postProcessPassResolved:!1,returnNull:!1,returnEmptyString:!0,returnObjects:!1,joinArrays:!1,returnedObjectHandler:!1,parseMissingKeyHandler:!1,appendNamespaceToMissingKey:!1,appendNamespaceToCIMode:!1,overloadTranslationOptionHandler:e=>{let t={};if(typeof e[1]==`object`&&(t=e[1]),x(e[1])&&(t.defaultValue=e[1]),x(e[2])&&(t.tDescription=e[2]),typeof e[2]==`object`||typeof e[3]==`object`){let n=e[3]||e[2];Object.keys(n).forEach(e=>{t[e]=n[e]})}return t},interpolation:{escapeValue:!0,format:e=>e,prefix:`{{`,suffix:`}}`,formatSeparator:`,`,unescapePrefix:`-`,nestingPrefix:`$t(`,nestingSuffix:`)`,nestingOptionsSeparator:`,`,maxReplaces:1e3,skipOnVariables:!0},cacheInBuiltFormats:!0}),Ce=e=>(x(e.ns)&&(e.ns=[e.ns]),x(e.fallbackLng)&&(e.fallbackLng=[e.fallbackLng]),x(e.fallbackNS)&&(e.fallbackNS=[e.fallbackNS]),e.supportedLngs?.indexOf?.(`cimode`)<0&&(e.supportedLngs=e.supportedLngs.concat([`cimode`])),typeof e.initImmediate==`boolean`&&(e.initAsync=e.initImmediate),e),we=()=>{},Te=e=>{Object.getOwnPropertyNames(Object.getPrototypeOf(e)).forEach(t=>{typeof e[t]==`function`&&(e[t]=e[t].bind(e))})},Ee=class e extends re{constructor(e={},t){if(super(),this.options=Ce(e),this.services={},this.logger=ne,this.modules={external:[]},Te(this),t&&!this.isInitialized&&!e.isClone){if(!this.options.initAsync)return this.init(e,t),this;setTimeout(()=>{this.init(e,t)},0)}}init(e={},t){this.isInitializing=!0,typeof e==`function`&&(t=e,e={}),e.defaultNS==null&&e.ns&&(x(e.ns)?e.defaultNS=e.ns:e.ns.indexOf(`translation`)<0&&(e.defaultNS=e.ns[0]));let n=Se();this.options={...n,...this.options,...Ce(e)},this.options.interpolation={...n.interpolation,...this.options.interpolation},e.keySeparator!==void 0&&(this.options.userDefinedKeySeparator=e.keySeparator),e.nsSeparator!==void 0&&(this.options.userDefinedNsSeparator=e.nsSeparator);let r=e=>e?typeof e==`function`?new e:e:null;if(!this.options.isClone){this.modules.logger?ne.init(r(this.modules.logger),this.options):ne.init(null,this.options);let e;e=this.modules.formatter?this.modules.formatter:ye;let t=new W(this.options);this.store=new ie(this.options.resources,this.options);let i=this.services;i.logger=ne,i.resourceStore=this.store,i.languageUtils=t,i.pluralResolver=new fe(t,{prepend:this.options.pluralSeparator,simplifyPluralSuffix:this.options.simplifyPluralSuffix}),this.options.interpolation.format&&this.options.interpolation.format!==n.interpolation.format&&this.logger.deprecate(`init: you are still using the legacy format function, please use the new approach: https://www.i18next.com/translation-function/formatting`),e&&(!this.options.interpolation.format||this.options.interpolation.format===n.interpolation.format)&&(i.formatter=r(e),i.formatter.init&&i.formatter.init(i,this.options),this.options.interpolation.format=i.formatter.format.bind(i.formatter)),i.interpolator=new he(this.options),i.utils={hasLoadedNamespace:this.hasLoadedNamespace.bind(this)},i.backendConnector=new xe(r(this.modules.backend),i.resourceStore,i,this.options),i.backendConnector.on(`*`,(e,...t)=>{this.emit(e,...t)}),this.modules.languageDetector&&(i.languageDetector=r(this.modules.languageDetector),i.languageDetector.init&&i.languageDetector.init(i,this.options.detection,this.options)),this.modules.i18nFormat&&(i.i18nFormat=r(this.modules.i18nFormat),i.i18nFormat.init&&i.i18nFormat.init(this)),this.translator=new le(this.services,this.options),this.translator.on(`*`,(e,...t)=>{this.emit(e,...t)}),this.modules.external.forEach(e=>{e.init&&e.init(this)})}if(this.format=this.options.interpolation.format,t||=we,this.options.fallbackLng&&!this.services.languageDetector&&!this.options.lng){let e=this.services.languageUtils.getFallbackCodes(this.options.fallbackLng);e.length>0&&e[0]!==`dev`&&(this.options.lng=e[0])}!this.services.languageDetector&&!this.options.lng&&this.logger.warn(`init: no languageDetector is used and no lng is defined`),[`getResource`,`hasResourceBundle`,`getResourceBundle`,`getDataByLanguage`].forEach(e=>{this[e]=(...t)=>this.store[e](...t)}),[`addResource`,`addResources`,`addResourceBundle`,`removeResourceBundle`].forEach(e=>{this[e]=(...t)=>(this.store[e](...t),this)});let i=S(),a=()=>{let e=(e,n)=>{this.isInitializing=!1,this.isInitialized&&!this.initializedStoreOnce&&this.logger.warn(`init: i18next is already initialized. You should call init just once!`),this.isInitialized=!0,this.options.isClone||this.logger.log(`initialized`,this.options),this.emit(`initialized`,this.options),i.resolve(n),t(e,n)};if(this.languages&&!this.isInitialized)return e(null,this.t.bind(this));this.changeLanguage(this.options.lng,e)};return this.options.resources||!this.options.initAsync?a():setTimeout(a,0),i}loadResources(e,t=we){let n=t,r=x(e)?e:this.language;if(typeof e==`function`&&(n=e),!this.options.resources||this.options.partialBundledLanguages){if(r?.toLowerCase()===`cimode`&&(!this.options.preload||this.options.preload.length===0))return n();let e=[],t=t=>{t&&t!==`cimode`&&this.services.languageUtils.toResolveHierarchy(t).forEach(t=>{t!==`cimode`&&e.indexOf(t)<0&&e.push(t)})};r?t(r):this.services.languageUtils.getFallbackCodes(this.options.fallbackLng).forEach(e=>t(e)),this.options.preload?.forEach?.(e=>t(e)),this.services.backendConnector.load(e,this.options.ns,e=>{!e&&!this.resolvedLanguage&&this.language&&this.setResolvedLanguage(this.language),n(e)})}else n(null)}reloadResources(e,t,n){let r=S();return typeof e==`function`&&(n=e,e=void 0),typeof t==`function`&&(n=t,t=void 0),e||=this.languages,t||=this.options.ns,n||=we,this.services.backendConnector.reload(e,t,e=>{r.resolve(),n(e)}),r}use(e){if(!e)throw Error(`You are passing an undefined module! Please check the object you are passing to i18next.use()`);if(!e.type)throw Error(`You are passing a wrong module! Please check the object you are passing to i18next.use()`);return e.type===`backend`&&(this.modules.backend=e),(e.type===`logger`||e.log&&e.warn&&e.error)&&(this.modules.logger=e),e.type===`languageDetector`&&(this.modules.languageDetector=e),e.type===`i18nFormat`&&(this.modules.i18nFormat=e),e.type===`postProcessor`&&H.addPostProcessor(e),e.type===`formatter`&&(this.modules.formatter=e),e.type===`3rdParty`&&this.modules.external.push(e),this}setResolvedLanguage(e){if(!(!e||!this.languages)&&!([`cimode`,`dev`].indexOf(e)>-1)){for(let e=0;e-1)&&this.store.hasLanguageSomeTranslations(t)){this.resolvedLanguage=t;break}}!this.resolvedLanguage&&this.languages.indexOf(e)<0&&this.store.hasLanguageSomeTranslations(e)&&(this.resolvedLanguage=e,this.languages.unshift(e))}}changeLanguage(e,t){this.isLanguageChangingTo=e;let n=S();this.emit(`languageChanging`,e);let r=e=>{this.language=e,this.languages=this.services.languageUtils.toResolveHierarchy(e),this.resolvedLanguage=void 0,this.setResolvedLanguage(e)},i=(i,a)=>{a?this.isLanguageChangingTo===e&&(r(a),this.translator.changeLanguage(a),this.isLanguageChangingTo=void 0,this.emit(`languageChanged`,a),this.logger.log(`languageChanged`,a)):this.isLanguageChangingTo=void 0,n.resolve((...e)=>this.t(...e)),t&&t(i,(...e)=>this.t(...e))},a=t=>{!e&&!t&&this.services.languageDetector&&(t=[]);let n=x(t)?t:t&&t[0],a=this.store.hasLanguageSomeTranslations(n)?n:this.services.languageUtils.getBestMatchFromCodes(x(t)?[t]:t);a&&(this.language||r(a),this.translator.language||this.translator.changeLanguage(a),this.services.languageDetector?.cacheUserLanguage?.(a)),this.loadResources(a,e=>{i(e,a)})};return!e&&this.services.languageDetector&&!this.services.languageDetector.async?a(this.services.languageDetector.detect()):!e&&this.services.languageDetector&&this.services.languageDetector.async?this.services.languageDetector.detect.length===0?this.services.languageDetector.detect().then(a):this.services.languageDetector.detect(a):a(e),n}getFixedT(e,t,n){let r=(e,t,...i)=>{let a;a=typeof t==`object`?{...t}:this.options.overloadTranslationOptionHandler([e,t].concat(i)),a.lng=a.lng||r.lng,a.lngs=a.lngs||r.lngs,a.ns=a.ns||r.ns,a.keyPrefix!==``&&(a.keyPrefix=a.keyPrefix||n||r.keyPrefix);let o=this.options.keySeparator||`.`,s;return a.keyPrefix&&Array.isArray(e)?s=e.map(e=>(typeof e==`function`&&(e=U(e,{...this.options,...t})),`${a.keyPrefix}${o}${e}`)):(typeof e==`function`&&(e=U(e,{...this.options,...t})),s=a.keyPrefix?`${a.keyPrefix}${o}${e}`:e),this.t(s,a)};return x(e)?r.lng=e:r.lngs=e,r.ns=t,r.keyPrefix=n,r}t(...e){return this.translator?.translate(...e)}exists(...e){return this.translator?.exists(...e)}setDefaultNamespace(e){this.options.defaultNS=e}hasLoadedNamespace(e,t={}){if(!this.isInitialized)return this.logger.warn(`hasLoadedNamespace: i18next was not initialized`,this.languages),!1;if(!this.languages||!this.languages.length)return this.logger.warn(`hasLoadedNamespace: i18n.languages were undefined or empty`,this.languages),!1;let n=t.lng||this.resolvedLanguage||this.languages[0],r=this.options?this.options.fallbackLng:!1,i=this.languages[this.languages.length-1];if(n.toLowerCase()===`cimode`)return!0;let a=(e,t)=>{let n=this.services.backendConnector.state[`${e}|${t}`];return n===-1||n===0||n===2};if(t.precheck){let e=t.precheck(this,a);if(e!==void 0)return e}return!!(this.hasResourceBundle(n,e)||!this.services.backendConnector.backend||this.options.resources&&!this.options.partialBundledLanguages||a(n,e)&&(!r||a(i,e)))}loadNamespaces(e,t){let n=S();return this.options.ns?(x(e)&&(e=[e]),e.forEach(e=>{this.options.ns.indexOf(e)<0&&this.options.ns.push(e)}),this.loadResources(e=>{n.resolve(),t&&t(e)}),n):(t&&t(),Promise.resolve())}loadLanguages(e,t){let n=S();x(e)&&(e=[e]);let r=this.options.preload||[],i=e.filter(e=>r.indexOf(e)<0&&this.services.languageUtils.isSupportedCode(e));return i.length?(this.options.preload=r.concat(i),this.loadResources(e=>{n.resolve(),t&&t(e)}),n):(t&&t(),Promise.resolve())}dir(e){if(e||=this.resolvedLanguage||(this.languages?.length>0?this.languages[0]:this.language),!e)return`rtl`;try{let t=new Intl.Locale(e);if(t&&t.getTextInfo){let e=t.getTextInfo();if(e&&e.direction)return e.direction}}catch{}let t=`ar.shu.sqr.ssh.xaa.yhd.yud.aao.abh.abv.acm.acq.acw.acx.acy.adf.ads.aeb.aec.afb.ajp.apc.apd.arb.arq.ars.ary.arz.auz.avl.ayh.ayl.ayn.ayp.bbz.pga.he.iw.ps.pbt.pbu.pst.prp.prd.ug.ur.ydd.yds.yih.ji.yi.hbo.men.xmn.fa.jpr.peo.pes.prs.dv.sam.ckb`.split(`.`),n=this.services?.languageUtils||new W(Se());return e.toLowerCase().indexOf(`-latn`)>1?`ltr`:t.indexOf(n.getLanguagePartFromCode(e))>-1||e.toLowerCase().indexOf(`-arab`)>1?`rtl`:`ltr`}static createInstance(t={},n){let r=new e(t,n);return r.createInstance=e.createInstance,r}cloneInstance(t={},n=we){let r=t.forkResourceStore;r&&delete t.forkResourceStore;let i={...this.options,...t,isClone:!0},a=new e(i);return(t.debug!==void 0||t.prefix!==void 0)&&(a.logger=a.logger.clone(t)),[`store`,`services`,`language`].forEach(e=>{a[e]=this[e]}),a.services={...this.services},a.services.utils={hasLoadedNamespace:a.hasLoadedNamespace.bind(a)},r&&(a.store=new ie(Object.keys(this.store.data).reduce((e,t)=>(e[t]={...this.store.data[t]},e[t]=Object.keys(e[t]).reduce((n,r)=>(n[r]={...e[t][r]},n),e[t]),e),{}),i),a.services.resourceStore=a.store),a.translator=new le(a.services,i),a.translator.on(`*`,(e,...t)=>{a.emit(e,...t)}),a.init(i,n),a.translator.options=i,a.translator.backendConnector.services.utils={hasLoadedNamespace:a.hasLoadedNamespace.bind(a)},a}toJSON(){return{options:this.options,store:this.store,language:this.language,languages:this.languages,resolvedLanguage:this.resolvedLanguage}}}.createInstance();Ee.createInstance,Ee.dir,Ee.init,Ee.loadResources,Ee.reloadResources,Ee.use,Ee.changeLanguage,Ee.getFixedT,Ee.t,Ee.exists,Ee.setDefaultNamespace,Ee.hasLoadedNamespace,Ee.loadNamespaces,Ee.loadLanguages;var De=(e,t,n,r)=>{let i=[n,{code:t,...r||{}}];if(e?.services?.logger?.forward)return e.services.logger.forward(i,`warn`,`react-i18next::`,!0);Pe(i[0])&&(i[0]=`react-i18next:: ${i[0]}`),e?.services?.logger?.warn?e.services.logger.warn(...i):console?.warn&&console.warn(...i)},Oe={},ke=(e,t,n,r)=>{Pe(n)&&Oe[n]||(Pe(n)&&(Oe[n]=new Date),De(e,t,n,r))},Ae=(e,t)=>()=>{if(e.isInitialized)t();else{let n=()=>{setTimeout(()=>{e.off(`initialized`,n)},0),t()};e.on(`initialized`,n)}},je=(e,t,n)=>{e.loadNamespaces(t,Ae(e,n))},Me=(e,t,n,r)=>{if(Pe(n)&&(n=[n]),e.options.preload&&e.options.preload.indexOf(t)>-1)return je(e,n,r);n.forEach(t=>{e.options.ns.indexOf(t)<0&&e.options.ns.push(t)}),e.loadLanguages(t,Ae(e,r))},Ne=(e,t,n={})=>!t.languages||!t.languages.length?(ke(t,`NO_LANGUAGES`,`i18n.languages were undefined or empty`,{languages:t.languages}),!0):t.hasLoadedNamespace(e,{lng:n.lng,precheck:(t,r)=>{if(n.bindI18n&&n.bindI18n.indexOf(`languageChanging`)>-1&&t.services.backendConnector.backend&&t.isLanguageChangingTo&&!r(t.isLanguageChangingTo,e))return!1}}),Pe=e=>typeof e==`string`,Fe=e=>typeof e==`object`&&!!e,Ie=/&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34|nbsp|#160|copy|#169|reg|#174|hellip|#8230|#x2F|#47);/g,Le={"&":`&`,"&":`&`,"<":`<`,"<":`<`,">":`>`,">":`>`,"'":`'`,"'":`'`,""":`"`,""":`"`," ":` `," ":` `,"©":`©`,"©":`©`,"®":`®`,"®":`®`,"…":`…`,"…":`…`,"/":`/`,"/":`/`},Re=e=>Le[e],ze={bindI18n:`languageChanged`,bindI18nStore:``,transEmptyNodeValue:``,transSupportBasicHtmlNodes:!0,transWrapTextNodes:``,transKeepBasicHtmlNodesFor:[`br`,`strong`,`i`,`p`],useSuspense:!0,unescape:e=>e.replace(Ie,Re),transDefaultProps:void 0},Be=(e={})=>{ze={...ze,...e}},Ve=()=>ze,He,Ue=e=>{He=e},We=()=>He,Ge={type:`3rdParty`,init(e){Be(e.options.react),Ue(e)}},Ke=(0,y.createContext)(),qe=class{constructor(){this.usedNamespaces={}}addUsedNamespaces(e){e.forEach(e=>{this.usedNamespaces[e]||(this.usedNamespaces[e]=!0)})}getUsedNamespaces(){return Object.keys(this.usedNamespaces)}},Je=o((e=>{var t=f();function n(e,t){return e===t&&(e!==0||1/e==1/t)||e!==e&&t!==t}var r=typeof Object.is==`function`?Object.is:n,i=t.useState,a=t.useEffect,o=t.useLayoutEffect,s=t.useDebugValue;function c(e,t){var n=t(),r=i({inst:{value:n,getSnapshot:t}}),c=r[0].inst,u=r[1];return o(function(){c.value=n,c.getSnapshot=t,l(c)&&u({inst:c})},[e,n,t]),a(function(){return l(c)&&u({inst:c}),e(function(){l(c)&&u({inst:c})})},[e]),s(n),n}function l(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!r(e,n)}catch{return!0}}function u(e,t){return t()}var d=typeof window>`u`||window.document===void 0||window.document.createElement===void 0?u:c;e.useSyncExternalStore=t.useSyncExternalStore===void 0?d:t.useSyncExternalStore})),Ye=o(((e,t)=>{t.exports=Je()})),Xe=Ye(),Ze={t:(e,t)=>Pe(t)?t:Fe(t)&&Pe(t.defaultValue)?t.defaultValue:Array.isArray(e)?e[e.length-1]:e,ready:!1},Qe=()=>()=>{},$e=(e,t={})=>{let{i18n:n}=t,{i18n:r,defaultNS:i}=(0,y.useContext)(Ke)||{},a=n||r||We();a&&!a.reportNamespaces&&(a.reportNamespaces=new qe),a||ke(a,`NO_I18NEXT_INSTANCE`,`useTranslation: You will need to pass in an i18next instance by using initReactI18next`);let o=(0,y.useMemo)(()=>({...Ve(),...a?.options?.react,...t}),[a,t]),{useSuspense:s,keyPrefix:c}=o,l=e||i||a?.options?.defaultNS,u=Pe(l)?[l]:l||[`translation`],d=(0,y.useMemo)(()=>u,u);a?.reportNamespaces?.addUsedNamespaces?.(d);let f=(0,y.useRef)(0),p=(0,y.useCallback)(e=>{if(!a)return Qe;let{bindI18n:t,bindI18nStore:n}=o,r=()=>{f.current+=1,e()};return t&&a.on(t,r),n&&a.store.on(n,r),()=>{t&&t.split(` `).forEach(e=>a.off(e,r)),n&&n.split(` `).forEach(e=>a.store.off(e,r))}},[a,o]),m=(0,y.useRef)(),h=(0,y.useCallback)(()=>{if(!a)return Ze;let e=!!(a.isInitialized||a.initializedStoreOnce)&&d.every(e=>Ne(e,a,o)),n=t.lng||a.language,r=f.current,i=m.current;if(i&&i.ready===e&&i.lng===n&&i.keyPrefix===c&&i.revision===r)return i;let s={t:a.getFixedT(n,o.nsMode===`fallback`?d:d[0],c),ready:e,lng:n,keyPrefix:c,revision:r};return m.current=s,s},[a,d,c,o,t.lng]),[g,_]=(0,y.useState)(0),{t:v,ready:b}=(0,Xe.useSyncExternalStore)(p,h,h);(0,y.useEffect)(()=>{if(a&&!b&&!s){let e=()=>_(e=>e+1);t.lng?Me(a,t.lng,d,e):je(a,d,e)}},[a,t.lng,d,b,s,g]);let x=a||{},S=(0,y.useRef)(null),C=(0,y.useRef)(),w=e=>{let t=Object.getOwnPropertyDescriptors(e);t.__original&&delete t.__original;let n=Object.create(Object.getPrototypeOf(e),t);if(!Object.prototype.hasOwnProperty.call(n,`__original`))try{Object.defineProperty(n,"__original",{value:e,writable:!1,enumerable:!1,configurable:!1})}catch{}return n},T=(0,y.useMemo)(()=>{let e=x,t=e?.language,n=e;e&&(S.current&&S.current.__original===e&&C.current===t?n=S.current:(n=w(e),S.current=n,C.current=t));let r=[v,n,b];return r.t=v,r.i18n=n,r.ready=b,r},[v,x,b,x.resolvedLanguage,x.language,x.languages]);if(a&&s&&!b)throw new Promise(e=>{let n=()=>e();t.lng?Me(a,t.lng,d,n):je(a,d,n)});return T},{slice:et,forEach:tt}=[];function nt(e){return tt.call(et.call(arguments,1),t=>{if(t)for(let n in t)e[n]===void 0&&(e[n]=t[n])}),e}function rt(e){return typeof e==`string`?[/<\s*script.*?>/i,/<\s*\/\s*script\s*>/i,/<\s*img.*?on\w+\s*=/i,/<\s*\w+\s*on\w+\s*=.*?>/i,/javascript\s*:/i,/vbscript\s*:/i,/expression\s*\(/i,/eval\s*\(/i,/alert\s*\(/i,/document\.cookie/i,/document\.write\s*\(/i,/window\.location/i,/innerHTML/i].some(t=>t.test(e)):!1}var it=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/,at=function(e,t){let n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{path:`/`},r=`${e}=${encodeURIComponent(t)}`;if(n.maxAge>0){let e=n.maxAge-0;if(Number.isNaN(e))throw Error(`maxAge should be a Number`);r+=`; Max-Age=${Math.floor(e)}`}if(n.domain){if(!it.test(n.domain))throw TypeError(`option domain is invalid`);r+=`; Domain=${n.domain}`}if(n.path){if(!it.test(n.path))throw TypeError(`option path is invalid`);r+=`; Path=${n.path}`}if(n.expires){if(typeof n.expires.toUTCString!=`function`)throw TypeError(`option expires is invalid`);r+=`; Expires=${n.expires.toUTCString()}`}if(n.httpOnly&&(r+=`; HttpOnly`),n.secure&&(r+=`; Secure`),n.sameSite)switch(typeof n.sameSite==`string`?n.sameSite.toLowerCase():n.sameSite){case!0:r+=`; SameSite=Strict`;break;case`lax`:r+=`; SameSite=Lax`;break;case`strict`:r+=`; SameSite=Strict`;break;case`none`:r+=`; SameSite=None`;break;default:throw TypeError(`option sameSite is invalid`)}return n.partitioned&&(r+=`; Partitioned`),r},ot={create(e,t,n,r){let i=arguments.length>4&&arguments[4]!==void 0?arguments[4]:{path:`/`,sameSite:`strict`};n&&(i.expires=new Date,i.expires.setTime(i.expires.getTime()+n*60*1e3)),r&&(i.domain=r),document.cookie=at(e,t,i)},read(e){let t=`${e}=`,n=document.cookie.split(`;`);for(let e=0;e-1&&(e=window.location.hash.substring(window.location.hash.indexOf(`?`)));let r=e.substring(1).split(`&`);for(let e=0;e0&&r[e].substring(0,i)===t&&(n=r[e].substring(i+1))}}return n}},lt={name:`hash`,lookup(e){let{lookupHash:t,lookupFromHashIndex:n}=e,r;if(typeof window<`u`){let{hash:e}=window.location;if(e&&e.length>2){let i=e.substring(1);if(t){let e=i.split(`&`);for(let n=0;n0&&e[n].substring(0,i)===t&&(r=e[n].substring(i+1))}}if(r)return r;if(!r&&n>-1){let t=e.match(/\/([a-zA-Z-]*)/g);return Array.isArray(t)?t[typeof n==`number`?n:0]?.replace(`/`,``):void 0}}}return r}},ut=null,dt=()=>{if(ut!==null)return ut;try{if(ut=typeof window<`u`&&window.localStorage!==null,!ut)return!1;let e=`i18next.translate.boo`;window.localStorage.setItem(e,`foo`),window.localStorage.removeItem(e)}catch{ut=!1}return ut},ft={name:`localStorage`,lookup(e){let{lookupLocalStorage:t}=e;if(t&&dt())return window.localStorage.getItem(t)||void 0},cacheUserLanguage(e,t){let{lookupLocalStorage:n}=t;n&&dt()&&window.localStorage.setItem(n,e)}},pt=null,mt=()=>{if(pt!==null)return pt;try{if(pt=typeof window<`u`&&window.sessionStorage!==null,!pt)return!1;let e=`i18next.translate.boo`;window.sessionStorage.setItem(e,`foo`),window.sessionStorage.removeItem(e)}catch{pt=!1}return pt},ht={name:`sessionStorage`,lookup(e){let{lookupSessionStorage:t}=e;if(t&&mt())return window.sessionStorage.getItem(t)||void 0},cacheUserLanguage(e,t){let{lookupSessionStorage:n}=t;n&&mt()&&window.sessionStorage.setItem(n,e)}},gt={name:`navigator`,lookup(e){let t=[];if(typeof navigator<`u`){let{languages:e,userLanguage:n,language:r}=navigator;if(e)for(let n=0;n0?t:void 0}},_t={name:`htmlTag`,lookup(e){let{htmlTag:t}=e,n,r=t||(typeof document<`u`?document.documentElement:null);return r&&typeof r.getAttribute==`function`&&(n=r.getAttribute(`lang`)),n}},vt={name:`path`,lookup(e){let{lookupFromPathIndex:t}=e;if(typeof window>`u`)return;let n=window.location.pathname.match(/\/([a-zA-Z-]*)/g);if(Array.isArray(n))return n[typeof t==`number`?t:0]?.replace(`/`,``)}},yt={name:`subdomain`,lookup(e){let{lookupFromSubdomainIndex:t}=e,n=typeof t==`number`?t+1:1,r=typeof window<`u`&&window.location?.hostname?.match(/^(\w{2,5})\.(([a-z0-9-]{1,63}\.[a-z]{2,6})|localhost)/i);if(r)return r[n]}},bt=!1;try{document.cookie,bt=!0}catch{}var xt=[`querystring`,`cookie`,`localStorage`,`sessionStorage`,`navigator`,`htmlTag`];bt||xt.splice(1,1);var St=()=>({order:xt,lookupQuerystring:`lng`,lookupCookie:`i18next`,lookupLocalStorage:`i18nextLng`,lookupSessionStorage:`i18nextLng`,caches:[`localStorage`],excludeCacheFor:[`cimode`],convertDetectedLanguage:e=>e}),Ct=class{constructor(e){let t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};this.type=`languageDetector`,this.detectors={},this.init(e,t)}init(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{languageUtils:{}},t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};this.services=e,this.options=nt(t,this.options||{},St()),typeof this.options.convertDetectedLanguage==`string`&&this.options.convertDetectedLanguage.indexOf(`15897`)>-1&&(this.options.convertDetectedLanguage=e=>e.replace(`-`,`_`)),this.options.lookupFromUrlIndex&&(this.options.lookupFromPathIndex=this.options.lookupFromUrlIndex),this.i18nOptions=n,this.addDetector(st),this.addDetector(ct),this.addDetector(ft),this.addDetector(ht),this.addDetector(gt),this.addDetector(_t),this.addDetector(vt),this.addDetector(yt),this.addDetector(lt)}addDetector(e){return this.detectors[e.name]=e,this}detect(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:this.options.order,t=[];return e.forEach(e=>{if(this.detectors[e]){let n=this.detectors[e].lookup(this.options);n&&typeof n==`string`&&(n=[n]),n&&(t=t.concat(n))}}),t=t.filter(e=>e!=null&&!rt(e)).map(e=>this.options.convertDetectedLanguage(e)),this.services&&this.services.languageUtils&&this.services.languageUtils.getBestMatchFromCodes?t:t.length>0?t[0]:null}cacheUserLanguage(e){let t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:this.options.caches;t&&(this.options.excludeCacheFor&&this.options.excludeCacheFor.indexOf(e)>-1||t.forEach(t=>{this.detectors[t]&&this.detectors[t].cacheUserLanguage(e,this.options)}))}};Ct.type=`languageDetector`;var wt={en:{translation:{nav:{printers:`Printers`,archives:`Archives`,queue:`Print Queue`,stats:`Statistics`,profiles:`Profiles`,maintenance:`Maintenance`,projects:`Projects`,inventory:`Filament`,files:`File Manager`,makerworld:`MakerWorld`,notifications:`Notifications`,settings:`Settings`,system:`System`,collapseSidebar:`Collapse sidebar`,expandSidebar:`Expand sidebar`,update:`Update`,updateAvailable:`Update available: v{{version}}`,updateAvailableBanner:`Version {{version}} is available!`,viewUpdate:`View update`,viewOnGithub:`View on GitHub`,keyboardShortcuts:`Keyboard shortcuts (?)`,switchToLight:`Switch to light mode`,switchToDark:`Switch to dark mode`,switchToSystem:`Switch to system mode`,smartSwitches:`Smart Switches`,logout:`Logout`,installApp:`Install app`,installAppSuccess:`Bambuddy was installed`},common:{save:`Save`,saving:`Saving...`,cancel:`Cancel`,delete:`Delete`,edit:`Edit`,add:`Add`,close:`Close`,confirm:`Confirm`,loading:`Loading...`,error:`Error`,errorLoading:`Error loading data`,retry:`Retry`,success:`Success`,warning:`Warning`,enabled:`Enabled`,disabled:`Disabled`,yes:`Yes`,no:`No`,on:`On`,off:`Off`,all:`All`,none:`None`,search:`Search`,filter:`Filter`,sort:`Sort`,refresh:`Refresh`,download:`Download`,upload:`Upload`,uploading:`Uploading...`,uploadFailed:`Upload failed`,actions:`Actions`,status:`Status`,name:`Name`,description:`Description`,date:`Date`,time:`Time`,hours:`hours`,minutes:`minutes`,seconds:`seconds`,days:`days`,enable:`Enable`,disable:`Disable`,permissions:`Permissions`,noPrinters:`No printers configured`,noData:`No data available`,linkNotFound:`Link not found`,required:`Required`,optional:`Optional`,dismiss:`Dismiss`,apply:`Apply`,reset:`Reset`,export:`Export`,import:`Import`,clear:`Clear`,selectAll:`Select All`,deselectAll:`Deselect All`,noChange:`— No change —`,unchanged:`Unchanged`,unassigned:`Unassigned`,unknown:`Unknown`,unknownError:`Unknown error`,today:`Today`,tomorrow:`Tomorrow`,asap:`ASAP`,overdue:`Overdue`,now:`Now`,collapse:`Collapse`,expand:`Expand`,previous:`Previous`,next:`Next`,viewArchive:`View archive`,viewInFileManager:`View in File Manager`,addedBy:`Added by {{username}}`,prints:`prints`,more:`+{{count}} more`,ascending:`Ascending`,descending:`Descending`,back:`Back`,copy:`Copy`,copied:`Copied!`,printer:`Printer`,remove:`Remove`,type:`Type`,print:`Print`,rename:`Rename`,move:`Move`,create:`Create`,duplicate:`Duplicate`,left:`Left`,right:`Right`},printers:{title:`Printers`,addPrinter:`Add Printer`,addPreflight:{checking:`Checking connection...`,warning:`Some connection checks failed. This printer may show as offline. Review the checks below, fix what you can, or save anyway.`,back:`Back`,saveAnyway:`Save anyway`},editPrinter:`Edit Printer`,deletePrinter:`Delete Printer`,printerName:`Printer Name`,serialNumber:`Serial Number`,ipAddress:`IP Address / Hostname`,accessCode:`Access Code`,model:`Model`,nozzleCount:`Nozzle Count`,autoArchive:`Auto Archive`,status:{available:`Available`,idle:`Idle`,printing:`Printing`,paused:`Paused`,offline:`Offline`,problem:`Problem`,error:`Error`,finished:`Finished`,unknown:`Unknown`},temperatures:{nozzle:`Nozzle`,bed:`Bed`,chamber:`Chamber`},heaterHistory:{title:`Heater History`,openLabel:`View heater history`,nozzle:`Nozzle`,nozzle2:`Nozzle 2`,bed:`Bed`,chamber:`Chamber`,error:`Failed to load history`,empty:`No data recorded yet`},progress:`{{percent}}% complete`,timeRemaining:`{{time}} remaining`,deleteConfirm:`Are you sure you want to delete "{{name}}"?`,maintenanceOk:`Maintenance OK`,maintenanceWarning:`{{count}} warning`,maintenanceWarning_plural:`{{count}} warnings`,maintenanceDue:`{{count}} due`,maintenanceDue_plural:`{{count}} due`,sort:{name:`Name`,status:`Status`,model:`Model`,location:`Location`,eta:`ETA`,ascending:`Sort ascending`,descending:`Sort descending`},cardSize:{small:`Small cards`,medium:`Medium cards`,large:`Large cards`,extraLarge:`Extra large cards`},pageView:{openCamWallPage:`Open cam wall as page`,cards:`Cards`,camWall:`Cam wall`},camWall:{page:{tokenRejected:`This Cam Wall link is no longer valid. The token may have expired or been revoked.`,loadFailed:`Could not load the printers.`},noPrinters:`No printers to show`,noSignal:`No signal`,live:`Live`,snap:`Snap`,off:`Off`,summary:`{{live}} live, {{snap}} snapshots, {{total}} total`,layer:`Layer {{cur}}/{{total}}`,timeLeft:`{{time}} left`,statusMode:{off:`Off`,compact:`Compact`,full:`Full`},settings:{title:`Cam wall settings`,maxLive:`Max live streams`,maxLiveHint:`How many tiles stream live at once. Others refresh as snapshots.`,snapshotInterval:`Snapshot interval (seconds)`,snapshotIntervalHint:`How often non-live tiles fetch a fresh snapshot.`,statusOverlay:`Status overlay`,statusOverlayHint:`Compact: state badge only. Full: + progress, layer, time left.`}},hideOffline:`Hide offline`,nextAvailable:`Next available`,powerOn:`Power On`,offlinePrintersWithPlugs:`Offline printers with smart plugs`,noPrintersConfigured:`No printers configured yet`,search:`Search printers...`,noSearchResults:`No printers match your search or filters`,filter:{allStatuses:`All statuses`,allLocations:`All locations`},toolbar:{filters:`Filters`,view:`View`,actions:`Actions`},readyToPrint:`Ready to print`,external:`External`,extL:`Ext-L`,extR:`Ext-R`,deleteArchives:`Delete print archives`,noLabel:`No label`,printPreview:`Print preview`,width:`Width`,height:`Height`,noObjectsFound:`No objects found`,objectsLoadedOnPrintStart:`Objects are loaded when a print starts`,willBeSkipped:`Will be skipped`,name:`Name`,serialCannotBeChanged:`Serial number cannot be changed`,locationHelp:`Used to group printers and filter queue jobs`,wifiSignal:{veryWeak:`Very weak`,weak:`Weak`,fair:`Fair`,good:`Good`,excellent:`Excellent`},maintenanceUpToDate:`All maintenance up to date - Click to view`,maintenance:{title:`In Maintenance`,subtitle:`This printer is paused — not connected, not eligible for the queue, not sending notifications.`,pillLabel:`Maintenance`,exitButton:`Exit maintenance`,menuEnter:`Enter maintenance mode`,menuExit:`Exit maintenance mode`,toastEntered:`{{name}} is now in maintenance mode`,toastExited:`{{name}} is back online`,confirmMidPrintTitle:`Enter maintenance mode mid-print?`,confirmMidPrintMessage:`{{name}} is currently printing. Entering maintenance mode will disconnect MQTT and stop progress tracking and completion notifications for this job. Continue?`,editFieldLabel:`Maintenance mode`,editFieldHelp:`When on, this printer is paused from MQTT, queue dispatch and notifications — useful for repair, parallel Bambuddy installs, or temporary suspension.`},chamberLightOn:`Turn on chamber light`,chamberLightOff:`Turn off chamber light`,files:`Files`,browseFiles:`Browse printer files`,autoOffAfterPrint:`Auto power-off after print`,autoOffExecuted:`Auto-off was executed - turn printer on to reset`,hmsErrors:`HMS Errors`,viewHmsErrors:`View {{count}} HMS error(s)`,resume:`Resume`,pause:`Pause`,stop:`Stop`,camera:`Camera`,skipObject:`Skip Object`,reconnect:`Reconnect`,forceRefresh:`Force Refresh`,forceRefreshSuccess:`Refresh requested`,mqttDebug:`MQTT Debug`,printerInformation:`Printer Information`,copyToClipboard:`Copy`,copied:`Copied!`,state:`State`,wifiSignalLabel:`WiFi Signal`,developerMode:`Developer Mode`,enabled:`Enabled`,disabled:`Disabled`,addedOn:`Added`,sdCard:`SD Card`,inserted:`Inserted`,notInserted:`Not inserted`,totalPrintHours:`Print Hours`,activeNozzle:`Active: {{nozzle}} nozzle`,nozzleRack:`Nozzle Rack`,nozzleDocked:`Docked`,nozzleMounted:`Mounted`,nozzleActive:`Active`,nozzleIdle:`Idle`,nozzleDiameter:`Diameter`,nozzleType:`Type`,nozzleStatus:`Status`,nozzleFilament:`Filament`,nozzleWear:`Wear`,nozzleMaxTemp:`Max Temp`,nozzleSerial:`Serial`,nozzleHardenedSteel:`Hardened Steel`,nozzleStainlessSteel:`Stainless Steel`,nozzleTungstenCarbide:`Tungsten Carbide`,nozzleFlow:`Flow`,nozzleHighFlow:`High Flow`,nozzleStandardFlow:`Standard`,firmwareUpdate:`Firmware Update`,firmwareInstructions:`On the printer's touchscreen, go to`,firmwareNav:`Navigate to`,settings:`Settings`,firmware:`Firmware`,discoverPrinters:`Discover Printers`,searching:`Searching...`,manualEntry:`Manual Entry`,addFromCloud:`Add from Cloud`,toast:{printerDeleted:`Printer deleted`,missingSpoolAssignment:`Print started on {{printer}}. Missing spool assignment for: {{slots}}`,assignmentVerified:`Filament loaded on slot {{slot}} ({{printer}})`,assignmentVerifiedNoKprofile:`Slot {{slot}} on {{printer}} loaded, but the flow calibration (K-profile) was not applied`,assignmentNotConfirmed:`Could not confirm the assignment for slot {{slot}} on {{printer}} — check the AMS slot`,printerAdded:`Printer added`,printerUpdated:`Printer updated`,failedToDelete:`Failed to delete printer`,failedToAdd:`Failed to add printer`,connectionFailedNotAdded:`Could not connect to the printer. Verify the IP, serial number, and access code, and confirm LAN-only mode is on. The printer was not added.`,failedToUpdate:`Failed to update printer`,commandSent:`Command sent`,failedToSendCommand:`Failed to send command`,turnedOn:`{{name}} turned on`,failedToPowerOn:`Failed to power on {{name}}`,scriptTriggered:`Script triggered`,printStopped:`Print stopped`,printPaused:`Print paused`,printResumed:`Print resumed`,referenceDeleted:`Reference deleted`,detectionAreaSaved:`Detection area saved`,failedToRunScript:`Failed to run script`,failedToStopPrint:`Failed to stop print`,failedToPausePrint:`Failed to pause print`,failedToResumePrint:`Failed to resume print`,failedToControlChamberLight:`Failed to control chamber light`,failedToSetSpeed:`Failed to set print speed`,failedToUpdateSetting:`Failed to update setting`,failedToSkipObjects:`Failed to skip objects`,failedToRereadRfid:`Failed to re-read RFID`,failedToCheckPlate:`Failed to check plate`,failedToUpdateLabel:`Failed to update label`,failedToDeleteReference:`Failed to delete reference`,failedToSaveDetectionArea:`Failed to save detection area`,plateCheckEnabled:`Plate check enabled`,plateCheckDisabled:`Plate check disabled`,calibrationSaved:`Calibration saved!`,calibrationFailed:`Calibration failed`,rfidRereadInitiated:`RFID re-read initiated`,loadInitiated:`Loading filament…`,unloadInitiated:`Unloading filament…`,failedToLoad:`Failed to load filament`,failedToUnload:`Failed to unload filament`},connection:{connected:`Connected`,offline:`Offline`},plateStatus:{markCleared:`Mark plate as cleared`,cleared:`Plate Clear`,notCleared:`Plate not Clear`,inUse:`Plate in Use`},queue:{inQueue:`{{count}} print in queue`,inQueue_plural:`{{count}} prints in queue`},controls:`Controls`,rfid:{reread:`Re-read RFID`},ams:{load:`Load`,unload:`Unload`},bedJog:{limitWarning:`Travel limits are not enforced during manual moves — a Bambu firmware bug ignores software endstops for remote commands. Move carefully to avoid a collision.`,title:`Jog Controls`,bed:`Bed`,step:`Step (mm)`,up:`Move plate up`,down:`Move plate down`,disabledWhilePrinting:`Disabled while printing`,notHomedTitle:`Printer is not homed`,notHomedMessage:`The printer has not been homed since the last print. Run auto-home first for safe positioning (parks the toolhead, then homes X, Y, and Z), or move anyway — soft endstops will be bypassed.`,homeZ:`Auto Home`,moveAnyway:`Move anyway`,homingStarted:`Auto-homing printer…`},permission:{noAdd:`You do not have permission to add printers`,noEdit:`You do not have permission to edit printers`,noDelete:`You do not have permission to delete printers`,noControl:`You do not have permission to control printers`,noFiles:`You do not have permission to access printer files`,noAmsRfid:`You do not have permission to re-read AMS RFID`,noSmartPlugControl:`You do not have permission to control smart plugs`,noCamera:`You do not have permission to view cameras`},modal:{addTitle:`Add Printer`,editTitle:`Edit Printer`,myPrinter:`My Printer`,selectModel:`Select model...`,locationGroup:`Location / Group (optional)`,locationPlaceholder:`e.g., Workshop, Office, Basement`,autoArchiveLabel:`Auto-archive completed prints`,fromPrinterSettings:`From printer settings`,modelOptional:`Model (optional)`,saveChanges:`Save Changes`},skipObjects:{tooltip:`Skip objects`,onlyWhilePrinting:`Skip objects (only while printing)`,requiresMultiple:`Skip objects (requires 2+ objects)`,title:`Skip Objects`,matchIdsInfo:`Match IDs with your printer display`,printerShowsIds:`The printer screen shows object IDs on the build plate`,skipSelected:`Skip Selected`,skipping:`Skipping...`,noObjectsSelected:`No objects selected`,selectObjectsToSkip:`Select objects you want to skip from the current print`,skipped:`skipped`,objectsSkipped:`Objects skipped`,activeCount:`{{count}} active`,waitForLayer:`Wait for layer 2+ to skip objects (currently layer {{layer}})`,skip:`Skip`,confirmTitle:`Skip Object?`,confirmMessage:`Are you sure you want to skip "{{name}}"? This cannot be undone.`,confirmAllMessage:`All remaining objects are selected. This will stop the print job. Continue?`,confirmMultipleMessage:`Skip {{count}} selected objects? This cannot be undone.`},confirm:{deleteTitle:`Delete Printer`,deleteMessage:`Are you sure you want to delete "{{name}}"? This will remove all connection settings.`,deleteArchivesNote:`All print history for this printer will be permanently deleted.`,keepArchivesNote:`Print history will be kept but no longer associated with this printer.`,stopTitle:`Stop Print`,stopMessage:`Are you sure you want to stop the current print on "{{name}}"? This will cancel the print job.`,stopButton:`Stop Print`,pauseTitle:`Pause Print`,pauseMessage:`Are you sure you want to pause the current print on "{{name}}"?`,pauseButton:`Pause Print`,resumeTitle:`Resume Print`,resumeMessage:`Are you sure you want to resume the print on "{{name}}"?`,resumeButton:`Resume Print`,powerOnTitle:`Power On Printer`,powerOnMessage:`Are you sure you want to turn ON the power for "{{name}}"?`,powerOnButton:`Power On`,powerOffTitle:`Power Off Printer`,powerOffMessage:`Are you sure you want to turn OFF the power for "{{name}}"?`,powerOffWarning:`WARNING: "{{name}}" is currently printing! Are you sure you want to turn OFF the power? This will interrupt the print and may damage the printer.`,powerOffButton:`Power Off`,haToggleTitle:`Toggle "{{name}}"`,haToggleMessage:`Toggle the Home Assistant entity {{entity}}? This may turn power off if it is currently on.`,haToggleWarning:`WARNING: "{{name}}" is currently printing! Toggling {{entity}} may cut power and interrupt the print. Continue?`,haToggleButton:`Toggle`},bulk:{select:`Select`,selectAll:`Select All`,selectByLocation:`Select by Location`,selected:`{{count}} selected`,actions:{stop:`Stop`,pause:`Pause`,resume:`Resume`,clearPlate:`Clear Bed`,clearHMS:`Clear Notifications`},confirm:{stopTitle:`Stop {{count}} Prints`,stopMessage:`This will cancel active prints on {{count}} printer(s). This action cannot be undone.`,stopButton:`Stop All`,pauseTitle:`Pause {{count}} Prints`,pauseMessage:`This will pause active prints on {{count}} printer(s).`,pauseButton:`Pause All`,clearPlateTitle:`Clear {{count}} Print Beds`,clearPlateMessage:`This will clear the print bed on {{count}} printer(s) and may trigger queued jobs.`,clearPlateButton:`Clear All`},success:`{{action}} completed on {{count}} printer(s)`,partial:`{{succeeded}} succeeded, {{failed}} failed`,noneApplicable:`No selected printers are in the right state for this action`,selectByState:`Select by State`},discovery:{title:`Discover Printers`,searching:`Searching...`,scanning:`Scanning...`,scanProgress:`Scanning... {{scanned}}/{{total}}`,foundPrinters:`Found {{count}} printer(s)`,noPrintersFound:`No printers found`,noPrintersFoundSubnet:`No printers found in the specified subnet.`,noPrintersFoundNetwork:`No printers found on the network.`,allConfigured:`All discovered printers are already configured.`,alreadyAdded:`Already added`,select:`Select`,manualEntry:`Manual Entry`,addFromCloud:`Add from Cloud`,subnetToScan:`Subnet to scan`,dockerNote:`Docker detected. Enter your printer's subnet in CIDR notation. Requires network_mode: host in docker-compose.yml.`,scanSubnet:`Scan Subnet for Printers`,discoverNetwork:`Discover Printers on Network`,scanningSubnet:`Scanning subnet for Bambu printers...`,scanningNetwork:`Scanning network...`,serialRequired:`Serial required`,unknown:`Unknown`,failedToStart:`Failed to start discovery`,customSubnetOption:`Custom subnet...`,customSubnetLabel:`Custom subnet (CIDR)`,customSubnetNote:`Use a custom subnet if your printer is on a different network than this server. The FTP (990) and MQTT (8883) ports must be reachable across the routing boundary.`},drying:{start:`Start Drying`,stop:`Stop Drying`,temperature:`Temperature`,duration:`Duration`,hours:`hours`,timeRemaining:`{{time}} left`,active:`Drying`,targetSummary:`{{filament}} @ {{temp}}°C`,notSupported:`Drying not supported`,powerRequired:`Connect AMS power adapter to enable drying`,startingDrying:`Starting drying...`,toastCommandSent:`Drying command sent`,toastStopped:`Drying stopped`,toastNotStarted:`The printer accepted the command but the AMS never started drying. Check that the AMS power adapter is connected and that the printer is idle.`,screenOnly:`AMS drying on this printer can only be controlled from the printer's own screen (Bambu limitation)`,stoppingDrying:`Stopping drying...`,rotateTray:`Rotate spool during drying`,rotateUnavailableReason:`Unavailable — a slot in this AMS is loaded to the toolhead. The spool is locked by the feed tube and cannot rotate. Retract the filament first.`},amsBackup:{titleOn:`AMS Filament Backup is ON. Click to disable.`,titleOff:`AMS Filament Backup is OFF. Click to enable.`,titleUnknown:`AMS Filament Backup status unavailable on this printer.`,toastEnabled:`AMS Filament Backup enabled`,toastDisabled:`AMS Filament Backup disabled`,modalTitle:`AMS Filament Backup`,modalHelp:`When the active slot runs out, the printer cycles through any matching same-preset, same-colour slots in this order.`,modalNoSlots:`No filament loaded.`,modalNoPairs:`No backup pairs — no two slots share the same filament profile and colour.`,extruderRightShort:`R`,extruderLeftShort:`L`,stateOn:`Enabled`,stateOff:`Disabled`,stateUnknown:`Unsupported on this printer`},activeJobSlot:{title:`This slot is filament {{n}} in the active print`,ariaLabel:`Active print slot {{n}}`},expectedSlot:{title:`The printer is waiting for filament in this slot`,ariaLabel:`Expected filament slot {{n}}`,label:`{{ams}} · Slot {{slot}}`,external:`External spool`},filaments:`Filaments`,openCameraOverlay:`Open camera overlay`,openCameraWindow:`Open camera in new window`,firmwareUpdateAvailable:`Firmware update available: {{current}} → {{latest}}`,firmwareUpToDate:`Firmware {{version}} — Up to date`,firmwareUpdateButton:`Update`,plateDetection:{noPermission:`You do not have permission to update printers`,enabledClick:`Plate check enabled - Click to disable`,disabledClick:`Plate check disabled - Click to enable`,manageCalibration:`Manage plate detection calibration`,calibrationRequired:`Calibration Required`,calibrationInstructions:`Please ensure the build plate is completely empty, then click Calibrate.`,calibrationDescription:`Calibration captures a reference image of the empty plate. Future checks will compare against this reference to detect objects.`,calibrationTip:`Tip: You can store up to 5 calibrations for different plates. The system automatically uses the best match when checking.`,plateEmpty:`Plate appears empty`,objectsDetected:`Objects detected on plate`,confidence:`Confidence`,difference:`Difference`,analysisPreview:`Analysis preview:`,analysisLegend:`Green box = detection area, Red overlay = differences from calibration`,savedReferences:`Saved References ({{count}}/{{max}})`,deleteReference:`Delete reference`,labelPlaceholder:`Label...`,clickToEdit:`{{label}} - Click to edit`,clickToAddLabel:`Click to add label`},speed:{title:`Print Speed`,silent:`Silent (50%)`,standard:`Standard (100%)`,sport:`Sport (124%)`,ludicrous:`Ludicrous (166%)`},airduct:{title:`Airduct Mode`,cooling:`Cooling`,heating:`Heating`},noSdCard:`No SD`,door:{open:`Open`,closed:`Closed`},fans:{partCooling:`Part Cooling Fan`,auxiliary:`Auxiliary Fan`,leftAuxiliary:`Left Auxiliary Fan`,exhaust:`Exhaust`,chamber:`Chamber Fan`},clickToViewHmsErrors:`Click to view HMS errors`,aiDetection:{safe:`Safe`,warning:`Warning`,failure:`Failure`,idle:`Idle`,tooltip:`AI Failure Detection: {{status}} (score {{score}}) - click for details`,tooltipIdle:`AI Failure Detection enabled - monitoring starts with the next print - click for details`,modalTitle:`AI Failure Detection - {{name}}`,currentStatus:`Status`,score:`Score`,framesAnalyzed:`Frames analyzed`,idleHint:`No print is being monitored right now. Monitoring starts automatically with the next print.`,lastError:`Last error`,openSettings:`Open settings`},estimatedCompletion:`Estimated completion time`,plateNumber:`Plate {{number}}`,slotOptions:`Slot options`,amsPopup:{friendlyName:`AMS Name`,friendlyNamePlaceholder:`e.g. AMS Friendly Name`,serialNumber:`Serial Number`,firmwareVersion:`Firmware`,save:`Save`,clear:`Clear`,noEditPermission:`You do not have permission to rename AMS units`},firmwareModal:{title:`Firmware Update`,titleUpToDate:`Firmware Info`,currentVersion:`Current:`,latestVersion:`Latest:`,releaseNotes:`Release Notes`,checkingPrereqs:`Checking prerequisites...`,sdCardReady:`SD card ready. Click below to upload firmware.`,uploadedSuccess:`Firmware uploaded to SD card!`,applyInstructions:`To apply the update on your printer:`,step1:`On the printer's touchscreen, go to Settings`,step2:`Navigate to Firmware`,step3:`Select Update from SD card`,step4:`The update will take 10-20 minutes`,done:`Done`,starting:`Starting...`,uploadFirmware:`Upload Firmware`,uploadFailed:`Failed to start upload: {{error}}`,uploadedToast:`Firmware uploaded! Trigger update from printer screen.`,availableVersions:`Available versions`,usable:`Usable`,unavailable:`Unavailable`,installed:`Installed`,newerBadge:`newer`,olderBadge:`older`,currentBadge:`current`},accessCodePlaceholder:`Leave empty to keep current`,roi:{title:`Detection Area (ROI)`,xStart:`X Start`,yStart:`Y Start`,width:`Width`,height:`Height`,instruction:`Adjust the detection area to focus on the build plate. The green box in the preview shows the current area.`},developerModeWarning:`Developer LAN mode is not enabled on: {{names}}. Some features may not work.`,howToEnable:`How to enable`,incompatibleFile:`This file was sliced for {{slicedFor}}, but this printer is a {{printerModel}}`,dropNotPrintable:`Only .gcode and .gcode.3mf files can be printed`,dropToPrint:`Drop to print`,cannotPrint:`Printer busy`},archives:{title:`Print Archives`,no3mfBanner:{title:`Some recent prints couldn't be archived with thumbnails`,body:`The slicer didn't leave the .gcode.3mf on the printer's SD card, so Bambuddy couldn't pull the thumbnail or slicer metadata. This is usually because "Store sent files on external storage" is off in the slicer (Bambu Studio / OrcaSlicer Device tab).`,docsLink:`See install step 4`,dismissLabel:`Dismiss this notice`},searchPlaceholder:`Search archives...`,filterByPrinter:`Filter by printer`,filterByStatus:`Filter by status`,sortBy:`Sort by`,sortNewest:`Newest first`,sortOldest:`Oldest first`,sortName:`Name`,sortDuration:`Duration`,sortLargest:`Largest first`,sortSmallest:`Smallest first`,sortSize:`Size`,noArchives:`No archives found`,noArchivesSearch:`No archives match your search`,originalPrintNotVisible:`Original print not visible - try clearing filters`,noArchivesYet:`No archives yet`,prints:`prints`,pagination:{showing:`Showing`,to:`to`,of:`of`,show:`Show`,page:`Page`,all:`All`},loadingArchives:`Loading archives...`,releaseToUpload:`Release to upload`,showAll:`Show all`,showFavoritesOnly:`Show favorites only`,gridView:`Grid view`,listView:`List view`,calendarView:`Calendar view`,logView:`Print Log`,manageTags:`Manage Tags`,showFailedPrints:`Show failed prints`,hideFailedPrints:`Hide failed prints`,hideDuplicates:`Hide Duplicates`,viewOriginalPrint:`Click to view original print (#{{id}})`,printTime:`Print Time`,filamentUsed:`Filament Used`,cost:`Cost`,preview:`Preview`,deleteArchive:`Delete Archive`,deleteConfirm:`Are you sure you want to delete this archive?`,favorite:`Favorite`,unfavorite:`Remove from favorites`,viewDetails:`View Details`,status:{completed:`Completed`,failed:`Failed`,stopped:`Stopped`},toast:{source3mfAttached:`Source 3MF attached: {{filename}}`,failedUploadSource3mf:`Failed to upload source 3MF`,source3mfRemoved:`Source 3MF removed`,failedRemoveSource3mf:`Failed to remove source 3MF`,f3dAttached:`F3D attached: {{filename}}`,failedUploadF3d:`Failed to upload F3D`,f3dRemoved:`F3D removed`,failedRemoveF3d:`Failed to remove F3D`,timelapseAttached:`Timelapse attached: {{filename}}`,timelapseAlreadyAttached:`Timelapse already attached`,noMatchingTimelapse:`No matching timelapse found`,failedScanTimelapse:`Failed to scan for timelapse`,failedAttachTimelapse:`Failed to attach timelapse`,timelapseRemoved:`Timelapse removed`,failedRemoveTimelapse:`Failed to remove timelapse`,timelapseUploaded:`Timelapse uploaded: {{filename}}`,failedUploadTimelapse:`Failed to upload timelapse`,archiveDeleted:`Archive deleted`,failedDeleteArchive:`Failed to delete archive`,addedToFavorites:`Added to favorites`,removedFromFavorites:`Removed from favorites`,projectUpdated:`Project updated`,failedUpdateProject:`Failed to update project`,linkCopied:`Link copied to clipboard`,failedCopyLink:`Failed to copy link`,photoDeleted:`Photo deleted`,failedDeletePhoto:`Failed to delete photo`,failedDeleteArchives:`Failed to delete archives`,failedUpdateFavorites:`Failed to update favorites`,exportDownloaded:`Export downloaded`,exportFailed:`Export failed`},menu:{print:`Print`,openInBambuStudio:`Open in Slicer`,slice:`Slice`,externalLink:`External Link`,viewOnMakerWorld:`View on MakerWorld`,preview3d:`3D Preview`,viewTimelapse:`View Timelapse`,scanForTimelapse:`Scan for Timelapse`,uploadTimelapse:`Upload Timelapse`,removeTimelapse:`Remove Timelapse`,downloadSource3mf:`Download Source 3MF`,uploadSource3mf:`Upload Source 3MF`,replaceSource3mf:`Replace Source 3MF`,removeSource3mf:`Remove Source 3MF`,uploadF3d:`Upload F3D`,replaceF3d:`Replace F3D`,downloadF3d:`Download F3D`,removeF3d:`Remove F3D`,download:`Download`,copyDownloadLink:`Copy Download Link`,qrCode:`QR Code`,viewPhotos:`View Photos`,viewPhotosCount:`View Photos ({{count}})`,projectPage:`Project Page`,addToFavorites:`Add to Favorites`,removeFromFavorites:`Remove from Favorites`,edit:`Edit`,printLog:`Print Log`,goToProject:`Go to Project: {{name}}`,addToProject:`Add to Project`,removeFromProject:`Remove from Project`,loading:`Loading...`,noProjectsAvailable:`No projects available`,searchProjects:`Search projects…`,select:`Select`,deselect:`Deselect`,delete:`Delete`},permission:{noReprint:`You do not have permission to reprint this archive`,noAddToQueue:`You do not have permission to add to queue`,noUpdateArchives:`You do not have permission to update archives`,noUploadFiles:`You do not have permission to upload files`,noDownload:`You do not have permission to download archives`,noCopyLink:`You do not have permission to copy download links`,noDelete:`You do not have permission to delete this archive`,noEdit:`You do not have permission to edit this entry`,noCreate:`You do not have permission to create archives`},platePicker:{title:`Select plate to preview`,hint:`This archive has multiple plates. Pick one to open in the GCode viewer.`,plateLabel:`Plate {{index}}`,objectCount:`{{count}} object`,objectCount_plural:`{{count}} objects`,noGcode:`This archive has no sliced G-code to preview. Open it in Bambu Studio to slice first.`},card:{previousPlate:`Previous plate`,nextPlate:`Next plate`,plateNumber:`Plate {{index}}`,moreOptions:`Right-click for more options`,addToFavorites:`Add to favorites`,removeFromFavorites:`Remove from favorites`,cancelled:`cancelled`,failed:`failed`,duplicate:`duplicate`,duplicateTitle:`This model has been printed before`,openSource3mf:`Open source 3MF in Bambu Studio (right-click for more options)`,downloadF3d:`Download Fusion 360 design file`,viewTimelapse:`View timelapse`,viewPhoto:`View 1 photo`,viewPhotos:`View {{count}} photos`,openFolder:`Open folder: {{name}}`,slicedFile:`Sliced file - ready to print`,sourceFile:`Source file only - no AMS mapping available`,gcode:`GCODE`,source:`SOURCE`,project:`Project: {{name}}`,runsBadge:`{{count}} prints`,runsBadgeTitle:`{{count}} prints total — {{successful}} successful, {{failed}} failed. Click to see the full print log.`,estimated:`Estimated: {{time}}`,actual:`Actual: {{time}}`,accuracy:`Accuracy: {{percent}}%`,filament:`{{weight}}g`,layer:`{{count}} layer`,layers:`{{count}} layers`,object:`{{count}} object`,objects:`{{count}} objects`,slicedFor:`Sliced for {{model}}`,uploadedBy:`Uploaded By`,noPermissionReprint:`You do not have permission to reprint`,noFileForReprint:`No 3MF file available — the file could not be downloaded from the printer when the print was recorded`,slicerAmsMapping:`AMS mapping saved ({{printer}})`,slicerAmsMappingTooltip:`The slicer's own AMS slot choice was saved for {{printer}}. Tray numbers only mean something on that printer, so a reprint reuses them only when it targets {{printer}} again.`,noPermissionEdit:`You do not have permission to edit archives`,noPermissionDelete:`You do not have permission to delete archives`,openInBambuStudio:`Open in Slicer`,openInBambuStudioToSlice:`Open in Slicer to slice`,slice:`Slice`,externalLink:`External Link`,makerWorld:`MakerWorld: {{designer}}`,viewProject:`View project`,noExternalLink:`No external link`,preview3d:`3D Preview`,download:`Download`,edit:`Edit`,delete:`Delete`},runLog:{title:`Print Log`,modalTitle:`Print Log — {{name}}`,modalTitleFallback:`this archive`,empty:`No print events recorded for this archive yet.`,col:{date:`Date`,status:`Status`,duration:`Duration`,filament:`Filament`,cost:`Cost`},status:{completed:`Completed`,failed:`Failed`,cancelled:`Cancelled`,stopped:`Stopped`,skipped:`Skipped`,printing:`Printing`}},modal:{deleteArchive:`Delete Archive`,deleteConfirm:`Are you sure you want to delete "{{name}}"? This action cannot be undone.`,deleteButton:`Delete`,deletePurgeStats:`Also remove this print from Quick Stats (filament, time, cost, energy)`,deleteQueueItemsWarning:`{{count}} queue item(s) linked to this archive will also be removed.`,deleteBlockedByPrinting:`Cannot delete — {{count}} queue item(s) are currently printing. Stop the print first, then retry.`,removeSource3mf:`Remove Source 3MF`,removeSource3mfConfirm:`Are you sure you want to remove the source 3MF file from "{{name}}"? This will delete the original slicer project file.`,removeButton:`Remove`,removeF3d:`Remove F3D`,removeF3dConfirm:`Are you sure you want to remove the Fusion 360 design file from "{{name}}"?`,removeTimelapse:`Remove Timelapse`,removeTimelapseConfirm:`Are you sure you want to remove the timelapse video from "{{name}}"?`,timelapse:`{{name}} - Timelapse`,selectTimelapse:`Select Timelapse`,selectTimelapseDesc:`No auto-match found. Select the timelapse for this print:`,deleteArchives:`Delete Archives`,deleteArchivesConfirm:`Are you sure you want to delete {{count}} archive(s)? This action cannot be undone.`,deleteCount:`Delete {{count}}`},page:{title:`Archives`,printsCount:`{{filtered}} of {{total}} prints`,dropFilesHere:`Drop .3mf files here`,releaseToUpload:`Release to upload`,only3mfSupported:`Only .3mf files are supported`,close:`Close`,selected:`{{count}} selected`,selectAll:`Select All`,tags:`Tags`,project:`Project`,favorite:`Favorite`,delete:`Delete`,toggledFavorites:`Toggled favorites for {{count}} archive(s)`,failedUpdateFavorites:`Failed to update favorites`,archivesDeleted:`{{count}} archive(s) deleted`,failedDeleteArchives:`Failed to delete archives`,photoDeleted:`Photo deleted`,failedDeletePhoto:`Failed to delete photo`},list:{name:`Name`,printer:`Printer`,date:`Date`,size:`Size`,actions:`Actions`,hasTimelapse:`Has timelapse`},log:{date:`Date`,printName:`Print Name`,printer:`Printer`,user:`User`,status:`Status`,duration:`Duration`,filament:`Filament`,allPrinters:`All Printers`,allUsers:`All Users`,allStatuses:`All Statuses`,cancelled:`Cancelled`,skipped:`Skipped`,dateFrom:`From`,dateTo:`To`,noEntries:`No print log entries found`,showing:`Showing {{count}} of {{total}} entries`,rowsPerPage:`Rows`,page:`Page`,prev:`Prev`,next:`Next`,clearLog:`Clear Log`,clearLogTitle:`Clear Print Log`,clearLogConfirm:`All print log entries will be permanently deleted. Archives and queue items are not affected. This action cannot be undone. Are you sure?`,clearLogButton:`Clear All`,cleared:`{{count}} log entries cleared`,clearFailed:`Failed to clear print log`,deleteEntryTitle:`Delete print log entry`,deleteEntryConfirm:`This entry will be removed from the log and its filament, time, and cost contributions will drop out of Quick Stats. The matching archive (if any) is not affected. This action cannot be undone.`,entryDeleted:`Print log entry deleted`,entryDeleteFailed:`Failed to delete print log entry`,editEntryTitle:`Edit print log entry`,editEntryDescription:`Classify this print run. The Failure Analysis widget groups by these values, so updates flow through to stats immediately.`,entryUpdated:`Print log entry updated`,entryUpdateFailed:`Failed to update print log entry`,statuses:{completed:`Completed`,failed:`Failed`,stopped:`Stopped`,cancelled:`Cancelled`,skipped:`Skipped`}}},dispatchToast:{untitled:`Print job`,startingPrints:`Starting prints`,progressSummary:`{{complete}}/{{total}} complete • Processing: {{processing}}`,expandDetails:`Expand dispatch details`,collapseDetails:`Collapse dispatch details`,awaitingPrinter:`Awaiting printer…`,status:{processing:`Processing`,completed:`Completed`,failed:`Failed`},failed:{generic:`Dispatch failed`,upload_failed:`Upload to printer failed`,start_command_failed:`Printer rejected start command`},dismiss:`Dismiss`},pipelineRuns:{title:`Pipeline Runs`,loading:`Loading…`,empty:`No pipeline runs yet.`,filter:{pipeline:`Pipeline`,status:`Status`,target:`Target`,all:`All`,allPipelines:`All pipelines`,allStatus:`All statuses`,allTargets:`All targets`,clear:`Clear filters`,noMatches:`No runs match the current filters.`},totalCount_one:`{{n}} run`,totalCount_other:`{{n}} runs`,copies:`{{n}} copies`,failedCount:`{{n}} failed`,copyN:`Copy {{n}}`,retryFailed:`Retry failed`,retryOf:`retry of #{{n}}`,pagination:`{{start}}–{{end}} of {{total}}`,cancelledByUser:`Cancelled by user`,toast:{cancelled:`Run cancelled`,cancelFailed:`Cancel failed`,retryStarted:`Retry started`,retryFailed:`Retry failed`,cleared:`{{n}} runs cleared`,clearFailed:`Clear failed`},clearLog:`Clear log`,clearConfirmTitle:`Clear log?`,clearConfirmBody:`Delete every completed, failed, cancelled, and partial-failure pipeline run? In-flight runs are kept. This cannot be undone.`,clearConfirmAction:`Clear`,jobStatus:{pending:`pending`,awaiting_printer:`awaiting printer`,queued:`queued`,printing:`printing`,completed:`completed`,failed:`failed`,cancelled:`cancelled`}},queue:{title:`Print Queue`,subtitle:`Schedule and manage your print jobs`,filamentShort:{rowBadge:`Insufficient filament for the assigned spool`,rowTooltip:`The dispatch scheduler flagged this item. Click Play to see the per-slot deficit and decide whether to print anyway.`,confirmTitle:`Insufficient filament`,confirmIntro:`The assigned spool cannot satisfy at least one slot. Print anyway?`,lineItem:`Slot {{slot}}: needs {{required}} g, {{remaining}} g remaining`,unknown:`unknown`,printAnyway:`Print Anyway`},slicerAmsMapping:{rowBadge:`AMS slots saved for this printer`,rowTooltip:`This archive carries the exact AMS slots the slicer picked, saved for the printer this item targets. A reprint on it can reuse those trays instead of matching again by type and colour.`},editQueueItem:`Edit Queue Item`,selectAllPlates:`Select All {{count}} Plates`,deselectAll:`Deselect All`,printQueued:`Print queued`,printQueuedWillStartWhenIdle:`Will start when printer is idle`,itemsQueued:`{{count}} items queued`,sending:`Sending...`,sendingProgress:`Sending {{current}}/{{total}}...`,adding:`Adding...`,addingProgress:`Adding {{current}}/{{total}}...`,savingProgress:`Saving {{current}}/{{total}}...`,clearQueue:`Clear Queue`,clearHistory:`Clear History`,emptyQueue:`Queue is empty`,position:`Position`,scheduledTime:`Scheduled Time`,moveUp:`Move Up`,moveDown:`Move Down`,startNow:`Start Now`,printingInProgress:`Printing in progress...`,viewArchive:`View archive`,viewInFileManager:`View in File Manager`,itemCount:`{{count}} item`,itemCount_plural:`{{count}} items`,dragToReorder:`Drag to reorder (ASAP only)`,reorderHint:`Position only affects ASAP items. Scheduled items run at their set time.`,sjf:{label:`SJF`,tooltip:`Shortest Job First — scheduler prioritizes shorter prints`},addedBy:`Added by {{name}}`,nextInQueue:`Next in queue`,clearPlateSuccess:`Plate cleared — ready for next print`,plateNumber:`Plate {{index}}`,quantity:`Quantity`,quantityHint:`Creates {{count}} queue items`,activeBatches:`Active Batches`,batchProgress:`{{completed}} of {{total}} completed`,cancelBatch:`Cancel Remaining`,batchCancelled:`Remaining batch items cancelled`,cancelBatchConfirmTitle:`Cancel Batch`,cancelBatchConfirmMessage:`Cancel all remaining pending items in this batch?`,batch:{defaultName:`Batch`,label:`{{count}} item`,label_plural:`{{count}} items`,pendingCount:`{{count}} pending`,pendingCount_plural:`{{count}} pending`,expand:`Expand batch`,collapse:`Collapse batch`,groupAsBatch:`Group as batch…`,groupAsBatchDescription:`Combine the {{count}} selected items into a single collapsible batch.`,nameLabel:`Batch name`,namePlaceholder:`e.g. Friday gifts`,create:`Create batch`,ungroup:`Ungroup`,ungroupConfirmTitle:`Ungroup batch?`,ungroupConfirmMessage:`The items will stay in the queue but no longer be grouped together.`,dragGroup:`Drag group`},tabs:{queue:`Queue`,history:`History`,timeline:`Timeline`,pipelines:`Pipelines`},layout:{flatList:`List`,byPrinter:`By Printer`,groupByPrinter:`Group by Printer`},history:{emptyTitle:`No history yet`,emptyDescription:`Completed, cancelled, and failed prints will appear here.`,showMore:`Show more`,showingCount:`Showing {{shown}} of {{total}}`},dragGhost:{multiCount:`{{count}} items`,batch:`{{name}} ({{count}} copy)`,batch_plural:`{{name}} ({{count}} copies)`},sections:{currentlyPrinting:`Currently Printing`,queued:`Queued`,history:`History`},status:{pending:`Pending`,waiting:`Waiting`,printing:`Printing`,paused:`Paused`,completed:`Completed`,failed:`Failed`,skipped:`Skipped`,cancelled:`Cancelled`},summary:{printing:`Printing`,queued:`Queued`,totalTime:`Total Queue Time`,totalWeight:`Total Queue Weight`,history:`History`},filter:{allPrinters:`All Printers`,unassigned:`Unassigned`,allStatus:`All Status`,allLocations:`All Locations`,any:`Any`},sort:{byPosition:`Sort by Position`,byName:`Sort by Name`,byPrinter:`Sort by Printer`,bySchedule:`Sort by Schedule`,byDate:`Sort by Date`,ascendingOldest:`Ascending (oldest first)`,descendingNewest:`Descending (newest first)`},badges:{staged:`Staged`,requiresPrevious:`Requires previous success`,autoPowerOff:`Auto power off`,gcodeInjection:`G-code`},empty:{title:`No prints scheduled`,description:`Schedule a print from the Archives page using the "Schedule" option in the context menu, or drag and drop files to get started.`},time:{etaIfStartedNow:`Completion time if this job started now`,asap:`ASAP`,overdue:`Overdue`,now:`Now`,lessThanMinute:`In less than a minute`,inMinutes:`In {{count}} min`,inHours:`In {{count}} hours`},actions:{startPrint:`Start Print`,stopPrint:`Stop Print`,requeue:`Re-queue`},bulkEdit:{title:`Edit {{count}} Item`,title_plural:`Edit {{count}} Items`,description:`Only changed settings will be applied to selected items.`,printer:`Printer`,noChange:`— No change —`,queueOptions:`Queue Options`,staged:`Staged (manual start)`,autoPowerOff:`Auto power off after print`,requirePrevious:`Require previous success`,printOptions:`Print Options`,bedLevelling:`Bed levelling`,flowCalibration:`Flow calibration`,vibrationCalibration:`Vibration calibration`,layerInspection:`First layer inspection`,timelapse:`Timelapse`,useAms:`Use AMS`,nozzleOffsetCali:`Nozzle offset calibration`,applyChanges:`Apply Changes`,selectAll:`Select All`,deselectAll:`Deselect All`,selected:`{{count}} selected`,editSelected:`Edit Selected`,cancelSelected:`Cancel Selected`},confirm:{cancelTitle:`Cancel Scheduled Print`,cancelMessage:`Are you sure you want to cancel "{{name}}"?`,stopTitle:`Stop Print`,stopMessage:`Are you sure you want to stop the current print "{{name}}"? This will cancel the print job on the printer.`,removeTitle:`Remove from History`,removeMessage:`Are you sure you want to remove "{{name}}" from the queue history?`,clearHistoryTitle:`Clear History`,clearHistoryMessage:`Are you sure you want to remove all {{count}} item(s) from the history?`,cancelButton:`Cancel Print`,stopButton:`Stop Print`,thisPrint:`this print`,thisItem:`this item`},toast:{cancelled:`Queue item cancelled`,cancelFailed:`Failed to cancel item`,removed:`Queue item removed`,removeFailed:`Failed to remove item`,stopped:`Print stopped`,stopFailed:`Failed to stop print`,released:`Print released to queue`,startFailed:`Failed to start print`,reorderFailed:`Failed to reorder queue`,historyCleared:`Cleared {{count}} history item(s)`,clearHistoryFailed:`Failed to clear history`,updateFailed:`Failed to update items`,bulkCancelled:`Cancelled {{count}} item(s)`,bulkCancelFailed:`Failed to cancel items`,batchCreated:`Batch "{{name}}" created`,batchCreateFailed:`Failed to create batch`,batchUngrouped:`Ungrouped {{count}} item(s)`,batchUngroupFailed:`Failed to ungroup batch`,resumedAfterFailure:`Resumed queue — {{restored}} job(s) restored to pending`,resumeAfterFailureFailed:`Failed to resume queue`},resumeAfterFailure:{banner:`{{printer}} is blocked by a previous-print failure — {{count}} job(s) skipped`,bannerHint:`Fix the printer issue, then resume to restore the skipped jobs and clear the gate.`,button:`Resume after failure`,confirmTitle:`Resume queue after failure?`,confirmMessage:`Restore {{count}} skipped job(s) on {{printer}} to pending and clear the previous-print gate. Make sure the printer is ready before continuing.`},timeline:{listView:`List`,timelineView:`Timeline`,unassigned:`Unassigned`,noData:`No scheduled prints for this day`,nothingCommitted:`No committed schedules in this window. Staged items, waiting items, and ASAP jobs on idle printers are not shown — set a scheduled time or release a staged item to see it here.`,allDoneBy:`All prints estimated done by {{time}}`,staged:`Staged`,filterAll:`Show All`,filterPrinting:`Printing`,filterQueued:`Queued`,time:{anyMoment:`any moment`,minutesLeft:`{{minutes}}m left`,hoursLeft:`{{hours}}h left`,hoursMinutesLeft:`{{hours}}h {{minutes}}m left`},day:{previous:`Previous day`,next:`Next day`,today:`Today`},window:{back12h:`Back 12 hours`,forward12h:`Forward 12 hours`,now:`Now`},printerColumnHeader:`Printer`},permissions:{noStopPrint:`You do not have permission to stop prints`,noStartPrint:`You do not have permission to start prints`,noEdit:`You do not have permission to edit this queue item`,noCancel:`You do not have permission to cancel this queue item`,noRequeue:`You do not have permission to re-queue items`,noRemove:`You do not have permission to remove this queue item`,noClearHistory:`You do not have permission to clear all history`,noEditItems:`You do not have permission to edit queue items`,noCancelItems:`You do not have permission to cancel queue items`}},stats:{title:`Statistics`,subtitle:`Drag widgets to rearrange. Click the eye icon to hide.`,overview:`Overview`,totalPrints:`Total Prints`,successRate:`Success Rate`,totalPrintTime:`Total Print Time`,printTime:`Print Time`,totalFilament:`Total Filament Used`,filamentUsed:`Filament Used`,filamentCost:`Filament Cost`,totalCost:`Total Cost`,energyUsed:`Energy Used`,energyCost:`Energy Cost`,energyWarmingUpTooltip:`Energy tracking is still collecting hourly snapshots. Date-range totals will become accurate once at least one snapshot exists before the selected range. Early values may undercount.`,averagePrintTime:`Average Print Time`,printsPerDay:`Prints per Day`,byPrinter:`By Printer`,printsByPrinter:`Prints by Printer`,byMaterial:`By Material`,byMonth:`By Month`,last7Days:`Last 7 Days`,last30Days:`Last 30 Days`,last90Days:`Last 90 Days`,allTime:`All Time`,quickStats:`Quick Stats`,printActivity:`Print Activity`,filamentTypes:`Filament Types`,filamentTrends:`Filament Trends`,failureAnalysis:`Failure Analysis`,timeAccuracy:`Time Accuracy`,successful:`Successful:`,failed:`Failed:`,cancelled:`Cancelled:`,perfectEstimate:`100% = perfect estimate`,noTimeAccuracyData:`No time accuracy data yet`,noFilamentData:`No filament data available`,noPrinterData:`No printer data available`,noPrintData:`No print data available`,noPrintDataLast30Days:`No print data in the last 30 days`,failureReasons:`Failure Reasons`,topFailureReasons:`Top Failure Reasons`,failedPrintsCount:`{{failed}} / {{total}} prints failed`,lastWeekRate:`Last week: {{rate}}%`,resetLayout:`Reset Layout`,recalculateCosts:`Recalculate Costs`,recalculateCostsHint:`Recalculate all archive costs using current filament prices`,exportStats:`Export Stats`,exportAsCsv:`Export as CSV`,exportAsExcel:`Export as Excel`,hiddenCount:`{{count}} Hidden`,exportDownloaded:`Export downloaded`,exportFailed:`Export failed`,layoutReset:`Layout reset`,recalculatedCosts:`Recalculated costs for {{count}} archives`,recalculateFailed:`Failed to recalculate costs`,loadingStats:`Loading statistics...`,noPermissionResetLayout:`You do not have permission to reset layout`,noPermissionRecalculate:`You do not have permission to recalculate costs`,noPrintDataInRange:`No print data in selected range`,periodFilament:`Period Filament`,periodCost:`Period Cost`,avgPerPrint:`Avg per Print`,usageOverTime:`Usage Over Time`,energyOverTime:`Energy Over Time`,filamentByWeight:`Weight`,printDuration:`Print Duration`,printerUtilization:`Printer Utilization`,filamentSuccess:`Success by Material`,printHabits:`Print Habits`,printTimeOfDay:`Print Time of Day`,colorDistribution:`Color Distribution`,noColorData:`No color data available`,records:`Records`,longestPrint:`Longest Print`,heaviestPrint:`Heaviest Print`,mostExpensivePrint:`Most Expensive`,busiestDay:`Busiest Day`,successStreak:`Success Streak`,streakPrint:`consecutive print`,streakPrints:`{{count}} consecutive prints`,printerStats:`Printer Stats`,hours:`hours`,avgPrints:`Avg. prints`,noArchiveData:`No print data available`,filamentByTime:`Time`,avgWeight:`Avg. weight`,avgTime:`Avg. time`,filamentByPrints:`Prints`,timeframe:{today:`Today`,"this-week":`This Week`,"this-month":`This Month`,"last-7":`Last 7 Days`,"last-30":`Last 30 Days`,"last-90":`Last 90 Days`,"this-year":`This Year`,"all-time":`All Time`,custom:`Custom Range`,from:`From`,to:`To`},allUsers:`All Users`,noUser:`No User (System)`,filterByUser:`Filter by User`},maintenance:{title:`Maintenance`,overview:`Overview`,allOk:`All maintenance up to date`,dueCount:`{{count}} item due`,dueCount_plural:`{{count}} items due`,warningCount:`{{count}} warning`,warningCount_plural:`{{count}} warnings`,totalPrintTime:`Total Print Time`,nextMaintenance:`Next Maintenance`,nothingDue:`Nothing due`,tasks:`Tasks`,lastPerformed:`Last performed`,interval:`Interval`,hoursRemaining:`{{hours}}h remaining`,hoursOverdue:`{{hours}}h overdue`,markDone:`Mark as Done`,performMaintenance:`Perform Maintenance`,history:`History`,noHistory:`No maintenance history`,editPrintHours:`Edit Print Hours`,currentHours:`Current Hours`,statusTab:`Status`,settingsTab:`Settings`,overdueCount:`{{count}} overdue`,dueSoonCount:`{{count}} due soon`,dueSoon:`Due soon`,allGood:`All good`,overdueBy:`Overdue by {{duration}}`,dueIn:`Due in {{duration}}`,timeLeft:`{{duration}} left`,day:`1 day`,days:`{{count}} days`,week:`1 week`,weeks:`{{count}} weeks`,month:`1 month`,months:`{{count}} months`,year:`1 year`,maintenanceTypes:`Maintenance Types`,maintenanceTypesDescription:`System types and your custom maintenance tasks`,addCustomType:`Add Custom Type`,restoreDefaults:`Restore Default Tasks`,intervalType:`Interval Type`,intervalValue:`Interval ({{type}})`,icon:`Icon`,documentationLink:`Documentation Link (optional)`,assignToPrinters:`Assign to Printers`,selectAtLeastOnePrinter:`Select at least one printer`,addType:`Add Type`,custom:`Custom`,printHours:`Print Hours`,calendarDays:`Calendar Days`,exampleName:`e.g., Replace HEPA Filter`,viewDocumentation:`View documentation`,timeBasedInterval:`Time-based interval`,intervalOverrides:`Interval Overrides`,intervalOverridesDescription:`Customize intervals for specific printers`,assignedToPrinters:`Assigned to printers:`,noPrintersAssigned:`No printers assigned`,addPrinterShort:`Add:`,printersAssignedClick:`{{count}} printer(s) assigned - click to manage`,removeFromPrinter:`Remove from this printer`,types:{lubricateCarbonRods:`Lubricate Carbon Rods`,lubricateRails:`Lubricate Linear Rails`,cleanNozzle:`Clean Nozzle/Hotend`,checkBelts:`Check Belt Tension`,cleanBuildPlate:`Clean Build Plate`,checkExtruder:`Check Extruder Gears`,checkCooling:`Check Cooling Fans`,generalInspection:`General Inspection`,cleanCarbonRods:`Clean Carbon Rods`,lubricateSteelRods:`Lubricate Steel Rods`,cleanSteelRods:`Clean Steel Rods`,cleanLinearRails:`Clean Linear Rails`,checkPtfeTube:`Check PTFE Tube`,replaceHepaFilter:`Replace HEPA Filter`,replaceCarbonFilter:`Replace Carbon Filter`,lubricateLeftNozzleRail:`Lubricate Left Nozzle Rail`},maintenanceComplete:`Maintenance marked as complete`,typeUpdated:`Maintenance type updated`,typeDeleted:`Maintenance type deleted`,defaultsRestored:`Restored {{count}} default task(s)`,printHoursUpdated:`Print hours updated`,printerAssigned:`Printer assigned`,printerRemoved:`Printer removed`,deleteTypeConfirm:`Delete "{{name}}"?`,deleteSystemTypeTitle:`Delete default maintenance task?`,deleteSystemTypeMessage:`Are you sure you want to delete the default maintenance task "{{name}}"?`,noPermissionUpdate:`You do not have permission to update maintenance items`,noPermissionPerform:`You do not have permission to perform maintenance`,noPermissionEditTypes:`You do not have permission to edit maintenance types`,noPermissionDeleteTypes:`You do not have permission to delete maintenance types`,noPermissionEditHours:`You do not have permission to edit print hours`,noPermissionRemovePrinter:`You do not have permission to remove printer assignments`,noPermissionAssignPrinter:`You do not have permission to assign printers`,noPermissionEditIntervals:`You do not have permission to edit intervals`,configureSettings:`Configure maintenance types and intervals`},settings:{title:`Settings`,general:`General`,tabs:{general:`General`,smartPlugs:`Smart Plugs`,notifications:`Notifications`,queue:`Workflow`,queueDispatch:`Queue & Dispatch`,queuePipelines:`Pipelines`,filament:`Filament`,network:`Network`,apiKeys:`API Keys`,virtualPrinter:`Virtual Printer`,spoolbuddy:`SpoolBuddy`,failureDetection:`Failure Detection`,users:`Authentication`,backup:`Backup`,emailAuth:`Email Authentication`,ldap:`LDAP`,twoFa:`Two-Factor Auth`,oidc:`SSO / OIDC`,security:`Security`},spoolbuddy:{infoTitle:`SpoolBuddy devices`,infoBody:`SpoolBuddy kiosks register themselves automatically via heartbeat. Unregister a device here if it is no longer in use or if a stale duplicate was left behind by a daemon crash.`,duplicatesTitle:`{{count}} devices registered`,duplicatesBody:`Only the first registered device is used by the kiosk UI. If one of these is a stale duplicate from a crash, unregister it — an online device will re-register itself on its next heartbeat.`,empty:`No SpoolBuddy devices registered yet.`,online:`Online`,offline:`Offline`,unregister:`Unregister`,unregisterSuccess:`Device unregistered`,unregisterError:`Failed to unregister device`,confirmTitle:`Unregister SpoolBuddy device?`,confirmBody:`This will remove "{{hostname}}" ({{deviceId}}) from the database. If the device is online, it will re-register itself on its next heartbeat.`,ipAddress:`IP address`,firmware:`Firmware`,lastSeen:`Last seen`,daemonUptime:`Daemon uptime`,systemUptime:`System uptime`,never:`never`,nfc:`NFC`,scale:`Scale`,cpuTemp:`CPU temp`,cpuLoad:`CPU load`,memory:`Memory`,disk:`Disk`,update:`Update`,updateConfirmTitle:`Update Spoolbuddy daemon?`,updateConfirmBody:`Trigger a software update on "{{hostname}}"? The daemon will restart once the update is applied.`,restartBrowser:`Restart Browser`,restartBrowserConfirmTitle:`Restart kiosk browser?`,restartBrowserConfirmBody:`Restart the kiosk browser on "{{hostname}}"? The display will blank briefly.`,restartDaemon:`Restart Daemon`,restartDaemonConfirmTitle:`Restart Spoolbuddy daemon?`,restartDaemonConfirmBody:`Restart the Spoolbuddy daemon on "{{hostname}}"? The device will go offline for a few seconds.`,reboot:`Reboot`,rebootConfirmTitle:`Reboot device?`,rebootConfirmBody:`Reboot "{{hostname}}"? The device will be offline for around a minute.`,shutdown:`Shutdown`,shutdownConfirmTitle:`Shutdown device?`,shutdownConfirmBody:`Shutdown "{{hostname}}"? You will need physical access to power it back on.`,commandConfirm:`Confirm`,commandQueued:`Command queued`,commandError:`Failed to send command`},ldap:{title:`LDAP Authentication`,enabledDesc:`LDAP authentication is enabled`,disabledDesc:`LDAP authentication is disabled`,disabledHint:`Configure and save LDAP settings below, then enable.`,enabled:`LDAP authentication enabled`,disabled:`LDAP authentication disabled`,feature1:`Users can login with LDAP credentials`,feature2:`Local admin account remains as fallback`,feature3:`LDAP groups are mapped to BamBuddy groups on login`,serverConfig:`LDAP Server Configuration`,serverUrl:`Server URL`,serverUrlHint:`Use ldaps:// for SSL or ldap:// with StartTLS`,security:`Security`,securityHint:`StartTLS upgrades a plain connection to TLS. LDAPS uses TLS from the start.`,bindDn:`Bind DN (Service Account)`,bindPassword:`Bind Password`,searchBase:`Search Base DN`,userFilter:`User Search Filter`,userFilterHint:`{username} is replaced with the login username. Use (uid={username}) for OpenLDAP.`,advanced:`Advanced`,autoProvision:`Auto-provision users`,autoProvisionHint:`Automatically create a BamBuddy account on first LDAP login`,defaultGroup:`Default group`,defaultGroupNone:`— None (no fallback) —`,defaultGroupHint:`Fallback group assigned when an LDAP user authenticates but is not listed in any mapped LDAP group. Leave empty to leave unmapped users without permissions.`,groupMapping:`Group Mapping (JSON)`,groupMappingHint:`Map LDAP group DNs to BamBuddy groups. Available groups: `,testConnection:`Test Connection`,settingsSaved:`LDAP settings saved`,errors:{serverRequired:`LDAP server URL is required`,searchBaseRequired:`Search base DN is required`,enableAuthFirst:`Enable authentication first`,configureLdapFirst:`Save LDAP settings first`}},email:{smtpSettings:`SMTP Configuration`,smtpHost:`SMTP Server`,smtpPort:`SMTP Port`,security:`Security`,authentication:`Authentication`,username:`Username`,password:`Password`,fromEmail:`From Email`,fromName:`From Name`,testConnection:`Test SMTP Connection`,testRecipient:`Test Recipient Email`,sendTest:`Send Test Email`,sending:`Sending...`,save:`Save Settings`,saving:`Saving...`,advancedAuth:`Advanced Authentication`,advancedAuthEnabled:`Advanced Authentication is enabled`,advancedAuthEnabledDesc:`Email-based user management features are active. New users will receive auto-generated passwords via email, and users can reset their passwords through the forgot password feature.`,advancedAuthDisabled:`Advanced Authentication is disabled`,advancedAuthDisabledDesc:`Enable advanced authentication to activate email-based features for user management.`,enable:`Enable`,disable:`Disable`,feature1:`Passwords are auto-generated and emailed to new users`,feature2:`Users can login with username or email`,feature3:`Forgot password feature is available`,feature4:`Admins can reset user passwords via email`,errors:{requiredFields:`Please fill in all required fields`,usernameRequired:`Username is required when authentication is enabled`,enterTestEmail:`Please enter a test email address`,smtpServerAndEmail:`Please fill in SMTP Server and From Email before testing`,usernamePasswordRequired:`Username and Password are required when authentication is enabled`,configureSmtpFirst:`Please configure and test SMTP settings first`,enableAuthFirst:`Please enable authentication first to use email-based features.`},success:{settingsSaved:`SMTP settings saved successfully`},securityOptions:{starttls:`STARTTLS (Port 587)`,ssl:`SSL/TLS (Port 465)`,none:`None (Port 25)`},authOptions:{enabled:`Enabled`,disabled:`Disabled`}},appearance:`Appearance`,notifications:`Notifications`,smartPlugs:`Smart Plugs`,spoolman:`Spoolman`,updates:`Updates`,language:`Language`,languageDescription:`Select your preferred language`,theme:`Theme`,themeLight:`Light`,themeDark:`Dark`,themeSystem:`System`,defaultView:`Default View`,defaultViewDescription:`Page to show when opening the app`,checkForUpdates:`Check for Updates`,autoUpdate:`Auto Update`,currentVersion:`Current Version`,latestVersion:`Latest Version`,upToDate:`You are up to date`,updateAvailable:`Update available`,notificationLanguage:`Notification Language`,notificationLanguageDescription:`Language for push notifications`,bedCooledThreshold:`Bed Cooled Threshold`,bedCooledThresholdDescription:`Temperature below which the bed is considered cooled after a print`,userNotificationsEnabled:`User Notifications`,userNotificationsEnabledDescription:`Enable the user notifications menu and email notifications for print job events. Requires Advanced Authentication.`,userNotificationsDisabledHint:`Enable Advanced Authentication to use user notifications.`,notificationProviders:`Notification Providers`,addProvider:`Add Provider`,editProvider:`Edit Provider`,providerType:`Provider Type`,testNotification:`Test Notification`,testSuccess:`Test notification sent successfully`,testFailed:`Failed to send test notification`,quietHours:`Quiet Hours`,quietHoursDescription:`Do not disturb during these hours`,quietHoursStart:`Start`,quietHoursEnd:`End`,events:{title:`Notification Events`,printStart:`Print Started`,printComplete:`Print Completed`,printFailed:`Print Failed`,printStopped:`Print Stopped`,printProgress:`Progress Milestones`,printProgressDescription:`Notify at 25%, 50%, 75%`,printerOffline:`Printer Offline`,printerError:`Printer Error`,filamentLow:`Low Filament`,maintenanceDue:`Maintenance Due`,maintenanceDueDescription:`Notify when maintenance is needed`},smartPlug:{title:`Smart Plugs`,add:`Add Smart Plug`,edit:`Edit Smart Plug`,name:`Name`,ipAddress:`IP Address`,linkedPrinter:`Linked Printer`,autoOn:`Auto Power On`,autoOnDescription:`Turn on when print starts`,autoOff:`Auto Power Off`,autoOffDescription:`Turn off after print completes`,offDelay:`Off Delay`,offDelayMinutes:`Minutes after print`,offDelayTemp:`When nozzle below temperature`,currentState:`Current State`,turnOn:`Turn On`,turnOff:`Turn Off`},filamentTracking:`Filament Tracking`,filamentTrackingDesc:`Choose how to track your filament spools. You can use the built-in inventory or connect an external Spoolman server.`,autoAddUnknownRfid:`Auto-add unknown RFID spools`,autoAddUnknownRfidDesc:`Automatically create an inventory entry when a spool with an unknown RFID tag is detected. Turn off if you pre-register new spools manually to avoid duplicates.`,filamentChecks:`Filament checks`,disableFilamentWarnings:`Disable filament warnings`,disableFilamentWarningsDesc:`Don't show warnings about insufficient filament when printing or queueing`,preferLowestFilament:`Prefer lowest remaining filament`,preferLowestFilamentDesc:`When multiple spools match, use the one with the least filament remaining`,preferLowestFilamentBackupNote:`Only takes effect when AMS Filament Backup is enabled on the printer — otherwise the printer cannot switch to a second spool when the picked one runs out.`,trackingModeBuiltIn:`Built-in Inventory`,trackingModeBuiltInDesc:`RFID auto-matching and usage tracking included`,trackingModeSpoolmanDesc:`External filament management server`,builtInFeatureRfid:`Automatically detects Bambu Lab RFID spools in AMS`,builtInFeatureUsage:`Tracks filament consumption per print`,builtInFeatureCatalog:`Manage spools, colors, and K-factor profiles`,builtInFeatureThirdParty:`Third-party spools can be assigned to inventory spools`,amsSyncButton:`Sync Weights from AMS`,amsSyncTitle:`Sync Spool Weights from AMS`,amsSyncMessage:`This will overwrite all inventory spool weights with the current AMS remain% values from connected printers. Use this to recover from corrupted weight data. Printers must be online.`,amsSyncing:`Syncing...`,amsSyncSuccess:`{{synced}} spool(s) synced, {{skipped}} skipped`,amsSyncError:`Failed to sync weights from AMS`,spoolmanAmsSyncButton:`Sync Spoolman Weights from AMS`,spoolmanAmsSyncTitle:`Sync Spoolman Spool Weights from AMS`,spoolmanAmsSyncMessage:`This will update all Spoolman spool weights based on the current AMS remain% values from connected printers. Printers must be online.`,spoolmanAmsSyncing:`Syncing...`,spoolmanAmsSyncSuccess:`{{synced}} spool(s) synced, {{skipped}} skipped`,spoolmanAmsSyncError:`Failed to sync Spoolman weights from AMS`,spoolmanAmsSyncErrorUnreachable:`Failed to sync Spoolman weights (Spoolman unreachable)`,spoolmanAmsSyncErrorNotConfigured:`Failed to sync Spoolman weights (Spoolman not configured)`,spoolmanNotConfigured:`Spoolman not configured`,spoolmanFilamentCatalogTitle:`Spoolman Filament Catalog`,spoolmanFilamentCatalogDesc:`Filament names and tare weights from your Spoolman instance. Name and spool weight are editable here; all other properties are managed directly in Spoolman.`,spoolmanUrl:`Spoolman URL`,spoolmanUrlHint:`URL of your Spoolman server (e.g., http://localhost:7912)`,spoolmanConnected:`Connected`,spoolmanDisconnected:`Disconnected`,status:`Status`,connect:`Connect`,disconnect:`Disconnect`,howSyncWorks:`How Sync Works`,syncInfoRfidOnly:`Only official Bambu Lab spools with RFID are synced`,syncInfoAutoCreate:`New spools are auto-created in Spoolman on first sync`,syncInfoThirdPartySkipped:`Non-Bambu Lab spools (third-party, refilled) are skipped`,linkingExistingSpools:`Linking Existing Spools`,linkingExistingSpoolsDesc:`To link existing Spoolman spools to your AMS, hover over an AMS slot and click "Link to Spoolman".`,syncMode:`Sync Mode`,syncModeAuto:`Automatic`,syncModeManual:`Manual Only`,syncModeAutoDesc:`AMS data syncs automatically when changes are detected`,syncModeManualDesc:`Only sync when manually triggered`,syncAmsData:`Sync AMS Data`,syncAmsDataDesc:`Manually sync printer AMS data to Spoolman`,allPrinters:`All Printers`,noDefaultPrinter:`No default (ask each time)`,sidebarOrder:`Sidebar order`,saveThumbnails:`Save thumbnails`,captureFinishPhoto:`Capture finish photo`,noPrintersConfigured:`No printers configured`,archiveMode:{always:`Always create archive entry`,never:`Never create archive entry`,ask:`Ask each time`},checkForUpdatesLabel:`Check for updates`,checkPrinterFirmware:`Check printer firmware`,includeBetaUpdates:`Include beta versions`,includeBetaUpdatesDesc:`Notify about beta and prerelease versions when checking for updates`,localLogin:{disable:`Disable local username/password login`,disableHint:`When enabled, only SSO providers can sign in. LDAP is unaffected. Set BAMBUDDY_LOCAL_LOGIN=true on the server to keep a recovery path.`},enableRetry:`Enable retry`,homeAssistantDescription:`Control smart plugs via Home Assistant`,environmentManagedLabel:`(Environment Managed)`,autoEnabledViaEnv:`Automatically enabled via environment variables`,urlFromEnvReadOnly:`Value set by HA_URL environment variable (read-only)`,tokenFromEnvReadOnly:`Value set by HA_TOKEN environment variable (read-only)`,mqttConnectedTo:`Connected to`,prometheusDescription:`Expose printer data in Prometheus format`,noSmartPlugsTitle:`No smart plugs configured`,noSmartPlugsDescription:`Add a Tasmota-based smart plug to track energy usage and automate power control.`,noProvidersTitle:`No providers configured`,noProvidersDescription:`Add a provider to receive alerts.`,noTemplatesAvailable:`No templates available. Restart the backend to seed default templates.`,apiPermissionView:`View printer status and queue`,apiPermissionEdit:`Add and remove items from print queue`,apiKeysEmptyTitle:`No API keys`,apiKeysEmptyDescription:`Create an API key to integrate with external services.`,noUsersFound:`No users found`,noGroupsFound:`No groups found`,noGroupsAvailable:`No groups available`,passwordsDoNotMatch:`Passwords do not match`,systemGroupWarning:`System group names cannot be changed`,authDisabledTitle:`Authentication is Disabled`,authDisabledFeature1:`Require login to access the system`,authDisabledFeature2:`Create multiple users with group-based permissions`,authDisabledFeature3:`Control access with 50+ granular permissions`,userHasCreated:`This user has created:`,userItemsQuestion:`What would you like to do with these items?`,deleteUserConfirm:`Are you sure you want to delete this user?`,actionCannotBeUndone:`This action cannot be undone.`,addFirstSmartPlug:`Add Your First Smart Plug`,providers:`Providers`,log:`Log`,testAll:`Test All`,testResults:`Test Results`,testPassedCount:`{{count}} passed`,testFailedCount:`{{count}} failed`,messageTemplates:`Message Templates`,messageTemplatesDescription:`Customize notification messages for each event.`,apiKeys:`API Keys`,apiKeysDescription:`Create API keys for external integrations and webhooks.`,createKey:`Create Key`,apiKeyCreated:`API Key Created Successfully`,apiKeyCopyWarning:`Copy this key now - it won't be shown again!`,useInApiBrowser:`Use in API Browser`,apiKeyQrButton:`QR code`,apiKeyQrTitle:`Scan to configure`,apiKeyQrCaption:`Scan with your mobile app to add this server and API key.`,apiKeyQrWarning:`Contains your secret API key — don't share or screenshot it where others can see.`,createNewApiKey:`Create New API Key`,keyName:`Key Name`,keyNamePlaceholder:`e.g., Home Assistant, OctoPrint`,readStatus:`Read Status`,readStatusDescription:`View printer status and queue`,manageQueue:`Manage Queue`,manageQueueDescription:`Add and remove items from print queue`,controlPrinter:`Control Printer`,controlPrinterDescription:`Pause, resume, and stop prints`,manageLibrary:`Manage Library`,manageLibraryDescription:`Upload, rename, and delete library files; import models from MakerWorld`,manageInventory:`Manage Inventory`,manageInventoryDescription:`Create, update, and delete spools and inventory records. Required for SpoolBuddy kiosks (NFC scan, scale readings, kiosk system commands).`,manageMaintenance:`Manage Maintenance`,manageMaintenanceDescription:`Log completed maintenance, reset counters, edit intervals, and manage the maintenance-type catalog. Suited to Home Assistant automations that record "I cleaned the nozzle" without granting broader printer control.`,manageArchives:`Manage Archives`,manageArchivesDescription:`Edit and delete print archives, including removing old prints. Does not include purging their statistics contribution. Suited to automations that prune the print history.`,manageProjects:`Manage Projects`,manageProjectsDescription:`Create, update, and delete projects, and add archives to them. Suited to automations that organize prints into projects.`,libraryBadge:`Library`,inventoryBadge:`Inventory`,maintenanceBadge:`Maintenance`,archivesBadge:`Archives`,projectsBadge:`Projects`,cloudAccess:`Allow cloud access`,cloudAccessDescription:`Read Bambu Cloud presets and filaments on your behalf. Requires you to be signed into Bambu Cloud.`,cloudBadge:`Cloud`,updateEnergyCost:`Update electricity price`,updateEnergyCostDescription:`Allow this key to POST a new per-kWh electricity price to /settings/electricity-price. Useful for Home Assistant dynamic-tariff automations (Tibber, Octopus, etc.). This is the only settings field writable via API key.`,energyCostBadge:`Energy`,legacyKey:`Legacy`,legacyKeyTooltip:`Created before per-user ownership; recreate to use cloud access`,unnamedKey:`Unnamed Key`,lastUsed:`Last used`,read:`Read`,control:`Control`,createFirstKey:`Create Your First Key`,webhookEndpoints:`Webhook Endpoints`,webhookApiKeyHint:`Use your API key in the X-API-Key header.`,webhook:{getAllStatus:`Get all printer status`,getSpecificStatus:`Get specific printer status`,addToQueue:`Add to print queue`,pausePrint:`Pause print`,resumePrint:`Resume print`,stopPrint:`Stop print`},apiBrowser:`API Browser`,apiBrowserDescription:`Explore and test all available API endpoints.`,apiKeyForTesting:`API Key for Testing`,apiKeyPlaceholder:`Paste your API key here to test authenticated endpoints...`,apiKeyHint:`This key will be sent as X-API-Key header with requests.`,deleteApiKeyTitle:`Delete API Key`,deleteApiKeyMessage:`Are you sure you want to delete this API key? Any integrations using this key will stop working.`,deleteKey:`Delete Key`,amsDisplayThresholds:`AMS Display Thresholds`,amsThresholdsDescription:`Configure color thresholds for AMS humidity and temperature indicators.`,humidity:`Humidity`,goodGreen:`Good (green)`,fairOrange:`Fair (orange)`,aboveFairBad:`Above fair threshold shows as red (bad)`,fairAlsoDryingThreshold:`This threshold is also used to trigger auto-drying when enabled`,temperature:`Temperature`,goodBlue:`Good (blue)`,aboveFairHot:`Above fair threshold shows as red (hot)`,historyRetention:`History Retention`,keepSensorHistory:`Keep sensor history for`,historyRetentionDescription:`Older humidity and temperature data will be automatically deleted`,defaultPrintOptions:`Default Print Options`,defaultPrintOptionsDescription:`Set default values for print options when starting new prints. These can be overridden per print in the print dialog.`,defaultBedLevelling:`Bed Levelling`,defaultBedLevellingDesc:`Auto-level bed before print`,defaultFlowCali:`Flow Calibration`,defaultFlowCaliDesc:`Calibrate extrusion flow`,defaultVibrationCali:`Vibration Calibration`,defaultVibrationCaliDesc:`Reduce ringing artifacts`,defaultLayerInspect:`First Layer Inspection`,defaultLayerInspectDesc:`AI inspection of first layer`,defaultTimelapse:`Timelapse`,defaultTimelapseDesc:`Record timelapse video`,defaultNozzleOffsetCali:`Nozzle Offset Calibration`,defaultNozzleOffsetCaliDesc:`Calibrate nozzle offsets between extruders`,tempFanPresetsTitle:`Temperature & Fan Presets`,tempFanPresetsDescription:`Customize the quick-select values shown in printer-card temperature and fan-speed popovers. The Off button is always shown.`,tempFanPresetsNozzle:`Nozzle temperature`,tempFanPresetsBed:`Bed temperature`,tempFanPresetsChamber:`Chamber temperature`,tempFanPresetsFan:`Fan speed`,tempFanPresetsReset:`Reset to defaults`,concurrentUploadsTitle:`Concurrent Uploads`,concurrentUploadsDescription:`How many printers the queue may send files to at the same time. Printers receive files slowly (a large print can take several minutes), and each one waits its turn — so on a bigger fleet, raising this is what stops the last printer in a batch from waiting out every transfer before it. Lower it if your network or Bambuddy host struggles with parallel transfers.`,concurrentUploadsLabel:`Printers uploaded to at once`,concurrentUploadsHelp:`1 sends to one printer at a time (the old behaviour). Default is 4.`,staggeredStart:`Staggered Start`,staggeredStartDescription:`Default group size and interval when staggering multi-printer batch starts. Can be overridden per batch in the print modal.`,preheatTitle:`Preheat & Heat Soak`,preheatDescription:`Heat the bed (and chamber, if supported) and hold at temperature before each queued print starts. Helpful for engineering filaments (PA, ABS) on printers without an active chamber heater — the bed warms the chamber by radiation while the soak timer runs. The bed target is read from the print file; chamber behaviour depends on printer model.`,preheatEnabled:`Enable preheat & soak`,preheatEnabledDesc:`When off, queued prints dispatch immediately. Each queue item can override per print.`,preheatFilamentTargetsLabel:`Per-filament chamber target (°C)`,preheatFilamentTargetsHint:`Bambuddy picks the highest target across the loaded AMS slots; PLA-only prints derive 0 and skip the chamber phase automatically.`,preheatFilamentTargetsReset:`Reset to defaults`,preheatFilamentTargetsDefaultRow:`Other / unmapped`,preheatMaxWait:`Max wait (seconds)`,preheatMaxWaitHelp:`Cap on the chamber warm-up phase before falling through.`,preheatSoak:`Soak (seconds)`,preheatSoakHelp:`Hold time after target reached or max-wait elapsed.`,preheatHardwareTitle:`Per-printer behaviour:`,preheatHardwareDetail:`H2C/H2D/H2D Pro/H2S/X2D/X1E actively heat the chamber via M141. X1C/P2S read chamber temp but rely on bed-radiation heating. P1S/P1P/A1/A1 Mini have no chamber sensor — only the soak timer applies.`,preheatPerItemDesc:`Heat the bed and chamber before this print starts. Defaults to the global Settings → Workflow toggle.`,preheatOverride_inherit:`Inherit`,preheatOverride_on:`On`,preheatOverride_off:`Off`,calibrationMode_off:`Off`,calibrationMode_on:`On`,calibrationMode_auto:`Auto`,preheatTargetOverride:`Chamber target override (°C, blank = filament default)`,plateClear:`Plate-Clear Confirmation`,requirePlateClear:`Require plate-clear confirmation`,requirePlateClearDescription:`When enabled, the scheduler waits for per-printer plate-clear confirmation before starting queued prints on printers with finished jobs. Disabling this also hides the plate status badge and the "Mark plate as cleared" button on printer cards.`,gcodeInjection:`G-code Injection`,gcodeInjectionDescription:`Configure custom G-code to inject at the start and/or end of prints for auto-print systems like Farmloop, SwapMod, AutoClear, and Printflow 3D. Snippets are configured per printer model and applied when "Inject G-code" is enabled on a queue item.`,gcodeInjectionNoPrinters:`No printers found. Add printers to configure G-code snippets.`,gcodeStartLabel:`Start G-code`,gcodeEndLabel:`End G-code`,gcodeStartPlaceholder:`G-code prepended before the print starts...`,gcodeEndPlaceholder:`G-code appended after the print ends...`,staggerGroupSize:`Group size`,staggerGroupSizeHelp:`Printers to start simultaneously per group`,staggerInterval:`Interval (minutes)`,staggerIntervalHelp:`Delay between each group starting`,queueDrying:`Queue Auto-Drying`,queueDryingDescription:`Automatically dry AMS filament when printer is idle between queued prints. Uses humidity threshold above to trigger drying.`,queueDryingEnabled:`Enable auto-drying`,queueDryingEnabledDescription:`Start AMS drying automatically when printer is idle and humidity is above threshold`,queueDryingBlock:`Wait for drying to complete`,queueDryingBlockDescription:`Block the print queue until drying finishes. When off, prints take priority over drying.`,ambientDryingEnabled:`Ambient drying`,ambientDryingEnabledDescription:`Automatically dry filament on idle printers when humidity exceeds threshold, even without queued prints.`,printDryingEnabled:`Continue drying while printing`,printDryingEnabledDescription:`Allow auto-drying to keep running during a print on supported hardware (H2D, H2C, H2S, P2S, H2D Pro, X2D, X1C, A2L on recent firmware). Drying temperature is automatically capped 5°C below the idle preset to protect spools.`,dryingPresets:`Drying Presets`,dryingPresetsDescription:`Temperature and duration per filament type. AMS 2 Pro uses lower temps, AMS-HT supports higher temps.`,dryingFilament:`Filament`,humidityThresholds:`Humidity Thresholds`,humidityThresholdsDescription:`Per-filament humidity trigger for auto-drying and alarms. Mixed loads in one AMS use the lowest threshold.`,humidityThresholdCol:`Threshold`,humidityThresholdDefault:`Default (unknown types)`,printModal:`Print Modal`,expandCustomMapping:`Expand custom mapping by default`,expandCustomMappingDescription:`When printing to multiple printers, show per-printer AMS mapping expanded`,authentication:`Authentication`,authEnabledDescription:`Your instance is secured with user authentication`,authDisabledDescription:`Enable to require login and manage user access`,authDisabledMessage:`Enable authentication to create user accounts, manage permissions, and secure your Bambuddy instance.`,enableAuthentication:`Enable Authentication`,currentUser:`Current User`,changePassword:`Change Password`,admin:`Admin`,users:`Users`,addUser:`Add User`,groups:`Groups`,addGroup:`Add Group`,system:`System`,noDescription:`No description`,userCount:`{{count}} users`,permissionCount:`{{count}} permissions`,createUser:`Create User`,username:`Username`,enterUsername:`Enter username`,password:`Password`,enterPassword:`Enter password`,passwordRequirements:`At least 8 characters, with one uppercase, one lowercase, one digit, and one special character.`,confirmPassword:`Confirm Password`,confirmPasswordPlaceholder:`Confirm password`,viewReleaseOnGitHub:`View release on GitHub`,turnAllPlugsOn:`Turn all plugs on`,turnAllPlugsOff:`Turn all plugs off`,clearNotificationLogs:`Clear Notification Logs`,clearLogsMessage:`This will permanently delete all notification logs older than 30 days. This action cannot be undone.`,clearLogs:`Clear Logs`,resetUiPreferences:`Reset UI Preferences`,resetUiPreferencesMessage:`This will reset all UI preferences to defaults: sidebar order, theme, dashboard layout, view modes, and sorting preferences. Your printers, archives, and server settings will NOT be affected. The page will reload after clearing.`,resetPreferences:`Reset Preferences`,deleteGroupTitle:`Delete Group`,deleteGroupMessage:`Are you sure you want to delete this group? Users in this group will lose these permissions.`,deleteGroup:`Delete Group`,disableAuthenticationTitle:`Disable Authentication`,disableAuthenticationMessage:`Are you sure you want to disable authentication? This will make your Bambuddy instance accessible without login. All users will remain in the database but authentication will be disabled.`,disableAuthentication:`Disable Authentication`,configureBambuddy:`Configure Bambuddy`,systemDefault:`System Default`,archiveSettings:`Archive Settings`,newWindow:`New Window`,embeddedOverlay:`Embedded Overlay`,preferredSlicer:`Preferred Slicer`,preferredSlicerDescription:`Slicer used for in-app slicing via the API sidecar`,openInSlicerLabel:`Open in Slicer`,openInSlicerInherit:`Same as API slicer`,openInSlicerDescription:`Desktop slicer used by the 'Open in Slicer' button. Leave on 'Same as API slicer' to inherit, or pick a different slicer to use locally.`,orcaslicerKnownIssuesWarning:`OrcaSlicer 2.3.2 / 2.4.0-dev have known CLI bugs that block slicing many Bambu-authored 3MFs — see upstream issues #12426 (segfault on painted multi-extruder files) and #13386 (parameter-range strict-validation reject). Bambu Studio is recommended until the upstream fixes land.`,useSlicerApi:`Use Slicer API`,useSlicerApiDescription:`When on, "Slice" actions open the in-app slicer modal and call the slicer-API sidecar. When off (default), they hand off to the desktop slicer via URI scheme.`,slicerCard:`Slicer`,orcaslicerApiUrl:`OrcaSlicer sidecar URL`,bambuStudioApiUrl:`Bambu Studio sidecar URL`,slicerStallTimeout:`Slicer stall timeout (minutes)`,slicerStallTimeoutDescription:`Give up on a slice after this long with no progress from the sidecar. Heavy models that keep reporting progress are never cut off, however long they take. Sidecars that do not report progress use this as a total time limit instead.`,slicerApiUrlDescription:`URL of the slicer-API sidecar container. Leave blank to use the SLICER_API_URL / BAMBU_STUDIO_API_URL env var defaults.`,slicerBundlesRemoved:{title:`Slicer Bundles (removed)`,description:`Printer Preset Bundle (.bbscfg) import was removed. BambuStudio's bundle export only includes user-customised presets, so the import never delivered standard processes / filaments and slicing fell back to embedded settings.`,alternatives:`Use Single Preset Import for individual customs, or sync via Bambu Cloud / Orca Cloud. Stock presets come from the slicer sidecar automatically.`,lookupOrder:`Slice-time preset lookup order: 1) Imported (local), 2) Orca Cloud, 3) Bambu Cloud, 4) Standard (sidecar fallback).`},externalCameras:`External Cameras`,costTracking:`Cost Tracking`,printsOnly:`Prints Only`,totalConsumption:`Total Consumption`,dataManagement:`Data Management`,storageUsage:`Storage Usage`,storageUsageDescription:`Breakdown of data usage by category`,storageUsageTotal:`Total`,storageUsageErrors:`Errors`,storageUsageOtherBreakdown:`Other (includes static assets, scripts, and configuration files)`,storageUsageSystem:`System`,storageUsageData:`Data`,storageUsageUnavailable:`Storage usage information unavailable`,clearNotificationLogsDescription:`Delete notification logs older than 30 days`,resetUiPreferencesDescription:`Reset sidebar order, theme, view modes, and layout preferences. Printers, archives, and settings are not affected.`,enableHomeAssistant:`Enable Home Assistant`,enableMqtt:`Enable MQTT`,useTls:`Use TLS`,enableMetricsEndpoint:`Enable Metrics Endpoint`,availableMetrics:`Available Metrics`,editUser:`Edit User`,deleteUserTitle:`Delete User`,groupName:`Group Name`,leaveEmptyForAnonymous:`Leave empty for anonymous`,leaveEmptyForNoAuth:`Leave empty for no authentication`,enterNewPassword:`Enter new password`,confirmNewPassword:`Confirm new password`,enterGroupName:`Enter group name`,enterDescriptionOptional:`Enter description (optional)`,enterCurrentPassword:`Enter current password`,enterNewPasswordMin6:`Enter new password (min 6 characters)`,toast:{keyCopied:`Key copied to clipboard`,copyFailed:`Failed to copy key`,keyAddedToBrowser:`Key added to API Browser`,clearLogsFailed:`Failed to clear logs`,uiPreferencesReset:`UI preferences reset. Refreshing...`,authDisabled:`Authentication disabled successfully`,authDisableFailed:`Failed to disable authentication`,apiKeyCreated:`API key created`,apiKeyDeleted:`API key deleted`,userCreated:`User created successfully`,userUpdated:`User updated successfully`,userDeleted:`User deleted successfully`,groupCreated:`Group created successfully`,groupUpdated:`Group updated successfully`,groupDeleted:`Group deleted successfully`,fillRequiredFields:`Please fill in all required fields`,passwordsDoNotMatch:`Passwords do not match`,passwordTooShort:`Password must be at least 8 characters`,passwordNeedsUppercase:`Password must contain at least one uppercase letter`,passwordNeedsLowercase:`Password must contain at least one lowercase letter`,passwordNeedsDigit:`Password must contain at least one digit`,passwordNeedsSpecial:`Password must contain at least one special character`,enterGroupName:`Please enter a group name`,settingsSaved:`Settings saved`,noPermissionUpdate:`You do not have permission to change settings`,cameraSettingsSaved:`Camera settings saved`,enterCameraUrl:`Please enter a camera URL`,passwordChanged:`Password changed successfully`,connectionFailed:`Connection failed`,testFailed:`Test failed`,cameraConnected:`Camera connected{{resolution}}`,cameraConnectedCoalesced:`Camera connected{{resolution}} (shared with a capture already running)`},testConnection:`Test Connection`,catalog:{spoolCatalog:`Spool Catalog`,spoolCatalogDescription:`Empty spool weights by brand/type. Used for automatic weight lookup when adding spools.`,searchCatalog:`Search catalog...`,addNewEntry:`Add New Entry`,namePlaceholder:`Name (e.g., Bambu Lab - Plastic)`,weight:`Weight`,type:`Type`,default:`Default`,custom:`Custom`,noMatch:`No entries match your search`,empty:`No entries in catalog`,deleteEntry:`Delete Entry`,deleteConfirm:`Are you sure you want to delete "{{name}}"?`,resetCatalog:`Reset Catalog`,resetConfirm:`Reset catalog to defaults? This will remove all custom entries.`,loadFailed:`Failed to load spool catalog`,nameWeightRequired:`Name and weight are required`,entryAdded:`Entry added`,addFailed:`Failed to add entry`,entryUpdated:`Entry updated`,updateFailed:`Failed to update entry`,entryDeleted:`Entry deleted`,deleteFailed:`Failed to delete entry`,resetSuccess:`Catalog reset to defaults`,resetFailed:`Failed to reset catalog`,exported:`Exported {{count}} entries`,imported:`Imported {{added}} entries ({{skipped}} skipped)`,importFailed:`Failed to import: invalid JSON format`,exportTooltip:`Export catalog to JSON`,importTooltip:`Import catalog from JSON`,resetTooltip:`Reset to defaults`,selectedCount:`{{count}} selected`,deleteSelected:`Delete Selected`,bulkDeleteConfirm:`Are you sure you want to delete {{count}} entries?`,bulkDeleted:`Deleted {{count}} entries`,bulkDeleteFailed:`Failed to delete entries`,material:`Material`,spoolWeight:`Spool Weight`,color:`Color`,updateSpoolWeight:`Update Spool Weight`,filamentUpdated:`Filament updated`,filamentUpdateFailed:`Failed to update filament`,filamentUpdateInvalid:`Invalid filament data`,keepExistingSpoolWeight:`Keep old weight for existing spools`,keepExistingSpoolWeightDesc:`Spools already created with this filament type retain the old tare weight. New spools use the updated value.`,applyToAllSpools:`Apply to all spools`,applyToAllSpoolsDesc:`All weight calculations for this filament type immediately use the new tare weight.`},colorCatalog:{title:`Color Catalog`,description:`Filament colors by manufacturer/material. Used for automatic color lookup when adding spools.`,searchColors:`Search colors...`,allManufacturers:`All manufacturers`,addNewColor:`Add New Color`,manufacturer:`Manufacturer`,colorName:`Color Name`,hex:`Hex`,materialOptional:`Material (optional)`,showing:`Showing {{filtered}} of {{total}} colors`,noMatch:`No colors match your search`,empty:`No colors in catalog`,deleteColor:`Delete Color`,deleteConfirm:`Are you sure you want to delete "{{name}}"?`,resetCatalog:`Reset Color Catalog`,resetConfirm:`Reset catalog to defaults? This will remove all custom colors.`,sync:`Sync`,starting:`Starting...`,syncTooltip:`Sync from FilamentColors.xyz (2000+ colors, may take a minute)`,loadFailed:`Failed to load color catalog`,fieldsRequired:`Manufacturer, color name, and hex color are required`,colorAdded:`Color added`,addFailed:`Failed to add color`,colorUpdated:`Color updated`,updateFailed:`Failed to update color`,colorDeleted:`Color deleted`,deleteFailed:`Failed to delete color`,resetSuccess:`Color catalog reset to defaults`,resetFailed:`Failed to reset catalog`,syncUpToDate:`Already up to date ({{count}} colors checked)`,syncComplete:`Added {{added}} new colors ({{skipped}} already existed)`,syncError:`Sync error`,syncFailed:`Failed to sync from FilamentColors.xyz`,exported:`Exported {{count}} colors`,imported:`Imported {{added}} colors ({{skipped}} skipped)`,importFailed:`Failed to import: invalid JSON format`,selectedCount:`{{count}} selected`,deleteSelected:`Delete Selected`,bulkDeleteConfirm:`Are you sure you want to delete {{count}} colors?`,bulkDeleted:`Deleted {{count}} colors`,bulkDeleteFailed:`Failed to delete colors`},dateFormat:`Date Format`,dateFormatUs:`US (MM/DD/YYYY)`,dateFormatEu:`EU (DD/MM/YYYY)`,dateFormatIso:`ISO (YYYY-MM-DD)`,timeFormat:`Time Format`,timeFormat12:`12-hour (3:30 PM)`,timeFormat24:`24-hour (15:30)`,defaultPrinter:`Default Printer`,defaultPrinterDescription:`Pre-select this printer for uploads, reprints, and other operations.`,slicerBambuStudio:`Bambu Studio`,slicerOrcaSlicer:`OrcaSlicer`,sidebarOrderDescription:`Use Sidebar to reorder items, reset visibility, and manage custom links.`,setDefault:`Set Default`,sidebarOrderSetDefaultHint:`Set default applies the current menu order to users who haven't customized theirs.`,sidebarDefaultSet:`Default menu order has been set.`,sidebarDefaultCleared:`Default menu order cleared.`,sidebarDefaultFailed:`Failed to set default menu order.`,reset:`Reset`,darkMode:`Dark Mode`,lightMode:`Light Mode`,active:`(active)`,background:`Background`,accent:`Accent`,style:`Style`,bgNeutral:`Neutral`,bgWarm:`Warm`,bgCool:`Cool`,bgOled:`OLED Black`,bgSlate:`Slate Blue`,bgForest:`Forest Green`,accentGreen:`Green`,accentTeal:`Teal`,accentBlue:`Blue`,accentOrange:`Orange`,accentPurple:`Purple`,accentRed:`Red`,styleClassic:`Classic`,styleGlow:`Glow`,styleVibrant:`Vibrant`,themeToggleHint:`Toggle between dark, light, and system mode using the icon in the sidebar.`,progressInTitle:`Print progress in tab`,progressInTitleDescription:`Show the active print's percentage and a progress ring in the browser tab.`,autoArchivePrints:`Auto-archive prints`,autoArchiveDescription:`Automatically save 3MF files when prints complete`,saveThumbnailsDescription:`Extract and save preview images from 3MF files`,captureFinishPhotoDescription:`Take a photo from printer camera when print completes. Bambuddy records a brief timelapse during the print so the photo can be sourced from the moment before the bed drops; the timelapse file is kept if you enabled timelapse for this print, otherwise it is deleted automatically after the photo is captured.`,finishPhotoRestorePlate:`Restore plate for finish photo`,finishPhotoRestorePlateDescription:`The printer drops the build plate about 100 mm when a print ends, leaving the finished print below the camera's framing. Bambuddy raises it back to just above the last printed layer, takes the photo, then lowers it again. Skipped when the print height is unknown or another job is queued.`,ffmpegNotInstalled:`ffmpeg not installed`,ffmpegRequired:`Camera capture requires ffmpeg. Install it via brew install ffmpeg (macOS) or apt install ffmpeg (Linux).`,camera:`Camera`,cameraViewMode:`Camera View Mode`,cameraOverlayDescription:`Camera opens in a resizable overlay on the main screen`,cameraWindowDescription:`Camera opens in a separate browser window`,externalCamerasDescription:`Configure external cameras to replace the built-in printer camera. Supports MJPEG streams, RTSP, HTTP snapshots, and USB cameras (V4L2). When enabled, the external camera is used for live view and finish photos.`,cameraPlaceholderUsb:`Device path (/dev/video0)`,cameraPlaceholderUrl:`Camera URL (rtsp://... or http://...)`,cameraTypeMjpeg:`MJPEG Stream`,cameraTypeRtsp:`RTSP Stream`,cameraTypeSnapshot:`HTTP Snapshot`,cameraTypeUsb:`USB Camera (V4L2)`,cameraSnapshotUrl:`Snapshot URL (optional)`,cameraSnapshotUrlPlaceholder:`http://192.168.1.61:1984/api/frame.jpeg?src=printer`,cameraSnapshotUrlHelp:`Single-frame URL used for notification thumbnails, finish photos, layer-timelapse frames, and plate detection. Timelapse and plate detection each require their own per-printer toggle — this URL is just the image source they pull from when active. Leave blank to capture from the live stream above. Useful for go2rtc (/api/frame.jpeg) and IP cameras with a dedicated snapshot endpoint.`,cameraRotation:`Rotation`,test:`Test`,connected:`Connected`,disconnected:`Disconnected`,currency:`Currency`,defaultFilamentCost:`Default filament cost (per kg)`,electricityCost:`Electricity cost per kWh`,energyDisplayMode:`Energy display mode`,energyModePrintDescription:`Dashboard shows sum of energy used during prints`,energyModeTotalDescription:`Dashboard shows lifetime energy from smart plugs`,fileManager:`File Manager`,createArchiveEntry:`Create Archive Entry When Printing`,createArchiveEntryDescription:`When printing from File Manager, optionally create an archive entry`,lowDiskSpaceWarning:`Low Disk Space Warning`,lowDiskSpaceDescription:`Show warning when free disk space falls below this threshold`,printerFirmware:`Printer Firmware`,checkFirmwareDescription:`Check for printer firmware updates from Bambu Lab`,bambuddySoftware:`Bambuddy Software`,autoCheckDescription:`Automatically check for new versions on startup`,checkNow:`Check now`,updateAvailableVersion:`Update available: v{{version}}`,releaseNotes:`Release Notes`,updateViaDocker:`Update via Docker Compose:`,updateViaHomeAssistant:`Updates are managed by the Home Assistant Supervisor. Open Settings → Add-ons → Bambuddy in Home Assistant to install the new version.`,updateViaWindowsInstaller:`Windows installations are updated by re-running the installer. Download the new version below — your data, settings and printers are preserved.`,downloadWindowsInstaller:`Download installer for v{{version}}`,installUpdate:`Install Update`,latestVersionRunning:`You're running the latest version`,failedToCheckUpdates:`Failed to check for updates: {{error}}`,backupRestore:`Backup & Restore`,backupRestoreDescription:`Export/import settings and configure GitHub backup`,goToBackup:`Go to Backup`,externalUrl:`External URL`,externalUrlDescription:`The external URL where Bambuddy is accessible. Used for notification images and external integrations.`,bambuddyUrl:`Bambuddy URL`,externalUrlHint:`Include protocol and port (e.g., http://192.168.1.100:8000)`,ftpRetry:`FTP Retry`,ftpRetryDescription:`Retry FTP operations when printer WiFi is unreliable. Applies to 3MF downloads, print uploads, timelapse downloads, and firmware updates.`,autoRetryDescription:`Automatically retry failed FTP operations`,retryAttempts:`Retry attempts`,retryDelay:`Retry delay`,connectionTimeout:`Connection timeout`,time_one:`{{count}} time`,time_other:`{{count}} times`,second_one:`{{count}} second`,second_other:`{{count}} seconds`,nSeconds:`{{count}} seconds`,increaseForWeakWifi:`Increase for printers with weak WiFi`,homeAssistant:`Home Assistant`,homeAssistantFullDescription:`Connect to Home Assistant to control smart plugs via HA's REST API. Supports switch, light, input_boolean, and script entities.`,homeAssistantUrl:`Home Assistant URL`,longLivedAccessToken:`Long-Lived Access Token`,haTokenHint:`Create a token in HA: Profile → Long-Lived Access Tokens → Create Token`,connectionSuccessful:`Connection Successful`,connectionFailed:`Connection Failed`,haConnectionSuccess:`Successfully connected to Home Assistant.`,haConnectionFailed:`Failed to connect to Home Assistant.`,mqttPublishing:`MQTT Publishing`,mqttDescription:`Publish BamBuddy events to an external MQTT broker for integration with Node-RED, Home Assistant, and other automation systems.`,mqttEnableDescription:`Publish events to external MQTT broker`,brokerHostname:`Broker hostname`,port:`Port`,usernameOptional:`Username (optional)`,passwordOptional:`Password (optional)`,topicPrefix:`Topic prefix`,topicPrefixHint:`Topics will be: {{prefix}}/printers//status, etc.`,prometheusMetrics:`Prometheus Metrics`,prometheusEndpointDescription:`Expose printer metrics at /api/v1/metrics for Prometheus/Grafana monitoring.`,bearerTokenOptional:`Bearer Token (optional)`,bearerTokenHint:`If set, requests must include Authorization: Bearer `,metricsConnectionStatus:`Connection status`,metricsPrinterState:`Printer state (idle/printing/etc)`,metricsPrintProgress:`Print progress 0-100%`,metricsBedTemp:`Bed temperature`,metricsNozzleTemp:`Nozzle temperature`,metricsPrintsTotal:`Total prints by result`,metricsMore:`...and more (layers, fans, queue, filament usage)`,smartPlugsDescription:`Connect smart plugs (Tasmota or Home Assistant) to automate power control and track energy usage for your printers.`,allOn:`All On`,allOff:`All Off`,addSmartPlug:`Add Smart Plug`,energySummary:`Energy Summary`,currentPower:`Current Power`,plugsOnline:`{{reachable}}/{{total}} plugs online`,today:`Today`,yesterday:`Yesterday`,total:`Total`,enablePlugsForSummary:`Enable plugs to see energy summary`,addNotificationProvider:`Add`,systemBadge:`(System)`,creating:`Creating...`,changing:`Changing...`,deleteUserAndItems:`Delete user AND their items`,deleteUserKeepItems:`Delete user, keep items (become ownerless)`,ok:`OK`,twoFa:{totpTitle:`Authenticator App (TOTP)`,totpDesc:`Use an authenticator app like Google Authenticator, Aegis or Authy.`,emailOtpTitle:`Email OTP`,emailOtpDesc:`Send a one-time code to {{email}} when you log in.`,emailOtpNoEmail:`Add an email address to your account to enable this method.`,addEmailFirst:`Your account has no email address. Ask an admin to add one before enabling Email OTP.`,setupTotp:`Set up Authenticator App`,setupAuthApp:`Set up Authenticator App`,setupInstructions:`Scan the QR code below with your authenticator app, then confirm with a code.`,manualEntry:`Can't scan? Enter this secret manually:`,scannedContinue:`I've scanned the code — continue`,enterCodeToConfirm:`Enter the 6-digit code from your authenticator app to confirm setup.`,activate:`Activate`,disableTotp:`Disable Authenticator`,disableConfirmHint:`Enter a valid TOTP code or a backup code to disable the authenticator.`,totpDisabled:`Authenticator app disabled.`,emailOtpEnabled:`Email OTP enabled.`,emailOtpDisabled:`Email OTP disabled.`,smtpRequired:`Please configure and test SMTP settings first.`,invalidCode:`Invalid code. Please try again.`,enableEmailOtp:`Enable Email OTP`,disableEmailOtp:`Disable Email OTP`,emailSetupEnterCode:`A verification code has been sent to your email address. Enter it below to confirm you own this inbox.`,verifyAndEnable:`Verify & Enable`,emailDisablePasswordHint:`Enter your account password to confirm disabling email OTP.`,passwordPlaceholder:`Enter your password`,backupCodesTitle:`Save your backup codes`,backupCodesWarning:`Save these codes somewhere safe. Each code can only be used once and they will not be shown again.`,backupCodesRemaining:`{{count}} backup codes remaining`,savedCodes:`I've saved my codes`,regenBackup:`Regenerate Backup Codes`,regenBackupHint:`Enter your current TOTP code to generate 10 new backup codes. All existing backup codes will be invalidated.`,newBackupCodes:`New backup codes`,linkedAccounts:`Linked SSO Accounts`,linkedAccountsDesc:`These external identity providers are linked to your account.`,oidcUnlinked:`Account unlinked.`},sessionPolicy:{title:`Session Policy`,description:`Maximum session lifetime for new user logins. Already-issued tokens keep their original expiry.`,preset24h:`24 hours`,preset7d:`7 days`,preset30d:`30 days`,customHoursLabel:`Custom session lifetime in hours`,hoursSuffix:`hours`,warning:`Longer sessions reduce automatic logout protection. Recommended only for trusted single-user deployments.`},oidc:{title:`SSO / OIDC Providers`,desc:`Configure OpenID Connect providers to allow single sign-on via external identity providers.`,addProvider:`Add Provider`,newProvider:`New Provider`,empty:`No OIDC providers configured yet.`,created:`Provider created.`,updated:`Provider updated.`,deleted:`Provider deleted.`,refreshIcon:`Refresh icon`,removeIcon:`Remove icon`,iconRefreshed:`Icon refreshed.`,iconRemoved:`Icon removed.`,iconFetchFailed:`Icon could not be fetched from the provider URL.`,deleteTitle:`Delete Provider`,deleteMessage:`Delete "{{name}}"? All linked user accounts will be disconnected.`,form:{name:`Display Name`,issuerUrl:`Issuer URL`,clientId:`Client ID`,clientSecret:`Client Secret`,scopes:`Scopes`,iconUrl:`Icon URL (optional)`,enabled:`Enabled`,autoCreate:`Auto-create users`,autoCreateDesc:`Automatically create a local account on first login.`,autoLink:`Auto-link existing accounts`,autoLinkDesc:`Link existing local accounts by matching email on first login.`,secretHint:`leave blank to keep current`,secretPlaceholder:`new secret`,emailClaim:`Email Claim`,emailClaimDesc:`JWT claim used as email identity. Use 'preferred_username' or 'upn' for Azure Entra ID (which does not send email_verified). Only use trusted claim names.`,emailClaimPlaceholder:`email`,emailClaimCustomClaimAutoLinkWarning:`Custom claims are safe for auto-link only when the value is tenant-administered (e.g. Azure Entra ID upn / preferred_username). Do not enable auto-link if your IdP allows users to self-assert this claim.`,requireEmailVerified:`Require email verified`,requireEmailVerifiedDesc:`Only accept the email claim when the provider marks it as verified.`,requireEmailVerifiedWarning:`Warning: email will be accepted even without verification. Use only with trusted providers.`,requireEmailVerifiedAutoLink:`Disable auto-link first to change this setting.`,defaultGroup:`Default Group`,defaultGroupDesc:`Group assigned to auto-created users. Falls back to Viewers if not set.`,defaultGroupViewersFallback:`Viewers (default)`,autologin:`Autologin`,autologinDesc:`Redirect unauthenticated visitors straight to this provider. Only one provider can carry this flag.`}},encryption:{title:`MFA Encryption Status`,enabledFromEnv:`At-rest encryption enabled (key from MFA_ENCRYPTION_KEY environment variable)`,enabledFromFile:`At-rest encryption enabled (key loaded from data directory)`,enabledGenerated:`At-rest encryption enabled with auto-generated key`,notConfigured:`At-rest encryption not configured`,notConfiguredDesc:`TOTP secrets and OIDC client_secrets are stored in plaintext. Set MFA_ENCRYPTION_KEY or restart Bambuddy with a writable data directory to auto-generate one.`,allEncrypted:`All MFA secrets are encrypted at rest.`,legacyRowsLabel:`Legacy plaintext rows`,encryptedRowsLabel:`Encrypted rows`,legacyRowsWarning:`{{count}} legacy plaintext row(s) detected. Re-save the OIDC provider or re-enroll the user’s authenticator app to migrate to encrypted storage.`,backupHint:`The auto-generated key is stored at DATA_DIR/.mfa_encryption_key and is included in local backup ZIPs. Keep your backups secure or set MFA_ENCRYPTION_KEY explicitly.`,decryptionBrokenTitle:`Encryption key missing`,decryptionBrokenError:`{{count}} encrypted record(s) cannot be decrypted because the encryption key is no longer available. Restore the previous MFA_ENCRYPTION_KEY or DATA_DIR/.mfa_encryption_key to recover.`,migrationErrorWarning:`{{count}} legacy row(s) failed to re-encrypt at startup. Check server logs and restart Bambuddy to retry.`},pipelineLimits:{title:`Slicer Pipeline limits`,maxCopiesLabel:`Max copies per run`,maxCopiesDesc:`Upper bound on the copies operators can request when running a pipeline. Server-side hard cap is 1000.`},pipelines:{title:`Slicer Pipelines`,subtitle:`Reusable preset bundles (printer + process + filaments + bed type). Save one from the Slice dialog and apply it with a single click on the next file.`,loading:`Loading pipelines…`,loadError:`Could not load pipelines.`,confirmDelete:`Delete this pipeline? This cannot be undone.`,staleWarning:`One or more referenced presets no longer exist. Re-save this pipeline from the Slice dialog to fix.`,empty:{title:`No pipelines yet.`,howto:`Open the Slice dialog for any file, pick your printer / process / filaments / bed type, then click "Save as pipeline". Your saved pipelines will appear here.`},field:{name:`Pipeline name`,description:`Description`,targetPrinter:`Target printer`,noTarget:`— No target —`,targetKind:`Target type`,targetKindSpecific:`Specific printer`,targetKindClass:`Printer class`,targetModelClass:`Printer model`,fanoutStrategy:`Fanout strategy`,fanout:{max_parallel:`Max parallel — distribute across any idle matching printer`,round_robin:`Round robin — cycle through eligible printers`,fill_one_first:`Fill one first — pin all copies to one printer`},fanoutShort:{max_parallel:`parallel`,round_robin:`round robin`,fill_one_first:`fill one first`}},action:{save:`Save`,cancel:`Cancel`,rename:`Rename`,delete:`Delete`},slot:{printer:`Printer`,process:`Process`,filament:`Filament`,filamentN:`Filament {{n}}`,filamentAll:`All {{n}} slots`,bed:`Bed`},group:{profiles:`Profiles`,filaments:`Filaments`},searchPlaceholder:`Search pipelines…`,filterTargetType:`Filter by target type`,filterTarget:`Filter by target`,filter:{all:`All targets`,noTarget:`No target set`,count:`{{shown}} / {{total}}`,noMatches:`No pipelines match the current filters.`},toast:{saved:`Pipeline saved`,saveFailed:`Save failed`,deleted:`Pipeline deleted`,deleteFailed:`Delete failed`},noTargetHint:`Set a target printer to run this`,noTargetWarning:`Set a target printer before running this pipeline.`,runs:{lastRun:`Last run`,status:{queued:`queued`,slicing:`slicing`,dispatching:`dispatching`,in_progress:`printing`,completed:`completed`,failed:`failed`,partial_failure:`partial failure`,cancelled:`cancelled`}}}},notification:{printStarted:{title:`Print Started`,body:`{{printer}}: {{filename}} has started printing`},printCompleted:{title:`Print Completed`,body:`{{printer}}: {{filename}} completed successfully`},printFailed:{title:`Print Failed`,body:`{{printer}}: {{filename}} has failed`},printStopped:{title:`Print Stopped`,body:`{{printer}}: {{filename}} was stopped`},printProgress:{title:`Print Progress`,body:`{{printer}}: {{filename}} is {{percent}}% complete`},printerOffline:{title:`Printer Offline`,body:`{{printer}} is offline`},printerError:{title:`Printer Error`,body:`{{printer}}: {{error}}`},filamentLow:{title:`Low Filament`,body:`{{printer}}: Filament is running low`},maintenanceDue:{title:`Maintenance Due`,body:`{{printer}}: {{items}} need attention`}},errors:{generic:`Something went wrong`,networkError:`Network error. Please check your connection.`,notFound:`Not found`,unauthorized:`Unauthorized`,serverError:`Server error`,validationError:`Please check your input`,printerConnectionFailed:`Failed to connect to printer`,saveFailed:`Failed to save changes`,deleteFailed:`Failed to delete`,loadFailed:`Failed to load data`},hmsErrors:{title:`Errors - {{name}}`,noErrors:`No errors`,viewOnWiki:`View on Bambu Lab Wiki`,mqttVerifyFailedRemedy:`Enable Developer Mode on the printer, restart the printer, then start the job again.`,unknownCode:`Unknown HMS code — see the Bambu Lab wiki for details.`,clearInstructions:`Clear errors on the printer to dismiss them here.`,clearErrors:`Clear Errors`,clearSuccess:`HMS errors cleared`,clearFailed:`Failed to clear HMS errors`,actionSuccess:`Action sent to printer`,actionFailed:`Failed to send action`,runoutExpectedSlot:`Filament ran out in {{ranOut}}. The printer is now waiting for compatible filament in {{expected}}. Insert a spool into {{expected}}, then select Retry.`,runoutExpectedSlotOnly:`The printer is waiting for compatible filament in {{expected}}. Insert a spool there, then select Retry.`,runoutSlotUnknown:`Filament ran out and the print is paused. Bambuddy could not determine which slot the printer now expects — check the printer screen for the requested slot.`,actions:{RESUME_PRINTING:`Resume Printing`,RESUME_PRINTING_DEFECTS:`Resume (defects acceptable)`,RESUME_PRINTING_PROBELM_SOLVED:`Resume (problem solved)`,STOP_PRINTING:`Stop Printing`,CHECK_ASSISTANT:`Check Assistant`,FILAMENT_EXTRUDED:`Filament Extruded, Continue`,RETRY_FILAMENT_EXTRUDED:`Not Extruded Yet, Retry`,CONTINUE:`Finished, Continue`,LOAD_VIRTUAL_TRAY:`Load Filament`,OK_BUTTON:`OK`,FILAMENT_LOAD_RESUME:`Filament Loaded, Resume`,JUMP_TO_LIVEVIEW:`View Liveview`,NO_REMINDER_NEXT_TIME:`No Reminder Next Time`,REFRESH_NOZZLE:`Recheck`,IGNORE_NO_REMINDER_NEXT_TIME:`Ignore. Don't Remind Next Time`,IGNORE_RESUME:`Ignore this and Resume`,PROBLEM_SOLVED_RESUME:`Problem Solved and Resume`,TURN_OFF_FIRE_ALARM:`Got it, Turn off the Fire Alarm.`,RETRY_PROBLEM_SOLVED:`Retry (problem solved)`,CANCLE:`Cancle`,STOP_DRYING:`Stop Drying`,PROCEED:`Proceed`,OK_JUMP_RACK:`OK`,ABORT:`Abort`,DISABLE_PURIFICATION:`Disable Purification for This Print`,DONT_REMIND_NEXT_TIME:`Don't Remind Me`,DBL_CHECK_CANCEL:`Cancel`,DBL_CHECK_DONE:`Done`,DBL_CHECK_RETRY:`Retry`,DBL_CHECK_RESUME:`Resume`,DBL_CHECK_OK:`Confirm`,REMOVE_CLOSE_BTN:`Close`}},mqttDebug:{title:`MQTT Debug Log`,searchPlaceholder:`Search topic or payload...`,noMessages:`No messages logged yet`,startLoggingHint:`Click "Start Logging" to begin capturing MQTT messages`,noMessagesMatch:`No messages match your filter`,adjustFilterHint:`Try adjusting your search or filter criteria`,incoming:`Incoming`,outgoing:`Outgoing`,loggingStopped:`Logging stopped`,loggingActive:`Logging active - messages will auto-refresh`,startLogging:`Start Logging`,stopLogging:`Stop Logging`,clearLog:`Clear Log`,topic:`Topic`,timestamp:`Timestamp`,direction:`Direction`,all:`All`},printerFiles:{title:`File Manager`,storageUsed:`Used:`,storageFree:`Free:`,filterPlaceholder:`Filter files...`,deleteButton:`Delete`,deleteFiles:`Delete {{count}} Files`,deleteFileConfirm:`Delete "{{name}}"? This cannot be undone.`,deleteFilesConfirm:`Delete {{count}} selected files? This cannot be undone.`,noFiles:`No files on printer`,loadingFiles:`Loading files...`,failedToLoad:`Failed to load files`,toast:{filesDeleted:`Deleted {{count}} file(s)`,deleteFailed:`Delete failed: {{error}}`}},confirm:{delete:`Are you sure you want to delete this?`,unsavedChanges:`You have unsaved changes. Are you sure you want to leave?`,clearQueue:`Are you sure you want to clear the queue?`},login:{title:`Bambuddy Login`,subtitle:`Sign in to your account`,username:`Username`,usernamePlaceholder:`Enter your username`,usernameOrEmail:`Username or Email`,usernameOrEmailPlaceholder:`Username or @ Email`,password:`Password`,passwordPlaceholder:`Enter your password`,signIn:`Sign in`,signingIn:`Logging in...`,rememberMe:`Remember Me`,forgotPassword:`Forgot your password?`,autologinFailed:`Automatic SSO sign-in failed. Pick a provider below to continue.`,localDisabledNotice:`Local sign-in is disabled. Use one of the SSO providers below.`,loginSuccess:`Logged in successfully`,loginFailed:`Login failed`,enterCredentials:`Please enter username and password`,enterEmail:`Please enter your email address`,oidcLoginFailed:`OIDC login failed`,oidcErrors:{providerError:`The identity provider returned an error`,missingParameters:`OIDC callback is missing required parameters`,invalidState:`OIDC state is invalid or has already been used`,stateExpired:`OIDC login session expired — please try again`,providerNotFound:`OIDC provider not found`,discoveryFailed:`Failed to fetch OIDC discovery document`,invalidDiscovery:`OIDC discovery document is invalid`,networkError:`Network error during OIDC token exchange`,badResponse:`Unexpected response during OIDC token exchange`,noIdToken:`OIDC provider did not return an ID token`,validationFailed:`OIDC token validation failed`,nonceMismatch:`OIDC nonce mismatch — possible replay attack`,missingSubClaim:`OIDC token is missing the sub claim`,noLinkedAccount:`No local account is linked to this OIDC identity`,accountInactive:`Your account is inactive`,userResolutionFailed:`Failed to resolve your account`,internalError:`An internal error occurred during OIDC login`,tokenExchangeFailed:`OIDC token exchange failed`},forgotPasswordTitle:`Forgot Password`,forgotPasswordMessage:`If you've forgotten your password, please contact your system administrator to reset it.`,forgotPasswordEmailMessage:`Enter your email address and we'll send you a new password.`,emailAddress:`Email Address`,emailPlaceholder:`your.email@example.com`,cancel:`Cancel`,sending:`Sending...`,sendResetEmail:`Send Reset Email`,howToReset:`How to reset your password:`,resetStep1:`Contact your Bambuddy administrator`,resetStep2:`Ask them to reset your password in User Management`,resetStep3:`They can set a new temporary password for you`,resetStep4:`Log in with the new password and change it in Settings`,gotIt:`Got it`,resetPassword:{title:`Set New Password`,subtitle:`Enter and confirm your new password below.`,newPassword:`New Password`,newPasswordPlaceholder:`At least 8 characters`,confirmPassword:`Confirm Password`,confirmPasswordPlaceholder:`Repeat new password`,saving:`Saving…`,submit:`Set New Password`,backToLogin:`Back to login`,passwordsDoNotMatch:`Passwords do not match`,passwordTooShort:`Password must be at least 8 characters`,resetFailed:`Password reset failed. The link may have expired.`},twoFA:{title:`Two-Factor Authentication`,subtitle:`Your account is protected with 2FA. Enter the verification code below.`,methodAuthenticator:`Authenticator App`,methodEmail:`Email Code`,methodBackup:`Backup Code`,instructionsTotp:`Open your authenticator app and enter the 6-digit code for Bambuddy.`,instructionsEmail:`A 6-digit code has been sent to your email address. It expires in 10 minutes.`,instructionsEmailNotSent:`Click the button below to receive a verification code via email.`,instructionsBackup:`Enter one of your 8-character backup recovery codes. Each code can only be used once.`,sendCodeButton:`Send Code via Email`,sendingCode:`Sending...`,resendCode:`Resend code`,codeLabel:`Verification Code`,backupCodeLabel:`Backup Code`,codePlaceholder:`000000`,backupCodePlaceholder:`XXXXXXXX`,verifyButton:`Verify`,verifyingButton:`Verifying...`,backToLogin:`← Back to login`,orContinueWith:`or continue with`,signInWith:`Sign in with {{provider}}`,enterCode:`Please enter the verification code`,sendCodeFailed:`Failed to send verification code`,invalidCode:`Invalid code. Please try again.`}},setup:{title:`Bambuddy Setup`,subtitle:`Configure authentication for your Bambuddy instance`,enableAuth:`Enable Authentication`,adminAccount:`Admin Account`,adminAccountDesc:`If admin users already exist, authentication will be enabled using the existing admin accounts. Leave the fields below empty to use existing admins, or enter new credentials to create a new admin user.`,adminUsername:`Admin Username`,adminPassword:`Admin Password`,optionalIfAdminExists:`(optional if admin users exist)`,adminUsernamePlaceholder:`Enter admin username (optional)`,adminPasswordPlaceholder:`Enter admin password (optional)`,confirmPassword:`Confirm Password`,confirmPasswordPlaceholder:`Confirm admin password`,settingUp:`Setting up...`,completeSetup:`Complete Setup`,toast:{authEnabledAdminCreated:`Authentication enabled and admin user created`,authEnabledExistingAdmins:`Authentication enabled using existing admin users`,setupCompleted:`Setup completed`,enterBothCredentials:`Please enter both admin username and password, or leave both empty to use existing admin users`,passwordsDoNotMatch:`Passwords do not match`,passwordTooShort:`Password must be at least 6 characters`}},changePassword:{title:`Change Password`,currentPassword:`Current Password`,currentPasswordPlaceholder:`Enter current password`,newPassword:`New Password`,newPasswordPlaceholder:`Enter new password (min 6 characters)`,confirmPassword:`Confirm New Password`,confirmPasswordPlaceholder:`Confirm new password`,passwordsDoNotMatch:`Passwords do not match`,passwordTooShort:`Password must be at least 6 characters`,changing:`Changing...`,success:`Password changed successfully`,failed:`Failed to change password`},plateAlert:{title:`Print Paused!`,message:`Objects detected on build plate. The print has been automatically paused. Please clear the plate and resume the print.`,understand:`I Understand`},camera:{title:`Camera View`,invalidPrinterId:`Invalid printer ID`,live:`Live`,snapshot:`Snapshot`,restartStream:`Restart stream`,refreshSnapshot:`Refresh snapshot`,fullscreen:`Fullscreen`,exitFullscreen:`Exit fullscreen`,connectingToCamera:`Connecting to camera...`,capturingSnapshot:`Capturing snapshot...`,connectionLost:`Connection lost`,connectionFailed:`Camera connection failed`,reconnecting:`Reconnecting in {{countdown}}s... (attempt {{attempt}}/{{max}})`,reconnectNow:`Reconnect now`,cameraUnavailable:`Camera unavailable`,cameraUnavailableDesc:`Make sure the printer is powered on and connected.`,noCamera:`No camera available`,retry:`Retry`,cameraStream:`Camera stream`,zoomOut:`Zoom out`,zoomIn:`Zoom in`,resetZoom:`Reset zoom`,recording:`Recording`,startRecording:`Start Recording`,stopRecording:`Stop Recording`,chamberLight:`Toggle chamber light`,unavailable:`Camera unavailable`,diagnose:{button:`Diagnose`,modalTitle:`Camera diagnostic`,running:`Running diagnostic...`,runFailed:`Diagnostic could not run: {{error}}`,retry:`Run again`,stage:{tcp_reachable:`Network reachability`,first_frame:`Frame capture`,live_stream_active:`Live stream active`},summary:{all_ok:`Camera is working. The diagnostic completed all stages successfully.`,live_stream_active_healthy:`Camera is currently streaming with recent frames — no test needed.`,printer_unreachable:`Printer is not reachable. Check the IP address, network connection, and that the printer is powered on.`,camera_port_closed:`Printer is reachable but the camera port is closed. Make sure LAN-only mode and Developer Mode are enabled in the printer settings.`,no_frame:`Connected to the camera but no frames were received. Try again, or check that the camera is enabled in the printer settings.`,unknown_failure:`Camera diagnostic failed for an unknown reason. Check the support log for details.`},meta:{protocol:`Protocol`,port:`Port`,profile:`Profile`}}},groups:{title:`Group Management`,subtitle:`Manage permission groups for access control`,backToSettings:`Back to Settings`,createGroup:`Create Group`,noPermission:`You do not have permission to access this page.`,system:`System`,noDescription:`No description`,usersCount:`{{count}} users`,permissionsCount:`{{count}} permissions`,edit:`Edit`,delete:`Delete`,toast:{created:`Group created successfully`,updated:`Group updated successfully`,deleted:`Group deleted successfully`,enterGroupName:`Please enter a group name`},modal:{editGroup:`Edit Group`,createGroup:`Create Group`,cancel:`Cancel`,saving:`Saving...`,creating:`Creating...`,saveChanges:`Save Changes`},form:{groupName:`Group Name`,groupNamePlaceholder:`Enter group name`,systemGroupWarning:`System group names cannot be changed`,description:`Description`,descriptionPlaceholder:`Enter description (optional)`,permissions:`Permissions ({{count}} selected)`},deleteModal:{title:`Delete Group`,message:`Are you sure you want to delete this group? Users in this group will lose these permissions.`,confirm:`Delete Group`},editor:{title:`Edit Group`,createTitle:`Create Group`,search:`Search permissions...`,selectAll:`Select All`,clearAll:`Clear All`,permissionsSelected:`{{count}} selected`,noResults:`No permissions match your search`,websocketHint:`Required for live updates. Without it, the interface falls back to periodic polling.`}},users:{title:`User Management`,subtitle:`Manage users and their access to your Bambuddy instance`,backToSettings:`Back to Settings`,createUser:`Create User`,noPermission:`You do not have permission to access this page.`,admin:`Admin`,noGroups:`No groups`,active:`Active`,inactive:`Inactive`,edit:`Edit`,delete:`Delete`,system:`System`,noGroupsAvailable:`No groups available`,table:{username:`Username`,groups:`Groups`,status:`Status`,actions:`Actions`},toast:{created:`User created successfully`,updated:`User updated successfully`,deleted:`User deleted successfully`,fillRequired:`Please fill in all required fields`,passwordsDoNotMatch:`Passwords do not match`,passwordTooShort:`Password must be at least 6 characters`,ldapProvisioned:`Provisioned LDAP user "{{username}}"`},modal:{createUser:`Create User`,editUser:`Edit User`,cancel:`Cancel`,creating:`Creating...`,saving:`Saving...`,saveChanges:`Save Changes`,advancedAuthSubtitle:`with Advanced Authentication`,tabsAriaLabel:`User source`,localTab:`Local`,ldapTab:`LDAP`,ldapSearchLabel:`Search directory`,ldapSearchPlaceholder:`Type a username, name, or email...`,ldapMinChars:`Type at least 2 characters to search`,ldapTypeToSearch:`Start typing to search the LDAP directory`,ldapSearching:`Searching directory...`,ldapNoResults:`No matching users in the directory`,ldapSearchError:`Directory search failed. Check the LDAP server status.`,ldapAlreadyProvisioned:`Already provisioned`,ldapSelectedLabel:`Selected`,ldapProvision:`Provision user`,ldapProvisioning:`Provisioning...`,ldapErrorProvision:`Provisioning failed. Check the LDAP server status and try again.`},form:{username:`Username`,usernamePlaceholder:`Enter username`,email:`Email`,emailPlaceholder:`user@example.com`,password:`Password`,passwordPlaceholder:`Enter password`,confirmPassword:`Confirm Password`,confirmPasswordPlaceholder:`Confirm password`,newPasswordPlaceholder:`Enter new password`,confirmNewPasswordPlaceholder:`Confirm new password`,leaveBlankToKeep:`leave blank to keep current`,groups:`Groups`,optional:`optional`,autoGeneratedPassword:`A secure password will be automatically generated and emailed to the user.`,passwordManagedByAdvancedAuth:`Password is managed by Advanced Authentication. Use "Reset Password" to send a new password to the user via email.`,resetPassword:`Reset Password`,resettingPassword:`Resetting Password...`},deleteModal:{title:`Delete User`,message:`Are you sure you want to delete this user? This action cannot be undone.`,confirm:`Delete User`}},streamOverlay:{title:`Stream Overlay`,invalidPrinterId:`Invalid printer ID`,cameraStream:`Camera stream`,progress:`Progress`,eta:`ETA`,printerIdle:`Printer is idle`,printerOffline:`Printer offline`,status:{printing:`Printing`,paused:`Paused`,finished:`Finished`,failed:`Failed`,idle:`Idle`,unknown:`Unknown`}},profiles:{title:`Profiles`,subtitle:`Manage your slicer presets and pressure advance calibrations`,tabs:{bambuCloud:`Bambu Cloud`,orcaCloud:`Orca Cloud`,local:`Local Profiles`,kprofiles:`K-Profiles`},orcaCloud:{connectedAs:`Connected as`,connectedShort:`Connected to Orca Cloud`,logout:`Disconnect`,noLogoutPermission:`You do not have permission to disconnect`,noConnectPermission:`You do not have permission to connect to Orca Cloud`,retry:`Retry`,connectButton:`Connect Orca Cloud`,connect:{title:`Connect to Orca Cloud`,description:`Sign in to your Orca Cloud account to sync your slicer profiles into Bambuddy.`},device:{title:`Approve Bambuddy in Orca Cloud`,instruction:`Open Orca Cloud and approve this code. Bambuddy connects automatically once you approve.`,codeLabel:`Your pairing code`,openButton:`Open Orca Cloud approval page`,manualHint:`Or go to {{url}} and enter the code above.`,waiting:`Waiting for you to approve…`,cancel:`Cancel`},profiles:{title:`Your Orca Cloud profiles ({{count}})`,refresh:`Refresh`,empty:`No profiles found in your Orca Cloud account yet.`},toast:{disconnected:`Disconnected from Orca Cloud`},errors:{startFailed:`Could not start Orca Cloud pairing.`,denied:`The pairing was denied in Orca Cloud.`,expired:`The pairing code expired. Click Connect to try again.`,pollFailed:`Lost the connection while waiting for approval. Please try again.`}},localProfiles:{title:`Local Profiles`,subtitle:`Import and manage slicer presets from OrcaSlicer`,import:`Import Profiles`,importDesc:`Drop .bbscfg, .bbsflmt, .orca_filament, .zip, or .json files here`,importing:`Importing...`,search:`Search local presets...`,noPresets:`No local presets yet`,noSearchResults:`No presets match your search`,badge:`Local`,edit:`Edit`,delete:`Delete`,cancel:`Cancel`,deleteConfirmTitle:`Delete Preset`,deleteConfirm:`Are you sure you want to delete this preset? This cannot be undone.`,source:`Source`,inheritsFrom:`Inherits`,filamentType:`Type`,vendor:`Vendor`,compatiblePrinters:`Printers`,nozzleTemp:`Nozzle Temp`,cost:`Cost`,density:`Density`,pressureAdvance:`Pressure Advance`,filament:`Filament`,process:`Process`,printer:`Printer`,toast:{importSuccess:`{{count}} preset(s) imported`,importSkipped:`{{count}} preset(s) skipped (duplicates)`,importError:`{{count}} error(s) during import`,deleted:`Preset deleted`,updated:`Preset updated`}},connectedAs:`Connected as`,signInExpiredTitle:`Bambu Cloud sign-in expired`,signInExpiredBody:`Bambu Lab no longer accepts the stored token. Sign in again to restore cloud profiles, MakerWorld imports and firmware checks.`,logout:`Logout`,noLogoutPermission:`You do not have permission to logout`,failedToLoad:`Failed to load profiles`,retry:`Retry`,time:{justNow:`Just now`,minsAgo:`{{count}}m ago`,hoursAgo:`{{count}}h ago`,daysAgo:`{{count}}d ago`},toast:{loggedOut:`Logged out`},login:{title:`Connect to Bambu Cloud`,subtitle:`Sync your slicer presets across devices`,email:`Email`,password:`Password`,region:`Region`,regionGlobal:`Global`,regionChina:`China`,verificationCode:`Verification Code`,totpCode:`Authenticator Code`,checkEmail:`Check your email ({{email}}) for a 6-digit code`,enterTotpHint:`Enter the 6-digit code from your authenticator app`,accessToken:`Access Token`,accessTokenHint:`Paste your Bambu Cloud access token. China-region accounts must use this path (phone-bound — email login unavailable). See the wiki for how to retrieve the token from MakerWorld cookies.`,back:`Back`,loginButton:`Login`,verifyButton:`Verify`,setTokenButton:`Set Token`,useToken:`Use access token instead`,useEmail:`Login with email instead`,toast:{loggedIn:`Logged in successfully`,codeSent:`Verification code sent to your email`,enterTotp:`Enter code from your authenticator app`,tokenSet:`Token set successfully`}},presets:{myPreset:`My preset (editable)`,duplicate:`Duplicate`,editable:`Editable`,failedToLoadDetails:`Failed to load preset details`,deleteConfirm:`Delete this preset?`,deleteWarning:`This will permanently delete "{{name}}" from Bambu Cloud. This cannot be undone.`,noDuplicatePermission:`You do not have permission to duplicate presets`,noEditPermission:`You do not have permission to edit presets`,noDeletePermission:`You do not have permission to delete presets`,types:{filament:`Filament preset`,printer:`Printer preset`,process:`Process preset`},toast:{deleted:`Preset deleted`,created:`Preset created`,updated:`Preset updated`,duplicated:`Preset duplicated`,fieldAdded:`Field "{{key}}" added`,exported:`Preset exported`},baseLabel:`Base: {{name}}`,currentLabel:`Current: {{name}}`,newPreset:`New Preset`,editPreset:`Edit Preset`,duplicatePreset:`Duplicate Preset`,createNewPreset:`Create New Preset`,customizeSettings:`Customize settings for your new preset`,compareWithBase:`Compare with base preset`,compare:`Compare`,basePreset:`Base Preset`,selectBasePreset:`Select base preset...`,presetName:`Preset Name`,myCustomPreset:`My custom preset`,inheritsFrom:`Inherits from`,dropJsonToImport:`Drop JSON to import`,tabs:{common:`Common`,allFields:`All Fields`},availableFields:`Available Fields`,searchFieldsPlaceholder:`Search fields...`,noMatchingFields:`No matching fields`,allFieldsAdded:`All fields added`,addCustomField:`Add custom field`,yourOverrides:`Your Overrides`,noOverridesYet:`No overrides yet`,clickFieldsToAdd:`Click fields on the left to add them`,saveAsTemplate:`Save as template`,jsonTip:`Tip: Drag & drop a .json file anywhere on this modal to import settings`},cloudView:{searchPlaceholder:`Search presets...`,templates:`Templates`,refresh:`Refresh`,newPreset:`New Preset`,clearFilters:`Clear filters`,compareMode:`Compare Mode`,selectAnotherPreset:`Select another {{type}} preset`,clickTwoPresets:`Click two presets of the same type to compare`,selectFirst:`1. Select first`,selectSecond:`2. Select second`,compareNow:`Compare Now`,lastSynced:`Last synced:`,showingCount:`Showing {{showing}} of {{total}} presets`,noPresetsFound:`No presets found`,columns:{filament:`Filament`,process:`Process`,printer:`Printer`},noFilamentPresets:`No filament presets`,noProcessPresets:`No process presets`,noPrinterPresets:`No printer presets`,filters:{type:`Type`,owner:`Owner`,printer:`Printer`,nozzle:`Nozzle`,filament:`Filament`,layer:`Layer`,all:`All`,myPresets:`My Presets`,builtIn:`Built-in`,process:`Process`},noTemplatesPermission:`You do not have permission to manage templates`,noRefreshPermission:`You do not have permission to refresh profiles`,noCreatePermission:`You do not have permission to create presets`},templates:{title:`Quick Templates`,noTemplates:`No templates yet`,createFirst:`Create templates from the preset editor`,typeFilter:`Type:`,deleteTitle:`Delete Template`,deleteWarning:`This action cannot be undone`,deleteConfirm:`Are you sure you want to delete "{{name}}"?`,namePlaceholder:`Template name`,descriptionPlaceholder:`Description`,settingsJson:`Settings (JSON)`,fieldsCount:`{{count}} fields`,shownInModals:`Shown in modals`,hiddenInModals:`Hidden in modals`,apply:`Apply`,toast:{deleted:`Template deleted`,updated:`Template updated`,created:`Template created`,applied:`Template applied`}}},support:{debugLoggingActive:`Debug logging is active`,manageLogs:`Manage`,collectItem7:`Printer connectivity and firmware versions`,collectItem8:`Integration status (Spoolman, MQTT, HA)`,collectItem9:`Network interfaces (subnets only)`,collectItem10:`Python package versions`,collectItem11:`Database health checks`,collectItem12:`Docker environment details`,bundleGenerating:`Generating bundle...`,bundleStepConnection:`Running printer connectivity checks`,bundleStepVirtualPrinters:`Running virtual-printer setup checks`,bundleStepLogScan:`Scanning recent logs for known issues`,bundleStepBuild:`Building the support bundle ZIP`},fileManager:{title:`File Manager`,subtitle:`Organize and manage your print files`,uploadFiles:`Upload Files`,newFolder:`New Folder`,folderName:`Folder Name`,folderNamePlaceholder:`e.g., Functional Parts`,renameFile:`Rename File`,renameFolder:`Rename Folder`,invalidFilenameChar:`The character "{{char}}" is not allowed in print filenames. The printer SD card rejects: < > : " / \\ | ? *`,moveFiles:`Move {{count}} File(s)`,rootNoFolder:`Root (No Folder)`,current:`current`,linkFolder:`Link Folder`,linkFolderDescription:`Link "{{name}}" to a project or archive for quick access.`,project:`Project`,archive:`Archive`,noProjectsFound:`No projects found`,noArchivesFound:`No archives found`,unlink:`Unlink`,link:`Link`,dragDropFiles:`Drag & drop files here`,dropFilesHere:`Drop files here`,releaseToUpload:`Release to upload`,orClickToBrowse:`or click to browse`,allFileTypesSupported:`All file types supported. ZIP files will be extracted.`,zipFilesDetected:`ZIP files detected`,zipExtractOptions:`ZIP files will be extracted. Choose how to handle folder structure:`,preserveZipStructure:`Preserve folder structure from ZIP`,createFolderFromZip:`Create folder from ZIP filename`,stlThumbnailGeneration:`STL thumbnail generation`,zipMayContainStl:`ZIP files may contain STL files. Thumbnails can be generated during extraction.`,thumbnailsCanBeGenerated:`Thumbnails can be generated for STL files. Large models may take longer to process.`,generateThumbnailsForStl:`Generate thumbnails for STL files`,threemfDetected:`3MF files detected`,threemfExtractionInfo:`Printer model, material, color, and print settings will be automatically extracted from 3MF files.`,willBeExtracted:`Will be extracted`,filesExtracted:`{{count}} files extracted`,uploadComplete:`Upload complete: {{succeeded}} succeeded`,uploadFailed:`Upload failed`,zipFilesFailed:`{{count}} files failed`,uploading:`Uploading...`,changeLink:`Change Link...`,linkTo:`Link to...`,linkToProjectOrArchive:`Link to project or archive`,generateThumbnail:`Generate Thumbnail`,generateThumbnails:`Generate Thumbnails`,generateThumbnailsForMissing:`Generate thumbnails for STL files missing them`,gridView:`Grid view`,listView:`List view`,lowDiskSpaceWarning:`Low disk space warning`,lowDiskSpaceDetails:`Only {{free}} free of {{total}} total. Threshold is set to {{threshold}} GB in settings.`,files:`Files`,folders:`Folders`,size:`Size`,free:`Free`,allFiles:`All Files`,allExternal:`External`,externalIsEmpty:`No external files`,externalEmptyDescription:`Files in your linked external folders will appear here.`,wrap:`Wrap`,enableTextWrapping:`Enable text wrapping`,disableTextWrapping:`Disable text wrapping`,collapse:`Collapse`,collapseFoldersByDefault:`Collapse folders by default`,expandFoldersByDefault:`Expand folders by default`,folderSort:`Sort folders`,folderSortByName:`By name`,folderSortByActivity:`By recent activity`,dragToResizeTooltip:`Drag to resize, double-click to reset`,searchFiles:`Search files...`,searchSubfoldersHint:`Including subfolders`,readme:{truncated:`Truncated`,show:`Show README`,hide:`Hide README`,label:`README`},tags:{title:`Tags`,subtitle:`Label files for cross-cutting filtering — toys, kid-safe, PETG-only, anything.`,manage:`Tags`,manageTitle:`Manage tag catalog`,add:`New tag`,edit:`Rename tag`,name:`Name`,fileCount:`Files`,empty:`No tags yet. Create one to start labelling files.`,noMatches:`No matching tags.`,createPlaceholder:`e.g. toys, kid-safe, petg`,createButton:`Create`,nameRequired:`Name is required.`,searchPlaceholder:`Filter tags...`,created:`Tag created.`,updated:`Tag renamed.`,deleted:`Tag removed.`,saveFailed:`Could not save tag.`,deleteFailed:`Could not remove tag.`,applyFailed:`Could not apply tags.`,applyAdd:`Add tags`,applyRemove:`Remove tags`,applyAddSuccess:`Added {{count}} tag(s) across {{files}} file(s).`,applyRemoveSuccess:`Removed {{count}} tag(s) across {{files}} file(s).`,actionAdd:`Add to selected files`,actionRemove:`Remove from selected files`,tagAction:`Tag`,bulkTitle:`Tag {{count}} selected file(s)`,bulkTooltip:`Add or remove tags on every selected file.`,noPermission:`You do not have permission to tag files.`,filterLabel:`Filtering by:`,clearAll:`Clear all`,confirmDelete:`Delete tag "{{name}}"?`,confirmDeleteMessage:`This removes the tag from the catalog. Files keep their other tags.`,confirmDeleteInUseMessage:`This tag is on {{count}} file(s). Deleting removes the chip from all of them; files themselves are untouched.`,editAria:`Edit {{name}}`,deleteAria:`Delete {{name}}`},allTypes:`All types`,prints:`Prints`,ascending:`Ascending`,descending:`Descending`,showModified:`Show modified dates`,hideModified:`Hide modified dates`,lastModified:`Last modified`,lastActivity:`Last activity`,resultsCount:`{{showing}} of {{total}} files`,selectAll:`Select All`,deselectAll:`Deselect All`,selected:`{{count}} selected`,adding:`Adding...`,loadingFiles:`Loading files...`,folderIsEmpty:`Folder is empty`,noFilesYet:`No files yet`,folderEmptyDescription:`Upload files or move files into this folder to get started.`,noFilesDescription:`Upload files to start organizing your print-related files.`,noMatchingFiles:`No matching files`,noMatchingFilesDescription:`No files match your current search or filter criteria.`,clearFilters:`Clear filters`,printedCount:`Printed {{count}}x`,uploadedBy:`Uploaded By`,deleteFolder:`Delete Folder`,deleteFile:`Delete File`,deleteFilesCount:`Delete {{count}} Files`,deleteFolderConfirm:`Are you sure you want to delete this folder? All files inside will also be deleted.`,deleteFileConfirm:`Are you sure you want to delete this file?`,deleteFilesConfirm:`Are you sure you want to delete {{count}} selected files? This action cannot be undone.`,deleting:`Deleting...`,noPermissionRenameFolder:`You do not have permission to rename folders`,noPermissionLinkFolder:`You do not have permission to link folders`,noPermissionDeleteFolder:`You do not have permission to delete folders`,onlyEmptyFoldersDeletable:`You can only delete empty folders`,noPermissionPrint:`You do not have permission to print`,noPermissionAddToQueue:`You do not have permission to add to queue`,noPermissionSlice:`You do not have permission to slice files`,noPermissionDownload:`You do not have permission to download files`,noPermissionRenameFile:`You do not have permission to rename this file`,noPermissionGenerateThumbnail:`You do not have permission to generate thumbnails`,noPermissionDeleteFile:`You do not have permission to delete this file`,noPermissionCreateFolder:`You do not have permission to create folders`,noPermissionUpload:`You do not have permission to upload files`,noPermissionMoveFiles:`You do not have permission to move files`,noPermissionDeleteFiles:`You do not have permission to delete files`,linkExternal:`Link External`,linkExternalFolder:`Link External Folder`,linkExternalFolderDescription:`Mount a host directory (NAS, USB, network share) into the File Manager. Files are not copied — they are accessed directly from the original path.`,externalFolderNamePlaceholder:`e.g., NAS Prints`,externalPath:`Host Path`,externalPathHelp:`Absolute path to the directory on the Docker host. Must be bind-mounted into the container.`,readOnly:`Read Only`,readOnlyHelp:`prevents uploads and deletions`,showHiddenFiles:`Show hidden files (dotfiles)`,externalFolder:`External Folder`,scanFolder:`Scan`,toast:{folderCreated:`Folder created`,folderDeleted:`Folder deleted`,fileDeleted:`File deleted`,filesDeleted:`Deleted {{count}} files`,filesMoved:`Files moved`,folderLinked:`Folder linked`,folderUnlinked:`Folder unlinked`,externalFolderLinked:`External folder linked and scanned`,folderScanned:`Scan complete: {{added}} added, {{removed}} removed`,addedToQueue:`Added {{count}} file(s) to queue`,addedToQueuePartial:`Added {{added}} file(s), {{failed}} failed`,failedToAddToQueue:`Failed to add files: {{error}}`,fileRenamed:`File renamed`,folderRenamed:`Folder renamed`,thumbnailsGenerated:`Generated {{count}} thumbnail(s)`,thumbnailsGeneratedPartial:`Generated {{succeeded}} thumbnail(s), {{failed}} failed`,noStlMissingThumbnails:`No STL files missing thumbnails`,failedToGenerateThumbnails:`Failed to generate thumbnails: {{error}}`,thumbnailGenerated:`Thumbnail generated`,failedToGenerateThumbnail:`Failed to generate thumbnail: {{error}}`}},projects:{title:`Projects`,subtitle:`Organize and track your 3D printing projects`,newProject:`New Project`,editProject:`Edit Project`,deleteProject:`Delete Project`,projectName:`Project Name`,description:`Description`,noProjects:`No projects yet`,noProjectsFiltered:`No {{status}} projects`,noProjectsFilteredHelp:`You don't have any {{status}} projects. Projects will appear here when their status changes.`,createFirst:`Create your first project to start organizing related prints, tracking progress, and managing your builds.`,createFirstButton:`Create Your First Project`,create:`Create`,files:`Files`,prints:`Prints`,plates:`plates`,parts:`parts`,lastModified:`Last Modified`,deleteConfirm:`Are you sure you want to delete this project? Archives and queue items will be unlinked but not deleted.`,addFiles:`Add Files`,removeFile:`Remove File`,viewDetails:`View Details`,namePlaceholder:`e.g., Voron 2.4 Build`,descriptionPlaceholder:`Optional description...`,urlLabel:`URL`,urlPlaceholder:`https://makerworld.com/...`,urlInvalid:`URL must start with http:// or https://`,openExternalUrl:`Open project URL`,coverImageLabel:`Cover photo`,coverImageAlt:`Project cover photo`,coverImageUpload:`Upload`,coverImageReplace:`Replace`,coverImageRemove:`Remove`,color:`Color`,targetPlates:`Target Plates`,targetPlatesPlaceholder:`e.g., 25`,targetPlatesHelp:`Number of print jobs`,targetParts:`Target Parts`,targetPartsPlaceholder:`e.g., 150`,targetPartsHelp:`Total objects needed`,targetSets:`Copies per File`,targetSetsPlaceholder:`e.g., 10`,targetSetsHelp:`Times each printable file should be printed`,tagsLabel:`Tags (comma-separated)`,tagsPlaceholder:`e.g., voron, functional, gift`,dueDate:`Due Date`,priority:`Priority`,priorityLow:`Low`,priorityNormal:`Normal`,priorityHigh:`High`,priorityUrgent:`Urgent`,statusActive:`Active`,statusCompleted:`Completed`,statusArchived:`Archived`,done:`Done`,completed:`completed`,failed:`failed`,inQueue:`in queue`,noPrintsYet:`No prints yet`,printJobs:`Print jobs (plates)`,partsPrinted:`Parts printed`,failedParts:`Failed parts`,import:`Import`,export:`Export`,importProject:`Import project`,exportAll:`Export all projects`,loading:`Loading projects...`,noEditPermission:`You do not have permission to edit projects`,noDeletePermission:`You do not have permission to delete projects`,noCreatePermission:`You do not have permission to create projects`,noImportPermission:`You do not have permission to import projects`,noExportPermission:`You do not have permission to export projects`,toast:{created:`Project created`,updated:`Project updated`,deleted:`Project deleted`,imported:`Project imported`,multipleImported:`{{count}} projects imported`,importFailed:`Import failed`,exported:`Projects exported (metadata only)`}},projectDetail:{notFound:`Project not found`,backToProjects:`Back to Projects`,export:`Export`,exportProject:`Export project`,noExportPermission:`You do not have permission to export projects`,noEditPermission:`You do not have permission to edit projects`,partOf:`Part of:`,priorityLabel:`Priority:`,noPrints:`No prints in this project yet`,status:{active:`Active`,completed:`Completed`,archived:`Archived`},priority:{low:`Low`,normal:`Normal`,high:`High`,urgent:`Urgent`},dueDate:{overdue:`Overdue`,today:`Due today`,daysLeft:`{{count}} days left`},progress:{platesProgress:`Plates Progress`,partsProgress:`Parts Progress`,setsProgress:`Complete Sets`,sets:`sets`,setsHint:`A set is complete once every printable file has reached this count`,printJobs:`print jobs`,parts:`parts`,percentComplete:`{{percent}}% complete`,remaining:`{{count}} remaining`},stats:{printJobs:`Print Jobs`,total:`total`,failed:`{{count}} failed`,partsPrinted:`{{count}} parts printed`,printTime:`Print Time`,filamentUsed:`Filament Used`},cost:{title:`Cost Tracking`,filamentCost:`Filament Cost`,energy:`Energy`,totalCost:`Total Cost`,total:`Total`,includesBom:`incl. BOM`,budget:`Budget`,remaining:`Remaining`},subProjects:{title:`Sub-projects ({{count}})`},notes:{title:`Notes`,noEditPermission:`You do not have permission to edit notes`,placeholder:`Add notes about this project...`,empty:`No notes yet. Click Edit to add notes.`},files:{title:`Files`,linkFolders:`Link folders from the File Manager`,forQuickAccess:`to this project for quick access.`,fileCount:`{{count}} file(s)`,empty:`No folders linked. Go to File Manager and link a folder to this project.`,printedCount:`Printed {{count}} time(s)`,progressTooltip:`{{done}} of {{target}} completed prints`,noFiles:`No files in this folder.`},bom:{title:`Bill of Materials`,acquired:`{{completed}}/{{total}} acquired`,showAll:`Show all`,hideDone:`Hide done`,addPart:`Add Part`,noAddPermission:`You do not have permission to add parts`,partNamePlaceholder:`Part name (e.g., M3x8 screws)`,partName:`Part name`,qty:`Qty`,price:`Price ({{currency}})`,sourcingUrlPlaceholder:`Sourcing URL (optional)`,remarksPlaceholder:`Remarks (optional)`,deletePart:`Delete Part`,deleteConfirm:`Are you sure you want to delete "{{name}}"?`,noUpdatePermission:`You do not have permission to update parts`,noEditPermission:`You do not have permission to edit parts`,noDeletePermission:`You do not have permission to delete parts`,totalCost:`Total cost:`,empty:`No parts in the bill of materials. Add hardware, electronics, or other components to track what needs to be sourced.`},timeline:{title:`Activity Timeline`,empty:`No activity yet.`},template:{saveAsTemplate:`Save as Template`,noCreatePermission:`You do not have permission to create templates`},queue:{title:`Queue`,viewAll:`View all`,printing:`{{count}} printing`,queued:`{{count}} queued`},prints:{title:`Prints ({{count}})`},toast:{projectUpdated:`Project updated`,partAdded:`Part added`,partRemoved:`Part removed`,exportFailed:`Export failed`,projectExported:`Project exported`,templateCreated:`Template created`}},system:{title:`System Information`,version:`Version`,uptime:`Uptime`,cpuUsage:`CPU Usage`,memoryUsage:`Memory Usage`,diskUsage:`Disk Usage`,networkInfo:`Network Info`,logs:`Logs`,debugMode:`Debug Mode`,enableDebug:`Enable Debug Logging`,disableDebug:`Disable Debug Logging`,downloadLogs:`Download Logs`,clearLogs:`Clear Logs`,dockerInfo:`Docker Info`,containerName:`Container Name`,imageName:`Image Name`,platform:`Platform`,architecture:`Architecture`},sponsors:{sectionTitle:`Independent & community-funded`,tagline:`Bambuddy is free and stays that way because people choose to support it. No VC, no cloud lock-in.`,viewSupporters:`View supporters`,toastPrints:`You've completed {{count}} prints with Bambuddy. Bambuddy stays free thanks to its supporters.`,toastCost:`You've tracked {{total}} in filament with Bambuddy. See who keeps the project independent.`,toastArchives:`{{count}} prints archived with Bambuddy. See who keeps it independent.`,toastAnniversary:`One year with Bambuddy! See who keeps the project independent.`,toastVersionUpdate:`Updated to v{{version}}. Bambuddy stays free thanks to its supporters.`,toastBusiness:`Running Bambuddy on {{count}} printers? There's a support plan for teams — priority fixes, invoicing, and a direct line to the maintainer.`,businessCta:`Bambuddy for business`,businessTitle:`Bambuddy for business`,businessTagline:`You're running {{count}} printers. Priority support, commercial licensing and invoicing are available for teams and print farms.`},library:{title:`Filament Library`,addFilament:`Add Filament`,editFilament:`Edit Filament`,deleteFilament:`Delete Filament`,vendor:`Vendor`,material:`Material`,color:`Color`,kFactor:`K Factor`,temperature:`Temperature`,noFilaments:`No filaments in library`,deleteConfirm:`Are you sure you want to delete this filament?`,importFromPrinter:`Import from Printer`,exportToFile:`Export to File`,runWithPipeline:{actionLabel:`Run with pipeline`,noPermission:`You do not have permission to run pipelines`,modalTitle:`Run with pipeline`,confirmTitle:`Confirm run`,confirmIntro:`Pre-flight found issues with this run`,sourceHint:`Source`,pipelineHint:`Pipeline`,targetHint:`Target`,pipelineListAria:`Available pipelines`,runAnyway:`Run anyway`,loading:`Loading…`,empty:`No pipelines saved yet. Open the Slice dialog and click "Save as pipeline" to create one.`,noTarget:`No target printer set`,noTargetMessage:`This pipeline has no target printer set. Open it in Settings to pick one.`,copies:`Copies`,copiesHint:`max {{n}}`,classTarget:`Any {{model}}`,toast:{started:`Pipeline run started`,failed:`Could not start run`},issue:{printerNotSet:`No target printer set on this pipeline.`,printerNotFound:`Target printer no longer exists.`,printerDisabled:`Target printer is disabled.`,printerOffline:`Target printer is offline.`,filamentType:`Filament slot {{slot}}: expected {{expected}}, AMS has {{actual}}`,filamentColor:`Filament slot {{slot}}: colour differs (expected {{expected}}, AMS has {{actual}})`,amsSlotMissing:`AMS slot {{slot}} not available on this printer`,filamentUnverified:`Filament slot {{slot}} comes from a cloud / standard preset and could not be statically verified.`,noClassMatches:`No printers in this install match the pipeline's target model class ({{expected}}).`,classNotSet:`Pipeline target is set to a printer class but no model was chosen.`}}},slice:{title:`Slice model`,action:`Slice`,actionAll:`Slice all {{count}} plates`,actionAllTitle:`Slice every plate into one multi-plate output (single archive). Filament selection covers every slot the project defines.`,allPlatesToggle:`Slice all {{count}} plates`,slicing:`Slicing…`,printer:`Printer profile`,process:`Process profile`,filament:`Filament profile`,filamentSlot:`Filament {{index}} ({{type}})`,selectPreset:`— Select a preset —`,loadingPresets:`Loading presets…`,analyzingPlateFilaments:`Analyzing plate filaments…`,analyzingPlateFilamentsHint:`Running a preview slice to discover which AMS slots this plate uses. Cached after — re-opening is instant.`,previewToast:`Analyzing {{name}} — {{elapsed}}`,previewWithProgress:`Analyzing {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}`,notUsedByPlate:`— not used by this plate`,noPresetsForSlot:`No presets available`,otherPrinters:`Other printers`,presetsLoadFailed:`Failed to load presets. Open Settings → Profiles to import them first.`,refreshPresets:`Refresh`,refreshPresetsTitle:`Refresh presets — fetch the latest cloud and bundled listings (use after deleting a preset in Bambu Studio or Bambu Handy)`,allPresetsRequired:`All presets must be selected`,useEmbedded:`Use the file's built-in settings`,useEmbeddedHint:`Slice it the way the designer set it up (walls, infill, filament) instead of the profiles above. Offered because your printer matches the file's.`,designSettings:`Keep the designer's settings`,designSettingsHint:`This file changes {{count}} print setting(s) from the stock profile.`,designSettingsSelected:`{{selected}} of {{total}} selected`,designSettingsPrinterCoupled:`printer-specific`,designSettingsPrinterCoupledHint:`Tuned for the printer this file was designed for — may be wrong or out of range on yours.`,enqueuing:`Submitting slice job…`,queued:`Queued…`,failed:`Slicing failed. Check the slicer sidecar logs.`,startedToast:`Slicing {{name}} in the background…`,queuedToast:`Queued: {{name}} — {{elapsed}}`,runningToast:`Slicing {{name}} — {{elapsed}}`,runningWithProgress:`{{name}} — {{stage}} ({{percent}}%) — {{elapsed}}`,runningWithProgressMultiPlate:`Plate {{plateIndex}} of {{plateCount}} • {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}`,completedToast:`Sliced {{name}}`,failedTitle:`Slicing failed`,failedToast:`Slicing {{name}} failed: {{detail}}`,tier:{local:`Imported`,cloud:`Bambu Cloud`,orcaCloud:`Orca Cloud`,standard:`Standard`},cloud:{notAuthenticated:`Sign in to Bambu Cloud (Settings → Profiles → Bambu Cloud) to see your cloud presets.`,expired:`Bambu Cloud session expired — sign in again to refresh your cloud presets.`,unreachable:`Bambu Cloud is unreachable right now. Local and standard presets still work.`},orcaCloud:{notAuthenticated:`Sign in to Orca Cloud (Profiles → Orca Cloud) to see your Orca presets.`,expired:`Orca Cloud session expired — sign in again to refresh your Orca presets.`,unreachable:`Orca Cloud is unreachable right now. Other presets still work.`},bedType:{label:`Build plate`,auto:`Auto (use process preset)`,coolPlate:`Cool Plate`,coolPlateSuperTack:`Cool Plate SuperTack`,engineering:`Engineering Plate`,highTemp:`High Temp Plate`,texturedPEI:`Textured PEI Plate`,smoothPEI:`Smooth PEI Plate`},pipelines:{label:`Pipeline`,applyAria:`Apply pipeline`,applyPrompt:`Apply pipeline…`,empty:`No saved pipelines`,saveButton:`Save as pipeline`,saveTitle:`Save the current four-slot selection as a reusable pipeline`,namePlaceholder:`Pipeline name`,nameAria:`New pipeline name`,toast:{applied:`Applied "{{name}}"`,saved:`Pipeline saved`,saveFailed:`Save failed`}}},spoolman:{title:`Spoolman Integration`,enabled:`Spoolman Enabled`,url:`Spoolman URL`,connected:`Connected`,disconnected:`Not Connected`,testConnection:`Test Connection`,sync:`Sync`,syncing:`Syncing...`,lastSync:`Last Sync`,linkToSpoolman:`Link to Spoolman`,openInSpoolman:`Open in Spoolman`,unlinkSpool:`Unlink Spool`,unlinkConfirmTitle:`Unassign Spool?`,unlinkConfirmMessage:`This will remove the spool from this slot. The spool data itself will remain unchanged.`,selectSpool:`Select Spool`,noUnlinkedSpools:`No unassigned spools available`,linkSuccess:`Spool assigned successfully`,linkFailed:`Failed to assign spool`,unlinkSuccess:`Spool unassigned successfully`,unlinkFailed:`Failed to unassign spool`,linkedSpool:`Assigned spool`,spoolId:`Spool ID`,fillSourceLabel:`(Spoolman)`,weight:`Weight`,remaining:`Remaining`,disableWeightSync:`Disable AMS Estimated Weight Sync`,disableWeightSyncDesc:`Don't update remaining capacity from AMS estimates. Use this if you prefer Spoolman's usage tracking over AMS percentage-based estimates. New spools will still use the AMS estimate as their initial weight.`,reportPartialUsage:`Report Partial Usage for Failed Prints`,reportPartialUsageDesc:`When a print fails or is cancelled, report the estimated filament used up to that point based on layer progress.`},locations:{title:`Storage Locations`,subtitle:`Manage shelves, drawers, and other physical storage spots for your spools`,add:`Add Location`,addShort:`Add`,edit:`Edit Location`,name:`Name`,spools:`Spools`,empty:`No storage locations yet. Create your first shelf or drawer.`,manage:`Locations`,createPlaceholder:`e.g. Shelf A, Drawer 1`,nameRequired:`Location name is required`,created:`Location created`,updated:`Location updated`,deleted:`Location deleted`,saveFailed:`Failed to save location`,deleteFailed:`Failed to delete location`,deleteBlocked:`Remove all spools from this location before deleting`,confirmDelete:`Delete "{{name}}"?`,confirmDeleteMessage:`This location will be removed from the catalog. Spools must be moved first.`},inventory:{title:`Spool Inventory`,subtitle:`Manage your spools`,addToInventory:`Add to Inventory`,addToInventoryPending:`Adding...`,addToInventorySuccess:`Spool added to inventory`,addToInventoryFailed:`Failed to add spool to inventory`,unknownSpoolTitle:`New filament detected`,unknownSpoolMessage:`A spool with an unknown RFID tag was detected at {{location}}. Add it to your inventory now?`,unknownSpoolSlot:`Slot`,bulk:{selectAllVisible:`Select all visible`,selectRow:`Select row`,selectGroup:`Select group`,selectionCount:`{{count}} selected`,edit:`Edit`,printLabels:`Print labels`,resetUsage:`Reset usage`,restore:`Restore`,archive:`Archive`,delete:`Delete`,clearSelection:`Clear selection`,editTitle:`Bulk edit spools`,editSubtitle:`Applies to {{count}} selected spools. Only fields you tick get updated.`,editHint:`Type into a field to mark it for update — only ticked rows are sent. Leaving a field empty leaves the spools unchanged (clearing fields is per-spool only).`,useCustom:`Use "{{value}}"`,toggleField:`Toggle update for this field`,changeCount:`{{count}} fields will be updated.`,applyPending:`Applying...`,applyButton:`Apply to {{count}} spools`,deleteTitle:`Delete selected spools`,archiveTitle:`Archive selected spools`,restoreTitle:`Restore selected spools`,resetUsageTitle:`Reset usage on selected spools`,deleteMessage:`Permanently delete {{count}} spools? This cannot be undone.`,archiveMessage:`Archive {{count}} spools? They can be restored later.`,restoreMessage:`Restore {{count}} archived spools?`,resetUsageMessage:`Reset the "Total Consumed" counter on {{count}} spools? Remaining weight is preserved.`,updateSuccess:`{{count}} spools updated`,updateFailed:`Bulk update failed`,updatePartial:`{{ok}} spools updated, {{failed}} failed`,updateAllFailed:`All {{count}} spool updates failed — selection kept so you can retry`,deleteSuccess:`{{count}} spools deleted`,deleteFailed:`Bulk delete failed`,deletePartial:`{{ok}} spools deleted, {{failed}} failed`,deleteAllFailed:`All {{count}} spool deletions failed — selection kept so you can retry`,archiveSuccess:`{{count}} spools archived`,archiveFailed:`Bulk archive failed`,archivePartial:`{{ok}} spools archived, {{failed}} failed`,archiveAllFailed:`All {{count}} spool archives failed — selection kept so you can retry`,restoreSuccess:`{{count}} spools restored`,restoreFailed:`Bulk restore failed`,restorePartial:`{{ok}} spools restored, {{failed}} failed`,restoreAllFailed:`All {{count}} spool restores failed — selection kept so you can retry`,invalidHex:`Enter 6 hex characters (RRGGBB) or 8 (RRGGBBAA). The field will not be applied otherwise.`},spoolmanMixedContentTitle:`Spoolman can't load over HTTPS — mixed-content blocked by your browser`,spoolmanMixedContentBody:`Bambuddy is served over HTTPS (via your reverse proxy), but your Spoolman URL is still plain HTTP. Browsers block mixed content for security, so the embedded Spoolman UI can't render. Spoolman needs to be reachable over HTTPS for this to work.`,spoolmanMixedContentFixReverseProxy:`Put Spoolman behind the same reverse proxy as Bambuddy (Traefik / Nginx / Caddy) with HTTPS, then update the Spoolman URL in Settings to the new HTTPS address.`,spoolmanMixedContentFixOpenNewTab:`As a workaround, open Spoolman in a new browser tab over HTTP — mixed-content rules only apply to embedded frames, so a standalone tab still works.`,spoolmanOpenInNewTab:`Open Spoolman in a new tab`,labels:{title:`Print spool labels`,selectedCount:`{{count}} selected`,pickSpools:`Pick which spools to print labels for:`,monochrome:`Monochrome (black & white printer)`,monochromeHint:`Drops the colour swatch and widens the text`,searchPlaceholder:`Search name, brand, or #ID`,filterByMaterial:`Material:`,allMaterials:`All`,selectVisible:`Select all visible ({{count}})`,deselectVisible:`Deselect visible`,clearAll:`Clear all`,noSpoolsToShow:`No spools to show. Adjust your filter and try again.`,noMatches:`No spools match the current search or filter.`,printOne:`Print label for this spool`,printLabels:`Print labels…`,bulkTitle:`Pick spools to print labels for from the {{count}} currently shown`,noSpoolsTitle:`No spools to label`,error:`Could not generate labels: {{msg}}`,sortBy:{label:`Sort:`,id:`By ID`,color:`By colour`},templates:{amsHolderSmall:{label:`AMS holder — small (74 × 33 mm)`,hint:`Single label per page; matches the printable label from MakerWorld model 752566 (AMS Filament Label Holder).`},amsHolderLarge:{label:`AMS holder — large (75 × 55 mm)`,hint:`Single label per page; fits the cardstock-insert variant of the AMS Filament Label Holder. Roomy enough for swatch, brand, material, ID, and QR code.`},box40x30:{label:`Box label (40 × 30 mm)`,hint:`Single label per page; common DK/Brother roll size, good for filament-bag and storage-bin labels.`},box:{label:`Box label (62 × 29 mm)`,hint:`Single label per page; sized for Brother PT/QL and Dymo small labels.`},averyL7160:{label:`Avery L7160 — A4 sheet (38.1 × 63.5 mm × 21)`,hint:`EU sheet stock; 21 labels per A4 page.`},avery5160:{label:`Avery 5160 — US Letter sheet (25.4 × 66.7 mm × 30)`,hint:`US sheet stock; 30 labels per Letter page.`}}},csv:{importButton:`Import CSV`,exportButton:`Export CSV`,modalTitle:`Import spools from CSV`,selectFile:`Choose a CSV file or drag it here`,dragHint:`Header: material (required), brand, subtype, color_name, rgba, …`,parsing:`Reading file…`,previewError:`Could not read the CSV file`,validCount:`{{count}} valid`,errorCount:`{{count}} error`,skippedCount:`{{count}} skipped`,colRow:`Row`,colStatus:`Status`,colColor:`Color`,colorResolved:`Color filled from catalog`,colorCrossMaterial:`Color taken from a different material — no exact match in catalog`,duplicateExisting:`A spool with this material, brand and color already exists — it will still be imported as a new spool`,spoolmanHint:`In Spoolman mode, use Spoolman's built-in CSV import/export.`,importValidRows:`Import {{count}} valid rows`,noValidRows:`No valid rows`,importing:`Importing…`,importSuccess:`{{count}} spools imported`,importError:`Import failed`,exportError:`Export failed`},addSpool:`Add Spool`,editSpool:`Edit Spool`,copySpool:`Copy Spool`,material:`Material`,selectMaterial:`Select material...`,subtype:`Subtype`,brand:`Brand`,searchBrand:`Search brand...`,useCustomBrand:`Use "{{brand}}"`,useCustomMaterial:`Use custom material: {{material}}`,suggestedOptions:`Suggested`,allOptions:`All`,colorName:`Color Name`,colorNamePlaceholder:`Jade White, Fire Red...`,color:`Color`,hexColor:`Hex Color`,pickColor:`Pick custom color`,labelWeight:`Label Weight`,coreWeight:`Empty Spool Weight`,searchSpoolWeight:`Search spool weight...`,weightUsed:`Used`,currentWeight:`Remaining Weight`,measuredWeight:`Measured Weight`,spoolName:`Spool`,costPerKg:`Cost per kg`,storageLocation:`Storage Location`,storageLocationPlaceholder:`e.g. Shelf A, Drawer 1`,openInInventory:`Open in Inventory`,measuredWeightError:`Measured weight must be between {{min}}g and {{max}}g.`,slicerFilament:`Slicer Filament`,slicerFilamentName:`Slicer Preset Name`,slicerPreset:`Slicer Preset`,searchPresets:`Search filament presets...`,selectedPreset:`Selected`,noPresetsFound:`No presets found`,tempOverrides:`Temperature Overrides`,note:`Note`,notePlaceholder:`Any additional notes about this spool...`,category:`Category`,categoryPlaceholder:`e.g. Production, Prototype, Client A`,categoryNone:`Uncategorized`,storageLocationNone:`No location set`,lowStockThresholdOverride:`Low-stock threshold (this spool)`,lowStockThresholdOverrideHelp:`Leave blank to use the global threshold ({{global}}%).`,clearRfid:`Clear RFID Tag`,rfidCleared:`RFID tag cleared`,archive:`Archive`,restore:`Restore`,noSpools:`No spools yet. Add your first spool to get started.`,noAvailableSpools:`No spools available. Add a spool to your inventory or unassign one from another slot first.`,kProfiles:`K-Profiles`,addKProfile:`Add K-Profile`,assignSpool:`Assign Spool`,unassignSpool:`Unassign`,assignSuccess:`Spool assigned and AMS slot configured`,assignPendingInsert:`Assigned. Slot will configure when you insert the spool.`,assignFailed:`Failed to assign spool`,selectSpool:`Select a spool to assign to this slot`,assigned:`Assigned`,assigning:`Assigning...`,searchSpools:`Search spools...`,showAllSpools:`Show all spools`,spoolmanSpools:`Spoolman Spools`,allMaterials:`All Materials`,filterByBrand:`Filter by brand...`,showArchived:`Show archived`,quickAdd:`Quick Add (Stock)`,quantity:`Quantity`,stock:`Stock`,configured:`Configured`,spoolsCreated:`{{count}} spools created`,spoolsPartiallyCreated:`{{created}} of {{total}} spools created (some failed)`,spoolCreated:`Spool created`,spoolUpdated:`Spool updated`,spoolDeleted:`Spool deleted`,deepLinkSpoolNotFound:`Spool not found`,deepLinkFetchFailed:`Could not load spool — try again`,spoolArchived:`Spool archived`,spoolRestored:`Spool restored`,kProfileSaveFailed:`K-profile settings could not be saved`,syncWeightSpoolNotFound:`Spool not found — it may have been deleted`,syncWeightSpoolmanUnreachable:`Spoolman is unreachable — try again later`,syncWeightFailed:`Failed to sync weight`,spoolmanUnreachable:`Spoolman is not reachable — please try again later`,deleteSpoolNotFound:`Spool not found — it may have already been deleted`,deleteFailed:`Failed to delete spool`,archiveSpoolNotFound:`Spool not found — it may have already been deleted`,archiveFailed:`Failed to archive spool`,restoreSpoolNotFound:`Spool not found — it may have already been deleted`,restoreFailed:`Failed to restore spool`,saveFailed:`Failed to save changes`,tagClearFailed:`Failed to clear tag`,deleteConfirm:`Are you sure you want to delete this spool? This cannot be undone.`,archiveConfirm:`Are you sure you want to archive this spool?`,advancedSettings:`Advanced Settings`,filamentInfoTab:`Filament Info`,paProfileTab:`PA Profile`,filamentInfo:`Filament`,additional:`Additional`,loadingPresets:`Loading cloud presets...`,cloudConnected:`Cloud connected`,cloudNotConnected:`Cloud not connected (using defaults)`,recentColors:`Recent`,searchColors:`Search colors...`,searchResults:`Search results`,allColors:`All colors`,commonColors:`Common colors`,showLess:`Show less`,showAll:`Show all`,noColorsFound:`No colors match your search`,noResults:`No matches found`,extraColorsLabel:`Extra colors`,extraColorsPlaceholder:`EC984C,#6CD4BC,A66EB9,D87694`,extraColorsHint:`Paste 2 to 8 hex stops, separated by commas. Renders as a gradient.`,extraColorsInvalid:`Ignored invalid hex: {{tokens}}`,colorEffectLabel:`Effect`,colorEffect:{none:`None`,sparkle:`Sparkle`,wood:`Wood`,marble:`Marble`,glow:`Glow`,matte:`Matte`,silk:`Silk`,galaxy:`Galaxy`,rainbow:`Rainbow`,metal:`Metal`,translucent:`Translucent`,gradient:`Gradient`,dualColor:`Dual Color`,triColor:`Tri Color`,multicolor:`Multicolor`},selectMaterialFirst:`Please select a material first in the Filament Info tab.`,noPrintersConfigured:`No printers configured. Add printers to use PA profiles.`,matchingFilter:`Matching`,anyBrand:`Any brand`,anyVariant:`Any variant`,autoSelect:`Auto-select`,matches:`matches`,match:`match`,noMatches:`No matches`,connected:`Connected`,offline:`Offline`,printerOffline:`Printer is offline. Connect to view calibration profiles.`,noKProfilesMatch:`No K-profiles match the selected filament.`,leftNozzle:`Left Nozzle`,rightNozzle:`Right Nozzle`,profilesSelected:`calibration profile(s) selected`,totalInventory:`Total Inventory`,totalConsumed:`Total Consumed`,byMaterial:`By Material`,inPrinter:`In Printer`,lowStock:`Low Stock`,sinceTracking:`Since tracking started`,resetConsumedCounter:`Reset counter`,resetConsumedCounterTooltip:`Zero the consumed-grams counter for this spool. Remaining weight is not changed.`,resetConsumedCounterConfirm:`Reset this spool's consumed-grams counter to 0? Future prints will track from zero again. The spool itself, its remaining weight calculation, and your settings are not changed.`,resetAllConsumedCounters:`Reset all counters`,resetAllConsumedCountersTooltip:`Zero the consumed-grams counter on every spool. Remaining weights are not changed.`,resetAllConsumedCountersConfirm:`Reset the consumed-grams counter to 0 on all {{count}} spools (archived ones included)? This clears the "Total Consumed" stat so future prints track from zero. Spools and remaining weights are not changed.`,consumedCounterReset:`Counter reset`,allConsumedCountersReset:`Counter reset for {{count}} spool(s)`,resetConsumedCounterFailed:`Failed to reset counter`,loadedInAms:`Loaded in AMS/Ext`,remaining:`Remaining`,weightCheck:`Weight Check`,lastWeighed:`Last weighed`,neverWeighed:`Never weighed`,search:`Search spools...`,showing:`Showing`,to:`to`,of:`of`,show:`Show`,spools:`spools`,spool:`spool`,page:`Page`,noSpoolsMatch:`No results found`,noSpoolsMatchDesc:`Try adjusting your search or filters to find what you're looking for.`,active:`Active`,archived:`Archived`,all:`All`,used:`Used`,new:`New`,clearFilters:`Clear filters`,table:`Table`,cards:`Cards`,net:`Net`,groupSimilar:`Group`,groupedSpools:`{{count}} identical spools`,groupedRows:`rows`,columns:`Columns`,configureColumns:`Configure Columns`,configureColumnsDesc:`Drag to reorder columns or use arrows. Toggle visibility with the eye icon.`,visible:`visible`,reset:`Reset`,cancel:`Cancel`,applyChanges:`Apply Changes`,moveUp:`Move up`,moveDown:`Move down`,hideColumn:`Hide column`,showColumn:`Show column`,linkToSpool:`Link to Spool`,tagLinked:`Tag linked to spool`,tagLinkFailed:`Failed to link tag`,tagAlreadyLinked:`Tag already linked to another spool`,unknownTag:`Unknown RFID tag detected`,usageHistory:`Usage History`,noUsageHistory:`No usage recorded yet`,printName:`Print Name`,weightConsumed:`Weight Consumed`,clearHistory:`Clear`,historyCleared:`Usage history cleared`,fillSourceLabel:`(Inv)`,lowStockThresholdError:`Threshold must be between 0.1 and 99.9`,assignMismatchTitle:`Material mismatch`,assignMismatchMessage:`The selected spool material "{{spoolMaterial}}" does not match the tray material "{{trayMaterial}}" for {{location}}. Assign anyway?`,assignMismatchConfirm:`Assign Anyway`,assignPartialMismatchMessage:`The spool material "{{spoolMaterial}}" is similar to but not exactly matching "{{trayMaterial}}" in {{location}}. Do you want to proceed?`,assignProfileMismatchMessage:`The spool profile "{{spoolProfile}}" does not match the tray profile "{{trayProfile}}" in {{location}}. Do you want to proceed?`,assignReconfigureNote:`The AMS slot will be reconfigured to use the spool's profile.`,spoolmanFilamentCatalog:`Spoolman Filament Catalog`,pickFromSpoolmanCatalog:`Pick from Spoolman catalog…`,spoolmanFilamentSelected:`Filament selected from Spoolman catalog`,spoolmanFilamentUnlinked:`Filament catalog link cleared`,noSpoolmanFilaments:`No filaments found in Spoolman catalog`,spoolmanFilamentColorSwatch:`Filament color`,spoolWeightManagedBySpoolman:`Empty spool weight is managed per filament type in Spoolman`,spoolmanCatalogLoadFailed:`Failed to load Spoolman filament catalog`},timelapse:{title:`Timelapse`,create:`Create Timelapse`,download:`Download`,delete:`Delete`,preview:`Preview`,frameRate:`Frame Rate`,quality:`Quality`,processing:`Processing...`,noTimelapses:`No timelapses available`},ams:{title:`AMS`,slot:`Slot`,empty:`Empty`,emptySlot:`Empty slot`,slotEmpty:`Empty`,slotUnconfigured:`?`,emptySlotReset:`No filament assigned`,unknown:`Unknown`,humidity:`Humidity`,temperature:`Temperature`,filamentType:`Filament Type`,filamentColor:`Color`,remaining:`Remaining`,history:`AMS History`,noHistory:`No history available`,configureSlot:`Configure Slot`,externalSpool:`External Spool`,profile:`Profile`,kFactor:`K Factor`,fill:`Fill`,configure:`Configure`,used:`used`,remainingUnit:`remaining`},printModal:{selectPrinter:`Select Printer`,selectPlate:`Select Plate`,filamentMapping:`Filament Mapping`,useArchiveMapping:`Mapping`,useArchiveMappingTooltip:`Select every slot from the AMS mapping saved with this archive (from the slicer), instead of matching by type/color.`,clickToChangeSlot:`Click to change slot assignment`,reRead:`Re-read`,plateN:`Plate {{n}}`,plateFilamentsUnreadable:`The filaments of a selected plate could not be read, so it can't be mapped. Deselect it to queue the others.`,totalCost:`Total cost:`,slotRemainingShort:` - {{grams}}g left`,printSettings:`Print Settings`,bedLeveling:`Bed Leveling`,flowCalibration:`Flow Calibration`,vibrationCalibration:`Vibration Calibration`,layerInspection:`First Layer Inspection`,timelapse:`Timelapse`,cancel:`Cancel`,noPrintersAvailable:`No printers available`,printerBusy:`Printer is busy`,printerOffline:`Printer is offline`,sameTypeDifferentColor:`Same type, different color`,filamentTypeNotLoaded:`Filament type not loaded`,whenToPrint:`When to print`,asap:`ASAP`,queue:`Queue`,schedule:`Schedule`,dateTime:`Date & Time`,invalidDateTime:`Please enter a valid date and time`,openCalendar:`Open calendar`,requireManualStart:`Require manual start`,requirePreviousSuccess:`Only start if previous print succeeded`,autoOffAfter:`Power off printer when done`,helpAsap:`Print will be added to the top of the queue and start as soon as an eligible printer is idle.`,helpSchedule:`Print will start at the scheduled time if the printer is idle. If busy, it will wait until the printer becomes available.`,helpQueue:`Print will be added to the back of the queue.`,leftNozzle:`L`,rightNozzle:`R`,leftNozzleTooltip:`Left nozzle`,rightNozzleTooltip:`Right nozzle`,filamentOverride:`Filament Override`,filamentOverrideHint:`Optionally override filaments for model-based assignment. The scheduler will match against your selected filaments instead of the original 3MF values.`,originalFilament:`Original`,overrideWith:`Override with`,resetToOriginal:`Reset to original`,insufficientFilamentTitle:`Not enough filament`,waitingForAmsStatus:`Waiting for AMS status from {{printer}}…`,insufficientFilamentMessage:`Some assigned spools have less filament remaining than this print needs:`,insufficientFilamentLine:`{{printer}} - {{slot}}: needs {{required}}g, remaining {{remaining}}g`,printAnyway:`Print anyway`,forceColorMatch:`Force color match`,staggerPrinterStarts:`Stagger printer starts`,staggerGroupSize:`Group size`,staggerInterval:`Interval (min)`,staggerPreview:`{{printers}} printers → {{groups}} groups of {{size}}, starting every {{interval}} min`,staggerLastGroup:`last group: {{count}}`,staggerTotal:`total: {{minutes}} min`,staggerToPrinters:`Stagger to {{count}} printers`,gcodeInjection:`Inject auto-print G-code`},backup:{includesEncryptionKey:`Local backups include the MFA encryption key file (DATA_DIR/.mfa_encryption_key) so a backup ZIP is self-contained. Treat the ZIP as sensitive — anyone with the file can decrypt the OIDC client secrets and TOTP secrets stored inside.`,title:`Backup & Restore`,createBackup:`Create Backup`,restoreBackup:`Restore Backup`,restoreDescription:`Replace all data from a backup file`,downloadBackup:`Download Backup`,uploadBackup:`Upload Backup`,lastBackup:`Last Backup`,autoBackup:`Auto Backup`,backupNow:`Backup Now`,restoreWarning:`Warning: Restoring a backup will overwrite all current data.`,includeArchives:`Include Archives`,includeSettings:`Include Settings`,includeProfiles:`Include Profiles`,backupSuccess:`Backup created successfully`,restoreSuccess:`Backup restored successfully`,backupFailed:`Backup failed`,restoreFailed:`Restore failed`,restoreNote:`Virtual Printer will be stopped during restore`,githubBackup:`Git Backup`,enabled:`Enabled`,cloudLoginRequired:`Bambu Cloud login required. Sign in under Profiles → Cloud Profiles to enable GitHub backup.`,cloudLoginRequiredShort:`Cloud login required`,githubDescription:`Automatically sync your profiles to a private GitHub repository for backup and version history.`,repoIsPrivate:`Repository is private — safe to back up to.`,repoIsPublicWarning:`Repository is PUBLIC. Bambuddy backups include MQTT credentials, Home Assistant tokens, Prometheus tokens, your Bambu Cloud email, and printer access codes via K-profiles. Saving is blocked until you make the repository private in your provider's settings.`,repoVisibilityUnknown:`Could not determine repository visibility. Bambuddy refuses to back up to anything not confirmed private; saving will be blocked.`,repositoryUrl:`Repository URL`,repoUrlPlaceholderGitHub:`https://github.com/username/repo-name`,repoUrlPlaceholderGitea:`https://gitea.example.com/username/repo-name`,repoUrlPlaceholderForgejo:`https://forgejo.example.com/username/repo-name`,repoUrlPlaceholderGitLab:`https://gitlab.com/username/repo-name`,allowInsecureHttp:`Allow insecure HTTP`,allowInsecureHttpHint:`Enable for self-hosted instances on private networks without TLS`,personalAccessToken:`Personal Access Token`,tokenSaved:`(saved)`,enterNewToken:`Enter new token to update`,tokenHint:`Fine-grained token with Contents read/write permission`,branch:`Branch`,provider:`Git Provider`,providerGitHub:`GitHub`,providerGitLab:`GitLab`,providerGitea:`Gitea`,providerForgejo:`Forgejo`,manualOnly:`Manual only`,hourly:`Hourly`,daily:`Daily`,weekly:`Weekly`,includeInBackup:`Include in backup`,kProfiles:`K-Profiles`,kProfilesDescription:`Pressure advance calibration from connected printers`,noPrintersConnected:`No printers connected`,printersConnected:`{{connected}}/{{total}} connected`,cloudProfiles:`Cloud Profiles`,cloudProfilesDescription:`Filament, printer, and process presets from Bambu Cloud and Orca Cloud`,cloudProfilesAccounts:`Connected accounts — Bambu Cloud: {{bambu}}, Orca Cloud: {{orca}}`,appSettings:`App Settings`,appSettingsDescription:`Bambuddy configuration (complete database)`,spoolInventory:`Spool Inventory`,spoolInventoryDescription:`Filament spools, usage history, and cost tracking`,printArchives:`Print Archives`,printArchivesDescription:`Print history metadata (no gcode/3MF files)`,lastBackupAt:`Last backup:`,noBackupsYet:`No backups yet`,next:`Next:`,startingBackup:`Starting backup...`,test:`Test`,enableBackup:`Enable Backup`,testConnection:`Test Connection`,enterRepoUrl:`Enter repository URL`,enterRepoAndToken:`Enter repository URL and access token`,repoRequired:`Repository URL is required`,tokenRequired:`Access token is required`,githubBackupEnabled:`GitHub backup enabled`,tokenUpdated:`Token updated`,settingsSaved:`Settings saved`,failedToSave:`Failed to save: {{message}}`,backupCompleteFiles:`Backup complete - {{count}} files updated`,backupSkippedNoChanges:`Backup skipped - no changes`,backupFailed2:`Backup failed: {{message}}`,clearedLogs:`Cleared {{count}} logs`,failedToClearLogs:`Failed to clear logs: {{message}}`,history:`History`,clear:`Clear`,date:`Date`,status:`Status`,commit:`Commit`,localBackup:`Local Backup`,localBackupDescription:`Create a complete backup of your Bambuddy data including the database, archives, uploads, and all files.`,downloadBackupLabel:`Download Backup`,completeBackupZip:`Complete backup: database + all files (ZIP)`,download:`Download`,preparingBackup:`Preparing backup...`,creatingArchive:`Creating backup archive... This may take a while for large archives.`,downloadingFile:`Downloading backup file...`,backupDownloaded:`Backup downloaded successfully`,failedToCreateBackup:`Failed to create backup: {{message}}`,restore:`Restore`,restoreReplacesAll:`Restore replaces all data.`,restoreReplacesAllDetail:`Your current database and files will be completely replaced. A restart is required after restore.`,restoreConfirmTitle:`Restore Backup`,restoreConfirmMessage:`Are you sure you want to restore from "{{filename}}"? This will completely replace your current database and all files. The application will need to be restarted after restore.`,restoreConfirmButton:`Restore Backup`,uploadingFile:`Uploading backup file...`,backupRestoredRestart:`Backup restored. Please restart Bambuddy.`,failedToRestore:`Failed to restore backup. Please check the file format.`,reloadNow:`Reload Now`,creatingBackup:`Creating Backup`,restoringBackup:`Restoring Backup`,preparing:`Preparing...`,processing:`Processing...`,doNotClosePage:`Please do not close this page or navigate away. This operation may take several minutes for large backups.`,restoring:`Restoring...`,restoreComplete:`Restore Complete`,restoreFailed2:`Restore Failed`,importSettings:`Import settings from a backup file`,pleaseWaitRestoring:`Please wait while your data is being restored`,selectBackupFile:`Click to select backup file (.json or .zip)`,duplicateHandling:`How duplicate handling works:`,matchPrinters:`Printers`,matchPrintersBy:`matched by serial number`,matchSmartPlugs:`Smart Plugs`,matchSmartPlugsBy:`matched by IP address`,matchNotificationProviders:`Notification Providers`,matchNotificationProvidersBy:`matched by name`,matchFilaments:`Filaments`,matchFilamentsBy:`matched by name + type + brand`,matchArchives:`Archives`,matchArchivesBy:`matched by content hash (always skipped)`,matchPendingUploads:`Pending Uploads`,matchPendingUploadsBy:`matched by filename`,matchSettingsTemplates:`Settings & Templates`,matchSettingsTemplatesBy:`always overwritten`,replaceExisting:`Replace existing data`,keepExisting:`Keep existing data`,overwriteDescription:`Overwrite items that already exist with backup data`,keepDescription:`Only restore items that don't already exist`,overwriteCaution:`Caution:`,overwriteWarning:`Overwriting will replace your current configurations with data from the backup. Printer access codes are never overwritten for security.`,cancel:`Cancel`,processingBackup:`Processing backup file...`,itemsRestored:`Items Restored`,itemsSkipped:`Items Skipped`,restored:`Restored`,skippedAlreadyExist:`Skipped (already exist)`,filesCategory:`Files (3MF, thumbnails, etc.)`,andMore:`...and {{count}} more`,newApiKeysGenerated:`New API Keys Generated`,keysShownOnce:`These keys are only shown once. Copy them now!`,copy:`Copy`,noDataFound:`No data was found to restore in the backup file.`,close:`Close`,scheduledBackup:`Scheduled Backups`,scheduledBackupDescription:`Automatically create backup snapshots on a schedule. Output directory can be mounted to a NAS or external storage.`,frequency:`Frequency`,backupTime:`Time`,retention:`Retention`,retentionDescription:`Number of backups to keep`,outputPath:`Output Path`,outputPathPlaceholder:`Default: {{path}}`,outputPathDescription:`Leave empty for default location`,runNow:`Run Now`,backupFiles:`Backup Files`,noScheduledBackups:`No backups yet`,deleteBackup:`Delete`,deleteBackupConfirm:`Delete this backup file?`,backupRunning:`Backup in progress...`,scheduledBackupComplete:`Backup completed successfully`,scheduledBackupFailed:`Backup failed`,nextBackup:`Next backup`,backupSize:`Size`,localTimeHint:`Local time ({{tz}})`,defaultPathLabel:`Default:`,pathCheck:{title:`Bambuddy cannot write to this directory`,howToFix:`How to fix:`,sandboxed:`The Bambuddy service cannot write to {{path}}. Its systemd unit runs with ProtectSystem=strict, which makes every directory outside the install, data and log directories read-only for the service - even one you can write to from your own shell.`,read_only:`{{path}} is on a read-only filesystem.`,permission_denied:`Bambuddy is not allowed to write to {{path}}. Check the directory owner and permissions.`,no_space:`The filesystem holding {{path}} is full.`,not_a_directory:`{{path}} exists but is not a directory.`,missing:`{{path}} does not exist and could not be created.`,error:`Bambuddy cannot write to {{path}}.`,ephemeralTitle:`These backups will not survive a container restart`,container_ephemeral:`{{path}} is inside the Bambuddy container, not on the host. Backups written there are lost when the container is recreated. Mount the directory from the host:`},categories:{settings:`Settings`,notification_providers:`Notification Providers`,notification_templates:`Notification Templates`,smart_plugs:`Smart Plugs`,printers:`Printers`,filaments:`Filaments`,maintenance_types:`Maintenance Types`,archives:`Archives`,projects:`Projects`,pending_uploads:`Pending Uploads`,external_links:`External Links`,api_keys:`API Keys`}},tags:{title:`Tags`,addTag:`Add Tag`,editTag:`Edit Tag`,deleteTag:`Delete Tag`,tagName:`Tag Name`,tagColor:`Tag Color`,noTags:`No tags`,deleteConfirm:`Are you sure you want to delete this tag?`,manageTags:`Manage Tags`},uploadModal:{title:`Upload 3MF Files`,dragDrop:`Drag & drop .3mf files here`,or:`or`,browseFiles:`Browse Files`,extractionInfo:`The printer model will be automatically extracted from the 3MF file metadata.`,uploaded:`uploaded`,failed:`failed`,uploading:`Uploading...`,upload:`Upload`,uploadFailed:`Upload failed`},editArchive:{title:`Edit Archive`,name:`Name`,namePlaceholder:`Print name`,printer:`Printer`,noPrinter:`No printer`,project:`Project`,noProject:`No project`,itemsPrinted:`Items Printed`,itemsPrintedHelp:`Number of items produced in this print job`,notes:`Notes`,notesPlaceholder:`Add notes about this print...`,externalLink:`External Link`,externalLinkPlaceholder:`https://printables.com/model/...`,externalLinkHelp:`Link to Printables, Thingiverse, or other source`,tags:`Tags`,tagsPlaceholder:`Add tags...`,addMoreTags:`Add more tags...`,matchingTags:`Matching "{{query}}"`,existingTags:`Existing tags`,clickToAdd:`(click to add)`,status:`Status`,failureReason:`Failure Reason`,selectReason:`Select reason...`,photos:`Photos of Printed Result`,photosHelp:`Click + to add photos of your printed result`,printResult:`Print result`,saving:`Saving...`,failureReasons:{adhesionFailure:`Adhesion failure`,spaghettiDetached:`Spaghetti / Detached`,layerShift:`Layer shift`,cloggedNozzle:`Clogged nozzle`,filamentRunout:`Filament runout`,warping:`Warping`,stringing:`Stringing`,underExtrusion:`Under-extrusion`,powerFailure:`Power failure`,userCancelled:`User cancelled`,other:`Other`},statuses:{completed:`Completed`,failed:`Failed`,aborted:`Cancelled`,printing:`Printing`}},kProfiles:{title:`K-Profiles`,noPrintersConfigured:`No Printers Configured`,addPrinterInSettings:`Add a printer in Settings to manage K-profiles`,noActivePrinters:`No Active Printers`,enablePrinterConnection:`Enable a printer connection to view its K-profiles`,loadingProfiles:`Loading K-Profiles...`,printerOffline:`Printer Offline`,printerOfflineDesc:`The selected printer is not connected. Power it on to view K-profiles.`,noMatchingProfiles:`No Matching Profiles`,noMatchingProfilesDesc:`No profiles match your search criteria`,noKProfiles:`No K-Profiles`,noKProfilesDesc:`No pressure advance profiles found for {{diameter}}mm nozzle`,createFirstProfile:`Create First Profile`,printer:`Printer`,nozzle:`Nozzle`,refresh:`Refresh`,addProfile:`Add Profile`,export:`Export`,import:`Import`,select:`Select`,selectAll:`Select All`,delete:`Delete`,searchPlaceholder:`Search by name or filament...`,allExtruders:`All Extruders`,leftOnly:`Left Only`,rightOnly:`Right Only`,allFlow:`All Flow`,hfOnly:`HF Only`,sOnly:`S Only`,sortName:`Sort: Name`,sortKValue:`Sort: K-Value`,sortFilament:`Sort: Filament`,leftExtruder:`Left Extruder`,rightExtruder:`Right Extruder`,modal:{addTitle:`Add K-Profile`,editTitle:`Edit K-Profile`,profileName:`Profile Name`,profileNamePlaceholder:`My PLA Profile`,kValue:`K-Value`,kValuePlaceholder:`0.020`,kValueHelp:`Typical range: 0.01 - 0.06 for PLA, 0.02 - 0.10 for PETG`,filament:`Filament`,selectFilament:`Select filament...`,source:{local:`Imported`,orcaCloud:`Orca Cloud`,bambuCloud:`Bambu Cloud`,builtin:`Built-in`},noFilamentsHelp:`No filaments available. Sign in to Bambu Cloud, or import presets under Profiles → Local Profiles.`,searchFilaments:`Search filaments...`,noFilamentMatches:`No filament matches that search`,flowType:`Flow Type`,highFlow:`High Flow`,standard:`Standard`,nozzleSize:`Nozzle Size`,extruder:`Extruder`,extruders:`Extruders`,left:`Left`,right:`Right`,notes:`Notes (stored locally)`,notesPlaceholder:`Add notes about this profile...`,notesHelp:`Notes are saved in Bambuddy, not on the printer`,syncing:`Syncing with printer...`,savingExtruder:`Saving to extruder {{current}}/{{total}}...`,pleaseWait:`Please wait`},deleteConfirm:{title:`Delete Profile`,cannotUndo:`This cannot be undone`,message:`Are you sure you want to delete "{{name}}" from the printer?`},bulkDelete:{title:`Delete Profiles`,cannotUndo:`This cannot be undone`,message:`Are you sure you want to delete {{count}} selected profiles from the printer?`},toast:{profileSaved:`K-profile saved`,profilesSaved:`K-profile saved to {{count}} extruders`,selectAtLeastOneExtruder:`Please select at least one extruder`,selectFilament:`Select a filament first`,filamentNotResolvable:`No Bambu filament ID for {{name}} — the printer cannot store a profile for it`,profileDeleted:`K-profile deleted`,profilesDeleted:`Deleted {{count}} profiles`,exportedProfiles:`Exported {{count}} profiles`,importedProfiles:`Imported {{count}} of {{total}} profiles`,noProfilesToExport:`No profiles to export`,invalidFileFormat:`Invalid file format`,failedToParseImport:`Failed to parse import file`,failedToSaveBatch:`Failed to save K-profiles`,noteSaved:`Note saved`,failedToSaveNote:`Failed to save note`},permission:{noRead:`You do not have permission to refresh profiles`,noCreate:`You do not have permission to add profiles`,noUpdate:`You do not have permission to update K-profiles`,noDelete:`You do not have permission to delete K-profiles`,noExport:`You do not have permission to export profiles`,noImport:`You do not have permission to import profiles`}},virtualPrinter:{title:`Virtual Printer`,running:`Running`,stopped:`Stopped`,description:{default:`Enable a virtual printer that appears in Bambu Studio and OrcaSlicer. Files sent to this printer will be archived directly without printing.`,proxy:`Enable a proxy that relays slicer traffic to a real printer, allowing remote printing over any network.`},enable:{title:`Enable Virtual Printer`,visibleInSlicer:`Visible as "Bambuddy" in slicer discovery`,proxyingTo:`Proxying to {{name}}`,notActive:`Not active`},model:{title:`Printer Model`,description:`Select which printer model to emulate.`,restartWarning:`Changing the model will restart the virtual printer`},accessCode:{title:`Access Code`,isSet:`Access code is set`,notSet:`No access code set - required to enable`,placeholder:`Enter 8-char code`,placeholderChange:`Enter new code to change`,hint:`Must be exactly 8 characters. Used by slicers to authenticate.`,charCount:`({{count}}/8)`,inheritedFromTarget:`Inherited from target`,derivedFromTargetHint:`Uses the target printer's access code. The bridge forwards slicer auth to the real printer, so the codes must match — edit the printer's access code to change this value.`,reveal:`Show access code`,hide:`Hide access code`},targetPrinter:{title:`Target Printer`,configured:`Proxy target configured`,notConfigured:`No target printer selected - required for proxy mode`,placeholder:`Select a printer...`,hint:`Select the printer to proxy slicer traffic to. The printer must be in LAN mode.`,noPrinters:`No printers configured. Add a printer first to use proxy mode.`},remoteInterface:{title:`Network Interface Override`,configured:`Interface override active`,optional:`Optional - use if auto-detected IP is wrong (e.g. multiple NICs, Docker, VPN)`,placeholder:`Auto-detect (default)...`,hint:`Override the IP address advertised via SSDP and used in the TLS certificate. Useful when Bambuddy has multiple network interfaces.`},mode:{title:`Mode`,archive:`Archive`,archiveDesc:`Archive files immediately`,review:`Review`,reviewDesc:`Review before archiving`,queue:`Queue`,queueDesc:`Archive and add to queue`,proxy:`Proxy`,proxyDesc:`Relay to real printer`},autoDispatch:{title:`Auto-dispatch`,description:`Automatically start prints when added to queue. When off, prints wait for manual dispatch.`},queueForceColorMatch:{title:`Force color match`,description:`Refuse to dispatch onto a printer that does not have the exact filament type and color loaded. Off by default — without this, the queue uses model-only matching and may pick a printer with the wrong color loaded.`},saveAmsMapping:{title:`Save AMS mapping`,description:`Persist the slicer's own AMS-slot pick (from the project_file MQTT command) onto the archive, so a later reprint reuses the exact physical spool instead of re-deriving one from the file's type/color. Off by default.`},gcodeInjection:{title:`G-code injection`,description:`Apply the per-model G-code snippets configured in Settings to jobs from this VP. Off by default.`},tailscaleDisabled:{title:`Tailscale integration`,description:`Enable to mark this VP as exposed over Tailscale. Shows the host's Tailscale address so you know which IP to paste into the slicer. The CA-import step is unchanged — this toggle has no effect on certificates.`},setupRequired:{title:`Setup Required`,description:`The virtual printer feature requires additional system configuration before it will work. This includes port forwarding, firewall rules, and platform-specific settings.`,readGuide:`Read the setup guide before enabling`},archiveNameSource:{title:`Archive name source`,description:`Choose how new archives are named when files arrive via the virtual printer. "Metadata" uses the slicer-embedded Title from the 3MF (default). "Filename" uses the filename Bambu Studio sent over FTP. Note: Bambu Studio overwrites the name you type in the "send to printer" dialog with the 3MF's Title field whenever one is present, so both modes often produce the same string.`,metadata:`Metadata`,filename:`Filename`},caCert:{title:`Slicer certificate`,description:`Virtual printers use a TLS certificate signed by the Bambuddy CA. Import this CA certificate into your slicer's trust store once so it accepts the connection — no need to copy it from the command line.`,copy:`Copy`,copied:`Copied`,download:`Download`,fingerprint:`SHA-256`},howItWorks:{title:`How it works`,step1:`On the same LAN, virtual printers appear in your slicer (Bambu Studio / OrcaSlicer) automatically via discovery. From other networks, add them manually by IP address and access code.`,step2:`In Archive, Review, and Queue modes, use the "Send" button in your slicer to upload 3MF files to Bambuddy. The slicer will show "Print success" — the file is stored, not printed.`,step3:`In Proxy mode, the virtual printer relays all traffic to a real printer — prints start immediately as if connected directly.`},status:{title:`Status Details`,printerName:`Printer Name`,model:`Model`,serialNumber:`Serial Number`,mode:`Mode`,pendingFiles:`Pending Files`,targetPrinter:`Target Printer`,ftpPort:`FTP Port`,mqttPort:`MQTT Port`,ftpConnections:`FTP Connections`,mqttConnections:`MQTT Connections`},toast:{updated:`Virtual printer settings updated`,failedToUpdate:`Failed to update settings`,copyFailed:`Failed to copy — try selecting the text manually`,accessCodeRequired:`Please set an access code first`,targetPrinterRequired:`Please select a target printer first`,bindIpRequired:`Please set a bind IP first`,accessCodeEmpty:`Access code cannot be empty`,accessCodeLength:`Access code must be exactly 8 characters`,targetCodeChangedRebind:`Access code now matches the new target printer. Re-add this device in your slicer to pick up the new code.`,created:`Virtual printer created`,failedToCreate:`Failed to create virtual printer`,deleted:`Virtual printer deleted`,failedToDelete:`Failed to delete virtual printer`},list:{title:`Virtual Printers`,add:`Add`,addFirst:`Add Virtual Printer`,empty:`No virtual printers configured. Add one to get started.`},bindIp:{title:`Bind Interface`,placeholder:`Select interface...`,hint:`Network interface for this virtual printer to bind to. Must be unique per printer.`},proxy:{accessCodeHint:`In proxy mode, use your target printer's access code in the slicer. The connection is forwarded transparently to the real printer.`},addDialog:{title:`Add Virtual Printer`,name:`Name`,hint:`You can configure access code, target printer, and other settings after creating.`,create:`Create`},deleteConfirm:{title:`Delete Virtual Printer`,message:`Are you sure you want to delete "{{name}}"? This will stop all services for this printer.`}},modelViewer:{openInSlicer:`Open in Slicer`,tabs:{model:`3D Model`,gcode:`G-code Preview`},notAvailable:`not available`,notSliced:`not sliced`,plates:`Plates`,allPlates:`All Plates`,plateNumber:`Plate {{number}}`,plateCount:`{{count}} plate`,plateCount_other:`{{count}} plates`,objectCount:`{{count}} object`,objectCount_other:`{{count}} objects`,filamentCount:`{{count}} filament`,filamentCount_other:`{{count}} filaments`,eta:`ETA {{minutes}} min`,noPreview:`No preview available for this file`,pagination:{pageOf:`Page {{current}} of {{total}}`,prev:`Prev`,next:`Next`},errors:{failedToLoad:`Failed to load file`,noMeshes:`No meshes found in 3MF file`,unsupportedFormat:`Unsupported file format`}},maintenanceDescriptions:{lubricateCarbonRods:`Apply lubricant to carbon rods for smooth motion`,lubricateRails:`Apply lubricant to linear rails for smooth motion`,cleanNozzle:`Clean hotend and nozzle to prevent clogs`,checkBelts:`Verify belt tension for accurate prints`,cleanBuildPlate:`Clean build plate for better adhesion`,checkExtruder:`Inspect extruder gears for wear`,checkCooling:`Ensure cooling fans are working properly`,generalInspection:`General printer inspection`,cleanCarbonRods:`Clean carbon rods to reduce friction`,lubricateSteelRods:`Apply lubricant to steel rods for smooth motion`,cleanSteelRods:`Clean steel rods to reduce friction`,cleanLinearRails:`Wipe linear rails to remove dust and debris`,checkPtfeTube:`Inspect PTFE tube for wear or damage`,replaceHepaFilter:`Replace HEPA filter for air quality`,replaceCarbonFilter:`Replace activated carbon filter`,lubricateLeftNozzleRail:`Lubricate left nozzle rail (H2 series)`},smartPlugs:{offline:`Offline`,admin:`Admin`,openPlugAdminPage:`Open plug admin page`,deleteSmartPlug:`Delete Smart Plug`,turnOnSmartPlug:`Turn On Smart Plug`,turnOffSmartPlug:`Turn Off Smart Plug`,turnOn:`Turn On`,turnOff:`Turn Off`,addSmartPlug:{scanningNetwork:`Scanning network...`,chooseEntity:`Choose an entity...`,connectionFailed:`Connection failed`,searchEntities:`Search entities...`,searchPowerSensors:`Search power sensors...`,searchEnergySensors:`Search energy sensors...`,placeholders:{plugName:`Living Room Plug`,mqttStateOnValue:`ON, true, 1`,mqttSameAsPower:`Same as power topic, or different`}},linkedTo:`Linked to:`,monitorOnly:`Monitor Only`,alerts:`Alerts`,scheduleOn:`On {{time}}`,scheduleOff:`Off {{time}}`,on:`On`,off:`Off`,power:`Power`,kwhToday:`kWh Today`,settings:`Settings`,automationSettings:`Automation Settings`,showInSwitchbar:`Show in Switchbar`,quickAccessSidebar:`Quick access from sidebar`,enabled:`Enabled`,enableAutomation:`Enable automation for this plug`,autoOn:`Auto On`,autoOnDescription:`Turn on when print starts`,autoOff:`Auto Off`,autoOffDescription:`Turn off when print completes (one-shot)`,autoOffPersistent:`Keep Enabled`,autoOffPersistentDescription:`Stay enabled between prints instead of one-shot`,controlsPrinterPower:`Powers the printer`,controlsPrinterPowerDescription:`Turn off if this plug only powers an accessory (filter fan, lights). Otherwise switching it off marks the printer offline.`,autoOffAfterDrying:`Auto Off After Drying`,autoOffAfterDryingDescription:`Turn off when AMS drying completes`,delayAfterDryingMinutes:`Drying delay (minutes)`,turnOffDelayMode:`Turn Off Delay Mode`,time:`Time`,temp:`Temp`,delayMinutes:`Delay (minutes)`,tempThreshold:`Temperature threshold (°C)`,tempThresholdDescription:`Turns off when nozzle cools below this temperature`,edit:`Edit`,deleteConfirm:`Are you sure you want to delete "{{name}}"? This cannot be undone.`,turnOnConfirm:`Are you sure you want to turn on "{{name}}"?`,turnOffConfirm:`Are you sure you want to turn off "{{name}}"? This will cut power to the connected device.`,failedToTurn:`Failed to turn {{action}} "{{name}}"`,unknown:`Unknown`,addTitle:`Add Smart Plug`,editTitle:`Edit Smart Plug`,stopScanning:`Stop Scanning`,discoverTasmota:`Discover Tasmota Devices`,foundDevices:`Found {{count}} device(s) - click to select:`,noDevicesFound:`No Tasmota devices found on your network`,haNotConfigured:`Home Assistant is not configured. Set it up in`,haSettingsPath:`Settings → Network → Home Assistant`,selectEntity:`Select Entity *`,ipAddress:`IP Address *`,nameLabel:`Name *`,username:`Username`,password:`Password`,authHint:`Leave empty if your Tasmota device doesn't require authentication`,linkToPrinter:`Link to Printer`,noPrinter:`No printer (manual control only)`,linkingDescription:`Linking enables automatic on/off when prints start/complete`,powerAlerts:`Power Alerts`,alertAbove:`Alert if above (W)`,alertBelow:`Alert if below (W)`,alertDescription:`Get notified when power consumption crosses these thresholds. Leave empty to disable that direction.`,dailySchedule:`Daily Schedule`,turnOnAt:`Turn On at`,turnOffAt:`Turn Off at`,scheduleDescription:`Automatically turn the plug on/off at these times daily. Leave empty to skip that action.`,showOnPrinterCard:`Show on Printer Card`,displayOnPrinterCard:`Display button on printer card`,connectedResult:`Connected!`,deviceLabel:`Device: {{name}} - `,stateLabel:`State: {{state}}`,test:`Test`,delete:`Delete`,save:`Save`,add:`Add`,cancel:`Cancel`,failedToStartScan:`Failed to start scan`,nameRequired:`Name is required`,entityRequired:`Entity is required for Home Assistant plugs`,mqttTopicRequired:`At least one MQTT topic must be configured for power, energy, or state monitoring`,loadingEntities:`Loading entities...`,loading:`Loading...`,failedToLoadEntities:`Failed to load entities: {{error}}`,noEntitiesMatching:`No entities found matching "{{search}}"`,noEntitiesAvailable:`No entities available`,searchingEntities:`Searching all entities ({{count}} found)`,showingEntities:`Showing switch, light, input_boolean ({{count}} available)`,energyMonitoringOptional:`Energy Monitoring (Optional)`,energyMonitoringHint:`Search and select sensors that provide power/energy data.`,powerSensorW:`Power Sensor (W)`,energyTodayKwh:`Energy Today (kWh)`,totalEnergyKwh:`Total Energy (kWh)`,noMatchingSensors:`No matching sensors`,none:`None`,mqttNotConfigured:`MQTT broker not configured. Set broker address in`,mqttSettingsPath:`Settings → Network → MQTT Publishing`,mqttNotConfiguredSuffix:`(you don't need to enable publishing, just fill in the broker details).`,mqttMonitorOnlyDescription:`MQTT plugs receive power/energy data via MQTT subscription. On/off control is not available - use your MQTT broker or home automation system.`,powerMonitoring:`Power Monitoring`,energyMonitoring:`Energy Monitoring`,stateMonitoring:`State Monitoring`,optional:`optional`,topic:`Topic`,jsonPath:`JSON Path`,multiplier:`Multiplier`,onValue:`ON Value`,mqttPowerHint:`JSON path extracts value from JSON payload (e.g., "power_l1"). Leave empty if topic publishes raw numeric values. Use multiplier 0.001 for mW→W, 1000 for kW→W.`,mqttEnergyHint:`JSON path extracts value from JSON payload. Leave empty for raw values. Use multiplier 0.001 for Wh→kWh, 1000 for MWh→kWh.`,mqttStateHint:`JSON path extracts value from JSON payload. Leave empty for raw values. ON value: the exact string that means "ON". Leave empty for auto-detect (ON, true, 1).`,restControl:`Control`,restOnUrl:`Turn ON URL`,restOffUrl:`Turn OFF URL`,restOnBody:`ON Request Body`,restOffBody:`OFF Request Body`,restMethod:`HTTP Method`,restHeaders:`Custom Headers (JSON)`,restStatusUrl:`Status URL`,restStatusPath:`State JSON Path`,restStatusOnValue:`ON Value`,restPowerUrl:`Power URL`,restPowerPath:`Power JSON Path`,restPowerMultiplier:`Power Multiplier`,restEnergyUrl:`Energy URL`,restEnergyPath:`Energy JSON Path (today)`,restEnergyTotalPath:`Energy JSON Path (lifetime)`,restEnergyTotalMultiplier:`Lifetime Multiplier`,restEnergyTotalPathHint:`e.g. aenergy.total`,restEnergyTotalHint:`Many plugs — every Shelly among them — report only a lifetime counter that never resets. It belongs here, not in the field above: read as today's usage it would never reset at midnight, and Yesterday and Total would stay empty. Bambuddy works Today and Yesterday out from it, which takes a day or two of readings to fill in. A Shelly reports watt-hours, so use a multiplier of 0.001.`,restEnergyMultiplier:`Energy Multiplier`,restUrlRequired:`At least one URL (ON or OFF) is required for REST plugs`,restHeadersHint:`e.g. {"Authorization": "Bearer your-token"}`,restBodyHint:`e.g. ON, {"state": "on"}`,restStatusHint:`URL to poll for current state`,restPathHint:`e.g. state or data.power.status`,restPowerUrlHint:`Separate URL for power data (uses Status URL if empty)`,restEnergyUrlHint:`Separate URL for energy data (uses Status URL if empty)`,restEnergyHint:`Each value can use its own URL or fall back to the Status URL. Use multipliers for unit conversion (e.g. 0.001 to convert Wh to kWh).`,testConnection:`Test Connection`,connectionSuccess:`Connection successful`,noSwitchesInSwitchbar:`No switches in switchbar`,enableSwitchbarHint:`Enable "Show in Switchbar" in Settings > Smart Plugs`},notifications:{providerTypes:{callmebot:`CallMeBot/WhatsApp`,ntfy:`ntfy`,pushover:`Pushover`,telegram:`Telegram`,email:`Email`,discord:`Discord`,webhook:`Webhook`,homeassistant:`Home Assistant`,bark:`Bark`},providerDescriptions:{email:`SMTP email notifications`,telegram:`Notifications via Telegram bot`,discord:`Send to Discord channel via webhook`,ntfy:`Free, self-hostable push notifications`,pushover:`Simple, reliable push notifications`,callmebot:`Free WhatsApp notifications via CallMeBot`,webhook:`Generic HTTP POST to any URL`,homeassistant:`Persistent notifications in Home Assistant dashboard`,bark:`iOS push notifications via Bark (self-hostable)`},lastSuccess:`Last: {{date}}`,error:`Error`,printer:`Printer:`,allPrinters:`All printers`,sendTestNotification:`Send Test Notification`,eventSettings:`Event Settings`,enabled:`Enabled`,sendFromProvider:`Send notifications from this provider`,printEvents:`Print Events`,printerStatus:`Printer Status`,amsAlarms:`AMS Alarms`,amsHtAlarms:`AMS-HT Alarms`,printQueue:`Print Queue`,start:`Start`,plateCheck:`Plate Check`,complete:`Complete`,failed:`Failed`,stopped:`Stopped`,progress:`Progress`,offline:`Offline`,lowFilament:`Low Filament`,maintenance:`Maintenance`,amsHumidity:`AMS Humidity`,amsTemp:`AMS Temp`,amsHtHumidity:`AMS-HT Humidity`,amsHtTemp:`AMS-HT Temp`,bedCooled:`Bed Cooled`,firstLayer:`First Layer`,quiet:`Quiet`,digest:`Digest {{time}}`,printStarted:`Print Started`,plateNotEmpty:`Plate Not Empty`,plateNotEmptyDescription:`Objects detected before print`,plateClearRequired:`Plate Clear Required`,plateClearRequiredDescription:`Print finished, queue waits for plate confirmation`,plateClear:`Plate Clear`,printCompleted:`Print Completed`,bedCooledLabel:`Bed Cooled`,bedCooledDescription:`Bed cooled below threshold after print`,firstLayerCompleteLabel:`First Layer Complete`,firstLayerCompleteDescription:`Notify with snapshot when first layer finishes`,missingSpoolAssignmentLabel:`Missing Spool Assignment`,missingSpoolAssignmentDescription:`Notify when print starts and required trays have no assigned spool`,printFailed:`Print Failed`,printStopped:`Print Stopped`,progressMilestones:`Progress Milestones`,progressMilestonesDescription:`Notify at 25%, 50%, 75%`,printerOffline:`Printer Offline`,printerError:`Printer Error`,aiFailureDetection:`AI Failure Detection`,aiFailureDetectionDescription:`Notify when Obico AI detects a possible print failure`,lowFilamentLabel:`Low Filament`,maintenanceDue:`Maintenance Due`,maintenanceDueDescription:`Notify when maintenance is needed`,amsHumidityHigh:`AMS Humidity High`,amsHumidityHighDescription:`Regular AMS humidity exceeds threshold`,amsTemperatureHigh:`AMS Temperature High`,amsTemperatureHighDescription:`Regular AMS temperature exceeds threshold`,amsHtHumidityHigh:`AMS-HT Humidity High`,amsHtHumidityHighDescription:`AMS-HT humidity exceeds threshold`,amsHtTemperatureHigh:`AMS-HT Temperature High`,amsHtTemperatureHighDescription:`AMS-HT temperature exceeds threshold`,inventoryAlerts:`Inventory Alerts`,stockReorderAlert:`Reorder Alert`,stockReorderAlertDescription:`SKU has reached its reorder point`,stockBreakAlert:`Stock Break Alert`,stockBreakAlertDescription:`Stock will run out before replenishment arrives`,jobAdded:`Job Added`,jobAddedDescription:`Job added to queue`,jobAssigned:`Job Assigned`,jobAssignedDescription:`Model-based job assigned to printer`,jobStarted:`Job Started`,jobStartedDescription:`Queue job started printing`,jobWaiting:`Job Waiting`,jobWaitingDescription:`Job waiting for filament or printer`,jobSkipped:`Job Skipped`,jobSkippedDescription:`Job skipped (previous failed)`,jobFailed:`Job Failed`,jobFailedDescription:`Job failed to start`,queueComplete:`Queue Complete`,queueCompleteDescription:`All queue jobs finished`,quietHours:`Quiet Hours`,noNotificationsDuring:`No notifications during these hours`,editProviderToChangeQuietHours:`Edit provider to change quiet hours`,dailyDigest:`Daily Digest`,batchNotifications:`Batch notifications into a single daily summary`,sendAt:`Send at {{time}}`,editProviderToChangeDigestTime:`Edit provider to change digest time`,edit:`Edit`,deleteProvider:`Delete Notification Provider`,deleteConfirm:`Are you sure you want to delete "{{name}}"? This cannot be undone.`,delete:`Delete`,addTitle:`Add Notification Provider`,editTitle:`Edit Notification Provider`,nameLabel:`Name *`,namePlaceholder:`My Notifications`,providerTypeLabel:`Provider Type *`,configuration:`Configuration`,testConfiguration:`Test Configuration`,printerFilter:`Printer Filter`,onlyFromPrinter:`Only send notifications for events from this printer`,quietHoursDnd:`Quiet Hours (Do Not Disturb)`,quietStart:`Start`,quietEnd:`End`,dailyDigestLabel:`Daily Digest`,sendDigestAt:`Send digest at`,digestCollected:`Events will be collected and sent as a single summary at this time`,notificationEvents:`Notification Events`,progressPercent:`(25%, 50%, 75%)`,bedCooledAfterPrint:`(after print completes)`,eventPriority:{sectionTitle:`ntfy Priority`,helpNtfy:`Pick a priority for each enabled event. ntfy uses these to escalate alerts (sound, visibility, push behavior). Levels not set here use the ntfy server default.`,min:`Min`,low:`Low`,default:`Default`,high:`High`,urgent:`Urgent`},cancel:`Cancel`,save:`Save`,add:`Add`,nameRequired:`Name is required`,fieldRequired:`{{field}} is required`,haDataInvalid:`The Data field must be a valid JSON object, e.g. {"priority": "high", "ttl": 0}`,phoneNumber:`Phone Number`,apiKey:`API Key`,serverUrl:`Server URL`,topic:`Topic`,authToken:`Auth Token`,userKey:`User Key`,appToken:`App Token`,priority:`Priority`,pushoverRetry:`Emergency Retry (s)`,pushoverExpire:`Emergency Expire (s)`,botToken:`Bot Token`,chatId:`Chat ID`,telegramThreadId:`Forum Topic ID`,telegramThreadIdHelp:`Optional. Posts into a single topic of a forum group — the last number in the topic link (t.me/c/.../25). Leave empty for the General topic.`,telegramThreadIdInvalid:`Forum Topic ID must be a number.`,smtpServer:`SMTP Server`,smtpPort:`SMTP Port`,security:`Security`,authentication:`Authentication`,username:`Username`,password:`Password`,fromEmail:`From Email`,toEmail:`To Email`,webhookUrl:`Webhook URL`,payloadFormat:`Payload Format`,authorization:`Authorization`,titleFieldName:`Title Field Name`,messageFieldName:`Message Field Name`,editTemplate:`Edit Template: {{name}}`,titleLabel:`Title`,bodyLabel:`Body`,titlePlaceholder:`Notification title...`,bodyPlaceholder:`Notification body...`,availableVariables:`Available Variables`,clickToInsert:`Click to insert at cursor position in body`,livePreview:`Live Preview`,hide:`Hide`,show:`Show`,loadingPreview:`Loading preview...`,enterTemplateContent:`Enter template content to see preview`,titlePreview:`Title:`,bodyPreview:`Body:`,resetToDefault:`Reset to Default`,titleRequired:`Title is required`,bodyRequired:`Body is required`,notificationLog:`Notification Log`,showFailedOnly:`Failed only`,last24Hours:`Last 24 hours`,last7Days:`Last 7 days`,last30Days:`Last 30 days`,last90Days:`Last 90 days`,justNow:`Just now`,noFailedNotifications:`No failed notifications`,noNotificationsLogged:`No notifications logged`,unknownProvider:`Unknown Provider`,logTitle:`Title`,logMessage:`Message`,logError:`Error`,logProvider:`Provider: {{type}}`,logTime:`Time: {{time}}`,refresh:`Refresh`,clearOld:`Clear Old`,statsSummary:`Last {{days}} days:`,statsNotifications:`notifications`,statsSent:`{{count}} sent`,statsFailed:`{{count}} failed`,eventTypes:{print_start:`Print Started`,print_complete:`Print Complete`,print_failed:`Print Failed`,print_stopped:`Print Stopped`,print_progress:`Progress`,printer_offline:`Printer Offline`,printer_error:`Printer Error`,filament_low:`Low Filament`,maintenance_due:`Maintenance Due`,test:`Test`},userEmail:{title:`Notifications`,emailNotifications:`Email Notifications`,emailNotificationsDesc:`Receive email notifications for your own print jobs. Emails are sent using the system SMTP settings configured in Advanced Authentication.`,sendingTo:`Notifications will be sent to`,noEmailWarning:`Your account does not have an email address. Contact an administrator to add one.`,printJobNotifications:`Print Job Notifications`,printJobNotificationsDesc:`Choose which events trigger email notifications for print jobs you submit.`,printJobStarts:`Print Job Starts`,printJobStartsDesc:`Get notified when your print job begins.`,printJobFinishes:`Print Job Finishes`,printJobFinishesDesc:`Get notified when your print job completes successfully.`,printErrors:`Print Errors`,printErrorsDesc:`Get notified when your print job fails or encounters an error.`,printJobStops:`Print Job Stops`,printJobStopsDesc:`Get notified when your print job is cancelled or stopped.`,saveSuccess:`Notification preferences saved.`,saveError:`Failed to save notification preferences.`}},richTextEditor:{bold:`Bold`,italic:`Italic`,underline:`Underline`,bulletList:`Bullet List`,numberedList:`Numbered List`,alignLeft:`Align Left`,alignCenter:`Align Center`,alignRight:`Align Right`,addLink:`Add Link`,removeLink:`Remove Link`},externalLinks:{title:`Sidebar Links`,sidebarLayout:`Sidebar`,sidebarLayoutDescription:`Show or hide built-in pages, add external links, and drag items to reorder the sidebar navigation.`,systemPages:`Bambuddy pages`,externalLinks:`External links`,visibleInSidebar:`Visible in sidebar`,hiddenFromSidebar:`Hidden from sidebar`,requiredInSidebar:`Required in sidebar`,hidePage:`Hide page`,showPage:`Show page`,settingsCannotBeHidden:`Settings cannot be hidden`,noLinksConfigured:`No external links configured`,deleteLink:`Delete Link`,removeCustomIcon:`Remove custom icon`,openInNewTab:`Open in new tab`,placeholders:{linkName:`My Link`}},keyboardShortcuts:{title:`Keyboard Shortcuts`,navigation:`Navigation`,archivesSection:`Archives`,kProfilesSection:`K-Profiles`,generalSection:`General`,shortcuts:{goToPrinters:`Go to Printers`,goToArchives:`Go to Archives`,goToQueue:`Go to Queue`,goToStats:`Go to Statistics`,goToProfiles:`Go to Cloud Profiles`,goToSettings:`Go to Settings`,focusSearch:`Focus search`,openUploadModal:`Open upload modal`,clearSelection:`Clear selection / blur input`,contextMenu:`Context menu on cards`,refreshProfiles:`Refresh profiles`,newProfile:`New profile`,exitSelectionMode:`Exit selection mode`,showHelp:`Show this help`},footer:`Press Esc or click outside to close`},notificationLog:{title:`Notification Log`,events:{printStarted:`Print Started`,printComplete:`Print Complete`,printFailed:`Print Failed`,printStopped:`Print Stopped`,progress:`Progress`,printerOffline:`Printer Offline`,printerError:`Printer Error`,lowFilament:`Low Filament`,maintenanceDue:`Maintenance Due`,test:`Test`},timeAgo:{justNow:`Just now`,minutesAgo:`{{minutes}}m ago`,hoursAgo:`{{hours}}h ago`}},restoreBackup:{title:`Restore Backup`,restoring:`Restoring...`,restoreComplete:`Restore Complete`,restoreFailed:`Restore Failed`,importSettings:`Import settings from a backup file`,pleaseWait:`Please wait while your data is being restored`,clickToSelect:`Click to select backup file (.json or .zip)`,howDuplicateHandling:`How duplicate handling works:`,categories:{printers:`Printers`,smartPlugs:`Smart Plugs`,notificationProviders:`Notification Providers`,filaments:`Filaments`,archives:`Archives`,pendingUploads:`Pending Uploads`,settingsTemplates:`Settings & Templates`},matchingInfo:{printers:`matched by serial number`,smartPlugs:`matched by IP address`,notificationProviders:`matched by name`,filaments:`matched by name + type + brand`,archives:`matched by content hash`,pendingUploads:`matched by filename`,settingsTemplates:`always overwritten`},replaceExisting:`Replace existing data`,keepExisting:`Keep existing data`,replaceDescription:`Overwrite items that already exist with backup data`,keepDescription:`Only restore items that don't already exist`,caution:`Caution:`,cautionText:`Overwriting will replace your current configurations with backup data. Printer access codes are never overwritten for security.`,itemsRestored:`Items Restored`,itemsSkipped:`Items Skipped`,restored:`Restored`,skipped:`Skipped (already exist)`,filesLabel:`Files (3MF, thumbnails, etc.)`,newApiKeysGenerated:`New API Keys Generated`,newApiKeysWarning:`These keys are only shown once. Copy them now!`,processingBackup:`Processing backup file...`,noDataFound:`No data was found to restore in the backup file.`,failedToRestore:`Failed to restore backup. Please check the file format.`},backupExport:{title:`Export Backup`,selectData:`Select data to include`,selectAll:`Select All`,selectNone:`Select None`,categoryDescriptions:{settings:`Language, theme, update preferences`,notifications:`ntfy, Pushover, Discord, etc.`,templates:`Custom message templates`,smartPlugs:`Tasmota plug configurations`,externalLinks:`Sidebar links to external services`,printers:`Printer info (access codes excluded)`,plateDetection:`Empty plate reference images`,filaments:`Filament types and costs`,maintenance:`Custom maintenance schedules`,archives:`All print data + files (3MF, thumbnails, photos)`,projects:`Projects, BOM items, and attachments`,pendingUploads:`Virtual printer uploads awaiting review`,apiKeys:`Webhook API keys (new keys generated on import)`},requiresPrinters:`Requires Printers to be selected`,zipFileWarning:`ZIP file will be created.`,zipFileDescription:`Includes all 3MF files, thumbnails, timelapses, and photos. This may take a while and result in a large file.`,includeAccessCodes:`Include Access Codes`,includeAccessCodesDescription:`For transferring to another machine`,includeAccessCodesWarning:`Access codes will be included in plain text. Keep this backup file secure!`,categoriesSelected:`{{selectedCount}} categories selected`},pendingUploads:{placeholders:{notes:`Add notes about this print...`},discardUpload:`Discard Upload`,archiveAllUploads:`Archive All Uploads`,discardAllUploads:`Discard All Uploads`,archive:`Archive`,timeAgo:{justNow:`Just now`,minutesAgo:`{{minutes}}m ago`,hoursAgo:`{{hours}}h ago`,daysAgo:`{{days}}d ago`}},apiBrowser:{placeholders:{requestBody:`JSON request body...`,searchEndpoints:`Search endpoints...`}},configureAmsSlot:{title:`Configure AMS Slot`,slotConfigured:`Slot Configured!`,configuringSlot:`Configuring slot:`,slotLabel:`{{ams}} Slot {{slot}}`,searchPresets:`Search presets...`,colorPlaceholder:`Color name or hex (e.g., brown, FF8800)`,clearCustomColor:`Clear custom color`,noCloudPresets:`No cloud presets. Login to Bambu Cloud to sync.`,noPresetsAvailable:`No presets available. Login to Bambu Cloud or import local profiles.`,noMatchingPresets:`No matching presets found.`,custom:`Custom`,builtin:`Built-in`,orcaCloud:`Orca Cloud`,bambuCloud:`Bambu Cloud`,settingsSentToPrinter:`Settings sent to printer`,filamentProfile:`Filament Profile`,kProfileLabel:`K Profile (Pressure Advance)`,filteringFor:`Filtering for: {{material}}`,noKProfile:`No K profile (use default 0.020)`,noMatchingKProfiles:`No matching K profiles found. Default K=0.020 will be used.`,otherKProfiles:`Other K profiles on this printer`,selectFilamentFirst:`Select a filament profile first`,kFromCalibration:`K={{value}} from printer calibration`,customColorLabel:`Custom Color (optional)`,presetColors:`{{name}} colors:`,showLessColors:`Show less colors`,showMoreColors:`Show more colors`,clear:`Clear`,hexLabel:`Hex: #{{hex}}`,resetting:`Resetting...`,resetSlot:`Reset Slot`,cancel:`Cancel`,configuring:`Configuring...`,configureSlot:`Configure Slot`},githubBackup:{title:`Git Backup`,history:`History`,downloadBackup:`Download Backup`,restoreBackup:`Restore Backup`,noBackupsYet:`No backups yet`},emailSettings:{placeholders:{fromName:`BamBuddy`}},tagManagement:{searchTags:`Search tags...`,renameTag:`Rename tag`,deleteTag:`Delete tag`},notificationTemplates:{placeholders:{title:`Notification title...`,body:`Notification body...`}},batchTag:{placeholders:{newTag:`Enter new tag...`}},photoGallery:{deletePhoto:`Delete Photo`},filamentHoverCard:{copySpoolUuid:`Copy spool UUID`},kProfilesView:{hasNote:`Has note`,copyProfile:`Copy profile`},layout:{openMenu:`Open menu`,noPermissionSystemInfo:`You do not have permission to view system information`},dashboard:{dragToReorder:`Drag to reorder`,hideWidget:`Hide widget`},notificationProviderCard:{deleteNotificationProvider:`Delete Notification Provider`},fileManagerModal:{closeFileManager:`Close file manager`,sortFiles:`Sort files`,goToParentFolder:`Go to parent folder`,threeView:`3D View`},embeddedCameraViewer:{refreshStream:`Refresh stream`,close:`Close`,zoomOut:`Zoom out`,resetZoom:`Reset zoom`,zoomIn:`Zoom in`,dragToResize:`Drag to resize`},timelapseViewer:{skipBack5s:`Skip back 5s`,skipForward5s:`Skip forward 5s`},notificationProviders:{descriptions:{email:`SMTP email notifications`,telegram:`Notifications via Telegram bot`,discord:`Send to Discord channel via webhook`,ntfy:`Free, self-hostable push notifications`,pushover:`Simple, reliable push notifications`,callmebot:`Free WhatsApp notifications via CallMeBot`,webhook:`Generic HTTP POST to any URL`}},logViewer:{searchPlaceholder:`Search message or logger name...`,noLogEntries:`No log entries found`},switchbarPopover:{noSwitchesInSwitchbar:`No switches in switchbar`},projectPageModal:{placeholders:{title:`Title`,designer:`Designer`,license:`License`,description:`Enter description...`,profileTitle:`Profile Title`,profileDescription:`Profile description...`}},spoolmanSettings:{},time:{unknown:`-`,waiting:`Waiting`,justNow:`Just now`,now:`Now`,minsAgo:`{{count}}m ago`,inMins:`in {{count}}m`,hoursAgo:`{{count}}h ago`,inHours:`in {{count}}h`,daysAgo:`{{count}}d ago`,inDays:`in {{count}}d`},spoolbuddy:{nav:{dashboard:`Dashboard`,ams:`AMS`,inventory:`Inventory`,writeTag:`Write`,settings:`Settings`},status:{nfcReady:`NFC Ready`,nfcOff:`NFC Off`,offline:`Offline`,online:`Online`,noPrinters:`No printers`,deviceOffline:`Device Offline`,waitingConnection:`Waiting for device connection...`,systemReady:`System Ready`,status:`Status`},dashboard:{readyToScan:`Ready to scan`,idleMessage:`Place a spool on the scale to identify it`,nfcHint:`NFC tag will be read automatically`,device:`Device`,syncWeight:`Sync Weight`,weightSynced:`Synced!`,unknownTag:`Unknown Tag`,newTag:`New Tag Detected`,onScale:`on scale`,linkSpool:`Link to Spool`,linkTagTitle:`Link Tag to Spool`,linkTag:`Link Tag`,selectSpool:`Select a spool to link this tag to:`,noUntagged:`No spools without tags found`,tagDetected:`Tag detected`,noTag:`No tag`,tagId:`Tag`,grossWeight:`Gross weight`,spoolSize:`Spool size`,close:`Close`,currentSpool:`Current Spool`,plateReady:`Plate ready: {{name}}`,plateReadyLabel:`Plates ready to clear`,plateClearAction:`Clear`,plateClearedToast:`Plate marked as cleared`,plateClearFailed:`Could not mark plate as cleared`},modal:{spoolDetected:`Spool Detected`,assignToAms:`Assign to AMS`,syncWeight:`Sync Weight`,weightSynced:`Synced!`,syncing:`Syncing...`,newTagDetected:`New Tag Detected`,addToInventory:`Add to Inventory`,assignToAmsTitle:`Assign to AMS`,selectSlot:`Select a slot`,assign:`Assign`,assigning:`Assigning...`,assignSuccess:`Assigned!`,assignPendingInsert:`Assigned. Slot will configure when you insert the spool.`,assignError:`Failed to assign spool. Please try again.`,noPrinterSelected:`Select a printer...`,noAmsDetected:`No AMS detected on this printer`,slot:`Slot`},weight:{noReading:`No reading`,stable:`Stable`,measuring:`Measuring...`,tare:`Tare`,calibrate:`Calibrate`},spool:{remaining:`Remaining`,material:`Material`,brand:`Brand`,color:`Color`,coreWeight:`Core`,labelWeight:`Label`,scaleWeight:`Scale`,netWeight:`Net`,lastUsed:`Last used`},ams:{noData:`No AMS detected`,connectAms:`Connect an AMS to see filament slots`,noPrinter:`No printer selected`,selectPrinter:`Select a printer from the top bar`,printerDisconnected:`Printer disconnected`,humidity:`Humidity`,level:`Level`,active:`Active`,slot:`Slot`,empty:`Empty`},inventory:{search:`Search spools...`,empty:`No spools in inventory`,noResults:`No matching spools`,spools:`spools`,addSpool:`Add Spool`},settings:{tabDevice:`Device`,tabDisplay:`Display`,tabScale:`Scale`,tabUpdates:`Updates`,nfcReader:`NFC Reader`,type:`Type`,connection:`Connection`,notConnected:`N/A`,deviceInfo:`Device Info`,hostname:`Host`,uptime:`Uptime`,systemConfig:`Backend & Auth`,backendUrl:`Bambuddy Backend URL`,apiToken:`API Token`,apiTokenPlaceholder:`Enter API token`,saveConfig:`Save Config`,systemQueued:`Config queued.`,nfcDiagnostic:`NFC Diagnostic`,scaleDiagnostic:`Scale Diagnostic`,readTagDiagnostic:`Read Tag Diagnostic`,testNfc:`Test reader`,testScale:`Test accuracy`,testReadTag:`Read tag`,systemFieldsRequired:`Backend URL is required.`,brightness:`Brightness`,saved:`Saved`,noBacklight:`No DSI backlight detected. Brightness control requires a DSI display.`,screenBlank:`Screen Blank Timeout`,screenBlankDesc:`Screen turns off after inactivity. Touch to wake.`,displayNote:`Brightness is applied as a software filter.`,scaleCalibration:`Scale Calibration`,currentWeight:`Current weight`,tareOffset:`Tare`,calFactor:`Factor`,knownWeight:`Known weight`,calStep1:`Remove all items from the scale and press Set Zero.`,calStep2:`Place known weight on scale.`,setZero:`Set Zero`,calibrateNow:`Calibrate`,calibrated:`Calibrated`,tareSet:`Tare command sent. Waiting for device...`,tareComplete:`Tare complete!`,tareTimedOut:`Tare timed out — is the SpoolBuddy daemon running?`,tareFailed:`Failed to send tare command`,zeroSet:`Zero point set. Place known weight on scale.`,calibrationDone:`Calibration complete!`,calibrationFailed:`Calibration failed`,lastCalibrated:`Last calibrated`,stable:`Stable`,settling:`Settling...`,firmware:`Firmware`,scale:`Scale`,noDevice:`No SpoolBuddy device found`,daemonVersion:`Daemon Version`,currentVersion:`Current`,versionPending:`Waiting for daemon...`,checking:`Checking...`,checkUpdates:`Check for Updates`,updateAvailable:`Update available`,updateInstructions:`Update via SSH: run the SpoolBuddy install script to upgrade.`,upToDate:`Up to date`,includeBeta:`Include beta versions`},writeTag:{tabExisting:`Existing Spool`,tabNew:`New Spool`,tabReplace:`Replace Tag`,searchPlaceholder:`Search by material, color, brand...`,noUntaggedSpools:`No spools without tags`,noTaggedSpools:`No spools with tags`,selectSpool:`Select a spool, then place a blank NTAG on the reader`,placeTag:`Place an NTAG on the reader`,tagReady:`Tag detected — ready to write`,writeTag:`Write Tag`,replaceTag:`Replace Tag`,writing:`Writing tag...`,waiting:`Waiting for SpoolBuddy...`,writeSuccess:`Tag written successfully!`,writeFailed:`Write failed`,queueFailed:`Failed to queue write command`,tryAgain:`Try Again`,cancel:`Cancel`,replaceWarning:`Old tag will be unlinked. New tag will replace it.`,deviceOffline:`SpoolBuddy is offline`,material:`Material`,colorName:`Color Name`,color:`Color`,brand:`Brand`,weight:`Weight (g)`,createSpool:`Create Spool`,creating:`Creating...`,spoolCreated:`Spool created! Ready to write.`,createFailed:`Failed to create spool`,incompleteDataWarning:`Tag written with incomplete Spoolman data`},quickMenu:{printerPower:`Printer Power`,systemControls:`System`,restartDaemon:`Restart Daemon`,restartBrowser:`Restart Browser`,reboot:`Reboot`,shutdown:`Shutdown`,swipeToClose:`Swipe down to close`,confirmTitle:`Confirm`,confirmShutdown:`Are you sure you want to shut down the SpoolBuddy? You will need physical access to turn it back on.`,confirmReboot:`Are you sure you want to reboot the SpoolBuddy?`,confirmRestartDaemon:`Restart the SpoolBuddy daemon? NFC and scale will be temporarily unavailable.`,confirmRestartBrowser:`Restart the kiosk browser? The display will briefly go blank.`,confirm:`Confirm`,confirmPlugOn:`Turn on {{name}}?`,confirmPlugOff:`Turn off {{name}}?`,turnOn:`Turn On`,turnOff:`Turn Off`}},diagnostic:{modalTitle:`Connection diagnostic — {{name}}`,running:`Running diagnostic...`,runningElapsed:`Running diagnostic... ({{elapsed}}s)`,waitingForReportHint:`Listening for the printer to publish a status report — this can take up to {{max}} seconds.`,runFailed:`Diagnostic could not run: {{error}}`,retry:`Run again`,runButton:`Run diagnostic`,sectionTitle:`Connection Diagnostic`,sectionDescription:`Check why a printer won't connect or won't print — port reachability, LAN developer mode, Docker network mode, and credentials.`,noPrinters:`No printers configured.`,overall:{ok:`No problems found — the printer connection looks healthy.`,warnings:`The printer should work, but some things need attention.`,problems:`Found problems that explain why the printer won't connect or print.`},check:{port_mqtt:{title:`Control port (MQTT 8883)`,pass:`Reachable — the printer is accepting control connections.`,fail:`Port 8883 is unreachable. The printer is powered off, on a different IP address, or a firewall is blocking it. Verify the printer IP and that nothing blocks port 8883.`},port_ftps:{title:`File transfer port (FTPS 990)`,pass:`Reachable — sending print files will work.`,warn:`Port 990 is unreachable. Monitoring may still work, but sending prints to the printer will fail. Make sure port 990 is not blocked.`},external_storage:{title:`Store sent files on external storage (install step 4)`,pass:`The printer reports this option is on — sent files will be stored on the SD card and archives will have thumbnails and slicer metadata.`,fail:`The printer reports this option is off. Enable "Store sent files on external storage" — on newer firmware (P2S 01.02 / Bambu Studio 2.6+) the toggle lives on the printer's Print Settings; on older versions it's in Bambu Studio / OrcaSlicer's Device tab. Without it, every archived print is missing its thumbnail and slicer metadata.`,skip:`Not checked — needs a live MQTT connection. On older slicers where this setting lives only in the slicer the printer never reports it, so this check will pass even when the option is off — verify install step 4 manually.`,skip_unsupported_model:`This model has an SD slot but no way to turn the option on — current P1-series firmware doesn't expose the toggle in Bambu Studio and the printer has no screen. Nothing to fix here; archived prints may lack thumbnails and slicer metadata until Bambu Lab adds firmware support.`},port_rtsps:{title:`Camera port ({{protocol}} {{port}})`,pass:`Reachable — the camera stream will work.`,warn:`Port {{port}} is unreachable. The live camera view will not work. This does not affect printing.`},network_mode:{title:`Docker network mode`,pass:`Running in host network mode.`,warn:`Bambuddy is running in Docker bridge networking. Printer discovery and the Virtual Printer need host network mode — recreate the container with "network_mode: host".`,skip:`Not running in Docker — not applicable.`},subnet:{title:`Network subnet`,pass:`The printer and Bambuddy are on the same subnet.`,warn:`The printer ({{printer_ip}}) and Bambuddy ({{host_ip}}) are on different subnets. They may not reach each other unless routing between the subnets is configured.`,skip:`Subnet could not be determined — skipped.`},mqtt_auth:{title:`Printer credentials`,pass:`The printer accepted the connection.`,fail:`The printer is reachable but Bambuddy is not connected to it. The access code or serial number is most likely wrong — the access code changes every time LAN Only or Developer Mode is toggled, so re-copy it from the printer screen. A printer that is rebooting, or already at its limit of simultaneous connections, can look the same.`,fail_auth_rejected:`The printer refused Bambuddy's credentials. The access code or serial number is wrong — the access code changes every time LAN Only or Developer Mode is toggled, so re-copy it from the printer screen and save it in the printer settings.`,skip:`Not checked — the printer could not be reached.`},developer_mode:{title:`LAN Developer Mode`,pass:`Developer Mode is enabled.`,fail:`Developer Mode is OFF on the printer. Enable it in the printer's LAN settings — and confirm with OK. Without it, prints will not start.`,skip:`Could not be checked — requires a live connection to the printer.`},printer_publishing:{title:`Printer is publishing status`,pass:`The printer is publishing status updates — AMS, filaments, and K-profiles will mirror correctly to the slicer.`,fail:`The MQTT broker accepted the connection but the printer has not published any status reports. This is almost always a wrong or mis-cased serial number — the device//report topic is case-sensitive. Re-check the serial in printer settings against the screen on the printer.`,skip:`Could not be checked — requires a live connection to the printer.`}}},systemHealth:{sectionTitle:`System Health`,sectionDescription:`Scans recent logs for known issues you can usually fix yourself, before they turn into a support ticket.`,rescan:`Re-scan`,clean:`No known issues found in the last {{times}} log entries.`,logUnavailable:`File logging is disabled, so logs cannot be scanned. Enable file logging to use this check.`,learnMore:`How to fix`,fixLabel:`Fix:`,occurrences:`Seen {{times}}× — last at {{lastSeen}}`,category:{layer8:`You can fix this`,environment:`Environment`,bug:`Please report this`},signature:{"ftp-auth-rejected":{name:`Printer rejected the access code`,cause:`The printer refused the file-transfer login. The access code is wrong, or it changed after Developer Mode was toggled.`,fix:`Re-copy the access code from the printer screen (LAN settings) and update it in the printer's settings in Bambuddy.`},"ftp-connection-timeout":{name:`File-transfer connection timed out`,cause:`Bambuddy could not reach the printer's file-transfer port (FTPS 990). The port is blocked, or the printer is off or on another subnet.`,fix:`Make sure nothing blocks port 990 between Bambuddy and the printer, and that both are on the same network.`},"ftp-ssl-error":{name:`Secure file-transfer handshake failed`,cause:`The TLS handshake with the printer's file-transfer server failed. This is often a firewall or outdated printer firmware.`,fix:`Update the printer firmware and check that no firewall or proxy intercepts the connection on port 990.`},"mqtt-connection-flapping":{name:`Printer connection keeps dropping`,cause:`The control connection (MQTT 8883) repeatedly disconnects and reconnects — usually a weak network path or a partially blocked port.`,fix:`Check the Wi-Fi signal at the printer, prefer a wired connection, and make sure port 8883 is reliably reachable.`},"camera-connection-refused":{name:`Camera stream unreachable`,cause:`The live camera could not be reached on port RTSPS 322. The port is blocked, or the camera or LAN liveview is off on the printer.`,fix:`Enable the camera and LAN liveview on the printer, and make sure port 322 is not blocked. This does not affect printing.`},"database-locked":{name:`Database write contention`,cause:`The SQLite database is hitting "database is locked" errors under load — common when running several printers at once.`,fix:`Switch Bambuddy to an external PostgreSQL database. See the PostgreSQL guide in the documentation.`}}},vpDiagnostic:{title:`Setup check — {{name}}`,runButton:`Run setup check`,running:`Running setup check...`,runFailed:`Could not run the setup check: {{error}}`,retry:`Run again`,overall:{ok:`All checks passed — this virtual printer is set up correctly.`,warnings:`The virtual printer should work, but some things need attention.`,problems:`Found problems that explain why the slicer can't see or use this virtual printer.`},check:{enabled:{title:`Virtual printer enabled`,fail:`This virtual printer is switched off. Toggle it on to make it discoverable.`},running:{title:`Services running`,fail:`The virtual printer is enabled but its services are not running. Check the Bambuddy log — a bind IP conflict or a permission error usually stops them.`},bind_interface:{title:`Bind network interface`,fail:`The bind interface is not set, or no longer exists on this host. Pick a current interface in the Bind Interface dropdown.`},access_code:{title:`Access code set`,fail:`No access code is set. The slicer must be given the same 8-character access code you set here.`},target_printer:{title:`Target printer`,fail:`No target printer is selected. Proxy mode needs a real printer to forward to.`,warn:`The target printer is offline right now — proxying will resume once it reconnects.`},port_ftps:{title:`File-upload service (port {{port}})`,fail:`Nothing is listening on port {{port}} of the bind IP, so the slicer cannot upload files. A port conflict on this interface is the usual cause.`},port_mqtt:{title:`Control service (port {{port}})`,fail:`Nothing is listening on port {{port}} of the bind IP, so the slicer cannot connect or show status.`},port_bind:{title:`Discovery service (port {{port}})`,fail:`Nothing is listening on port {{port}} of the bind IP, so the slicer's discovery handshake fails.`},certificate:{title:`TLS certificate`,pass:`Certificate ready. Make sure the Bambuddy CA certificate (above) is imported into your slicer's trust store.`,fail:`The TLS certificate for this virtual printer is missing. Check that the Bambuddy data directory is writable.`}}},bugReport:{title:`Report a Bug`,description:`Description`,descriptionPlaceholder:`What went wrong? Please describe the issue...`,email:`Email (optional)`,emailPlaceholder:`your@email.com`,emailPrivacy:`If provided, your email will be included in a collapsed section of the GitHub issue so the maintainer can follow up.`,screenshot:`Screenshot`,uploadOrPaste:`Upload, paste, or drag an image`,dataCollectedSummary:`What data is included in the report?`,dataIncluded:`Included:`,dataIncludedList:`App version, OS, architecture, Python version, database stats (counts only), printer models, nozzle counts, firmware versions, connectivity status, integration status (Spoolman, MQTT, HA), non-sensitive settings, network interface count, Docker details, dependency versions.`,dataNeverIncluded:`Never included:`,dataNeverIncludedList:`Printer names, serial numbers, access codes, passwords, IP addresses, email addresses, API keys, tokens, webhook URLs, hostnames, or usernames.`,submit:`Submit`,startLogging:`Start Debug Logging`,stepEnableLogging:`Debug logging enabled`,stepReproduce:`Reproduce the issue now`,stepStopLogging:`Stop & submit report`,stopAndSubmit:`Stop & Submit`,maxDuration:`Auto-stops after {{minutes}} min`,stoppingLogs:`Collecting logs & submitting...`,submitting:`Submitting bug report...`,submittingStepConnection:`Running printer connectivity checks`,submittingStepVirtualPrinters:`Running virtual-printer setup checks`,submittingStepLogScan:`Scanning recent logs for known issues`,submittingStepSubmit:`Submitting report to GitHub`,submitSuccess:`Bug report submitted successfully!`,submitFailed:`Failed to submit bug report`,diagnosticChecking:`Checking printer connections...`,diagnosticHealthy:`Connection check passed — no problems found on your printers.`,diagnosticSummary:`{{problems}} of {{total}} printers have connection issues`,diagnosticIntro:`One or more printers have a connection problem that may be causing your issue. Expand a printer below to see the fix — resolving it could solve the problem without a bug report. You can still submit a report below.`,logHealthSummary:`Known issues found in your logs`,logHealthIntro:`Recent logs match known problems. Check the fixes below — resolving them could solve your issue without a bug report. You can still submit a report below.`,thankYou:`Thank you!`,submitted:`Your bug report has been submitted.`,viewIssue:`View Issue`,unexpectedError:`An unexpected error occurred`},failureDetection:{title:`AI Failure Detection`,description:`Monitor prints with a self-hosted Obico ML API and act on detected failures automatically.`,mlUrl:`Obico ML API URL`,mlUrlHint:`Base URL of your self-hosted Obico ml_api container (e.g. http://192.168.1.10:3333).`,mlToken:`ML API Token (optional)`,mlTokenPlaceholder:`Leave empty if the server runs without ML_API_TOKEN`,mlTokenHint:`Must match the ML_API_TOKEN environment variable of your Obico ml_api container. Leave empty when the container runs without one.`,test:`Test`,testSuccess:`ML API reachable and healthy.`,testSuccessTokenUnknown:`ML API reachable and healthy. The token could not be checked.`,testFailed:`Could not reach the ML API.`,sensitivity:`Sensitivity`,sensitivityLow:`Low (fewer false positives)`,sensitivityMedium:`Medium (balanced)`,sensitivityHigh:`High (detect early, more false positives)`,sensitivityHint:`Adjusts the confidence thresholds that trigger warnings and failures.`,action:`Action on detected failure`,actionNotify:`Notify only`,actionPause:`Pause print`,actionPauseOff:`Pause and cut power`,pollInterval:`Poll interval (seconds)`,pollIntervalHint:`How often to check each printer while it is printing. Minimum 5s, maximum 120s.`,externalUrlMissing:`External URL is not set.`,externalUrlHint:`The ML API fetches the camera snapshot by URL. Set the External URL in General settings so the ML API container can reach Bambuddy.`,perPrinterTitle:`Monitored Printers`,perPrinterHint:`Choose which printers the detection service watches.`,monitorAll:`Monitor all connected printers`,statusTitle:`Status`,serviceRunning:`Service running`,thresholds:`Low / High thresholds`,activePrinters:`Active prints`,noActivePrints:`No prints currently running.`,historyTitle:`Recent Detections`,noHistory:`No detections yet.`},makerworld:{title:`MakerWorld`,description:`Paste a MakerWorld model URL to import and print it directly from Bambuddy — without leaving for the Bambu Handy app.`,pasteUrlHeader:`Import from MakerWorld`,pasteUrlPlaceholder:`https://makerworld.com/en/models/… or paste any MakerWorld link`,resolveButton:`Resolve`,signInRequiredTitle:`Bambu Cloud sign-in required to download`,signInRequiredBody:`You can browse model details anonymously, but MakerWorld requires a Bambu Cloud account to download 3MF files.`,signInExpiredTitle:`Bambu Cloud sign-in expired`,signInExpiredBody:`You are still signed in to Bambuddy, but Bambu Lab has stopped accepting the stored token, so downloads will fail. Sign in to Bambu Cloud again.`,openCloudSettings:`Open Cloud settings`,untitledModel:`Untitled model`,byCreator:`by {{name}}`,downloadsCount:`{{count}} downloads`,licensePrefix:`License`,alreadyImported:`Already in library`,openOnMakerworld:`Open on MakerWorld`,alreadyInLibrary:`This model is already in your library — find it in File Manager → MakerWorld`,importSuccess:`Imported {{filename}} — saved to File Manager → MakerWorld`,platesHeader:`Plates ({{count}})`,plateDefaultName:`Plate {{n}}`,materialCount:`{{count}} filaments`,amsRequired:`AMS required`,slicedFor:`Sliced for {{printer}}`,alsoCompatible:`Also marked compatible: {{printers}}`,importToLibrary:`Save`,sliceIn:`Save & Slice in {{slicer}}`,disclaimer:`MakerWorld integration uses community-documented API endpoints. Bambuddy is not affiliated with or endorsed by MakerWorld or Bambu Lab.`,lastImportSuccess:`Imported to your library`,lastImportAlreadyInLibrary:`Already in your library`,viewInLibrary:`View in File Manager`,openInBambuStudio:`Open in Bambu Studio`,openInOrcaSlicer:`Open in OrcaSlicer`,importTo:`Import to file manager`,recentImportsHeader:`Recent imports`,phaseResolving:`Resolving`,phaseDownloading:`Downloading`,folderAuto:`MakerWorld (default)`,importAll:`Import all`,importAllProgress:`Importing {{current}}/{{total}}`,openGallery:`Open image gallery`,galleryPrev:`Previous image`,galleryNext:`Next image`,deleteImport:`Remove from library`,importDeleting:`Removing…`,importDeleted:`Removed from library`,confirmDelete:`Remove {{filename}} from the library? This deletes the local file but the plate can be re-imported from MakerWorld.`,errors:{resolveFailed:`Could not resolve that MakerWorld URL.`,downloadFailed:`Download failed. Please try again.`,deleteFailed:`Could not remove the file from the library.`}},gcodeViewer:{back:`Back`,backToArchives:`Back to Print Archives`,backToFiles:`Back to File Manager`},libraryTrash:{title:`Trash`,headerButton:`Trash`,headerTooltip:`View files moved to the trash`,backToFiles:`Back to File Manager`,subtitleAdmin:`Deleted files stay here for {{days}} days, then auto-delete. This view shows trashed files for all users.`,subtitleUser:`Deleted files stay here for {{days}} days, then auto-delete.`,loading:`Loading trash…`,loadError:`Could not load the trash.`,empty:`The trash is empty.`,summary:`{{count}} files · {{size}}`,emptyTrash:`Empty trash`,restore:`Restore`,purgeNow:`Delete now`,autoPurgeIn:`Auto-deletes in {{when}}`,days:`days`,retentionLabel:`Auto-delete after`,selectAll:`Select all`,selectOne:`Select {{filename}}`,selectionCount:`{{count}} selected`,bulkRestore:`Restore selected`,bulkPurge:`Delete selected`,col:{filename:`File`,folder:`Folder`,size:`Size`,deleted:`Moved to trash`,autoPurge:`Auto-deletes`,owner:`Owner`,actions:`Actions`},confirm:{purgeTitle:`Delete permanently?`,purgeBody:`{{filename}} will be deleted from disk and cannot be restored.`,emptyTitle:`Empty the trash?`,emptyBody:`All {{count}} files will be deleted from disk. This cannot be undone.`,bulkPurgeTitle:`Delete selected files permanently?`,bulkPurgeBody:`The {{count}} selected files will be deleted from disk and cannot be restored.`,cta:`Delete permanently`},toast:{restored:`File restored.`,restoreFailed:`Could not restore the file.`,purged:`File deleted permanently.`,purgeFailed:`Could not delete the file.`,emptied:`Deleted {{count}} file(s) from trash.`,emptyFailed:`Could not empty the trash.`,retentionSaved:`Auto-delete set to {{days}} days.`,retentionFailed:`Could not save retention setting.`,bulkRestored:`Restored {{count}} file(s).`,bulkPurged:`Deleted {{count}} file(s).`}},libraryPurge:{title:`Purge old files`,headerButton:`Purge old`,headerTooltip:`Bulk-move old files to trash`,description:`Sweep old files out of your library in one shot. Files with a print history are aged by their last-printed date; files that were never printed are aged by their upload date.`,ageLabel:`Move files older than`,days:`days`,includeNeverPrinted:`Include files that have never been printed`,effectsTitle:`What happens when you click Purge`,effect1:`Matching files are moved to Trash — they are not deleted from disk yet.`,effect2:`You can restore them from Trash at any time until the retention window expires.`,effect3:`After retention, the trash sweeper permanently removes them from disk.`,effect4:`Files in external (linked) folders are skipped — Bambuddy never deletes bytes it does not own.`,previewLoading:`Checking how many files match…`,previewFailed:`Could not preview the purge.`,previewSummary:`{{count}} files · {{size}} would move to trash`,andMore:`…and {{count}} more`,warning:`Trashed files still count against storage until the retention window expires. Empty the Trash afterwards to free disk immediately.`,confirmCta:`Move {{count}} to trash`,purging:`Moving to trash…`,toast:{success:`Moved {{count}} file(s) to trash.`,failed:`Could not purge files.`}},libraryAutoPurge:{enableLabel:`Auto-purge old files`,enableDescription:`Runs the admin purge once per day. Files go to Trash first — they are not deleted immediately.`,ageLabel:`Auto-purge files older than`,ageDescription:`Minimum 7 days, maximum 10 years. Uses the same age rule as the manual Purge button.`,days:`days`,includeNeverPrinted:`Include files that have never been printed`,saveFailed:`Could not save auto-purge settings.`},archivePurge:{headerButton:`Purge old`,headerTooltip:`Bulk-delete old archives`,title:`Purge old archives`,description:`Clear out old print history. Each archive is aged by its most recent print completion — reprinting an archive refreshes its age, so active work is never purged.`,ageLabel:`Delete archives not printed in the last`,days:`days`,effectsTitle:`What happens when you click Purge`,effect1:`Each matching archive is hidden from the listings and its files are removed from disk (3MF, thumbnail, timelapse, source 3MF, F3D design file, photos).`,effect2:`The archive row stays in the database so Quick Stats keeps the filament, time, cost, and energy contribution — same as the single-archive delete default.`,effect3:`Tick "Also remove from statistics" below to drop the Quick Stats contribution too (matches the single-archive delete option). That path is irreversible.`,effect4:`Reprinting an archive refreshes its age clock, so archives you still use are safe.`,purgeStatsLabel:`Also remove from statistics`,purgeStatsHint:`Drops the matching archives from Quick Stats (filament, time, cost, energy). Without this, Quick Stats keeps every contribution and only the files leave disk.`,previewLoading:`Checking how many archives match…`,previewFailed:`Could not preview the purge.`,previewSummary:`{{count}} archives · {{size}} would be removed`,andMore:`…and {{count}} more`,warning:`Files are removed from disk and cannot be restored. Download or favourite anything you want to keep before continuing.`,confirmCta:`Remove {{count}} archive(s)`,purging:`Removing…`,toast:{success:`Removed {{count}} archive(s).`,failed:`Could not purge archives.`}},archiveAutoPurge:{enableLabel:`Auto-purge old archives`,enableDescription:`Once per day, hides archives from the listings and removes their files from disk when they have not been printed within the threshold. Reprinting an archive resets the clock.`,ageLabel:`Auto-delete archives not printed in the last`,ageDescription:`Minimum 7 days, maximum 10 years. Based on the most recent print completion — reprinting an archive refreshes its age. Removes the 3MF, thumbnail, timelapse, source 3MF, F3D, and photos.`,days:`days`,purgeStatsLabel:`Also remove from statistics`,purgeStatsDescription:`When enabled, the daily sweeper also drops each purged archive from Quick Stats (filament, time, cost, energy). Default off — Quick Stats keeps the contribution, only the files leave disk.`,runNow:`Purge archives now`,saveFailed:`Could not save auto-purge settings.`},cameraTokens:{scope:{camera_stream:`Camera stream`,camwall:`Cam Wall`,overlay:`Streaming Overlay`},title:`Camera API Tokens`,navTitle:`Camera API tokens`,description:`Long-lived tokens for embedding the camera stream into Home Assistant, Frigate, kiosks, or any other tool that needs a stable URL. Pick the scope when you create one; a token can be revoked at any time.`,loading:`Loading…`,confirmRevoke:{title:`Revoke this token?`,body:`Any device using "{{name}}" will lose access immediately. This cannot be undone.`,cancel:`Cancel`,confirm:`Revoke`},create:{scopeLabel:`Scope`,hintCameraStream:`A camera-stream token can only fetch camera streams and snapshots. Use it for Home Assistant, Frigate, or anything embedding a single camera.`,hintCamWall:`A Cam Wall token opens /camwall on a screen with no login. It can see every printer's name and state, and their camera streams. It cannot see filenames, addresses or access codes.`,hintOverlay:`A Streaming Overlay token opens /overlay/{printerId} on a screen with no login — for OBS or any live stream. It can see one printer's camera stream plus its live print status, including the filename shown on screen. It cannot see addresses or access codes.`,title:`Create new token`,nameLabel:`Token name`,namePlaceholder:`e.g. Home Assistant`,daysLabel:`Days until expiry`,submit:`Create`,hint:`Maximum lifetime is 365 days. The token value is shown only once on creation — copy it now.`},created:{camWallUrlTitle:`Cam Wall URL for this display`,camWallUrlHint:`Open this on the screen. Anyone who can read the URL can watch the wall, so treat it like a key — revoke the token to cut the display off.`,overlayUrlTitle:`Overlay URL for OBS`,overlayUrlHint:`Add this as a Browser Source in OBS. Change the /overlay/1 number to your printer's number (from its URL on the Printers page). Anyone who can read the URL can watch the stream, so treat it like a key — revoke the token to cut it off.`,title:`Token created — copy it now`,warning:`This is the only time this token will be visible. After you close this dialog you can never view it again.`,copy:`Copy`,dismiss:`I've saved it`},list:{scope:`Scope`,myTitle:`My tokens`,allTitle:`All users (admin view)`,empty:`No tokens yet.`,name:`Name`,owner:`Owner`,prefix:`Prefix`,created:`Created`,expires:`Expires`,lastUsed:`Last used`,revoke:`Revoke`,expired:`Expired`},toast:{created:`Token created`,createFailed:`Failed to create token`,revoked:`Token revoked`,revokeFailed:`Failed to revoke token`,loadFailed:`Failed to load tokens`,copied:`Copied to clipboard`,copyFailed:`Copy failed — select and copy manually`}},forecast:{title:`Forecast`,noSpools:`No active spools found. Add spools to your inventory to see forecast data.`,noUsageData:`No usage data available — cannot project stock timeline.`,sku:`SKU`,material:`Material`,stock:`Stock`,dailyRate:`Rate`,daysLeft:`Days Left`,emptyBy:`Empty By`,reorderBy:`Reorder By`,actions:`Actions`,trend:`Trend`,estimated:`Est.`,noData:`No data`,timeframe:`Timeframe`,chartTitle:`Projected Stock — Top 5 Materials`,dashedLinesROP:`Dashed lines = reorder points`,stockLevel:`Stock Level`,reorderPoint:`Reorder Point`,safetyMargin:`Safety Margin`,trendLegend:`Trend (history-based, 95% service level)`,estimatedLegend:`Estimated (weight delta)`,noDataLegend:`No data`,ropLabel:`ROP`,ssLabel:`SS`,safetyStockLegend:`Safety stock`,stockArrivalLegend:`Stock arrival`,stockoutLegend:`Stockout`,alertCount_one:`{{count}} alert`,alertCount_other:`{{count}} alerts`,order:`Order`,save:`Save`,cancel:`Cancel`,settingsSaved:`Settings saved`,failedSaveSettings:`Failed to save settings`,globalLeadTimeSaved:`Global lead time saved`,globalLeadTime:`Global lead time`,globalLeadTimeHint:`Global lead time floor — used in reorder point calculation for all SKUs`,skuLeadTimeOverride:`Lead Time Override`,skuLeadTimeHint:`0 = use global lead time. Set >0 to override for this SKU.`,safetyMarginLabel:`Safety Margin`,effectiveLeadTime:`Effective Lead Time`,effectiveLeadTimeHint:`max(global {{global}}d, SKU {{sku}}d)`,reorderPointHint:`d̄ × LT + safety margin — order when stock hits this level`,safetyMarginHint:`Statistical safety stock (z=1.65 × σ × √LT) + user-defined buffer`,safetyMarginHintDays:`Buffer added on top of statistical safety stock.{{approx}}`,safetyMarginHintDaysApprox:` ≈ {{g}}g at current rate.`,safetyMarginHintG:`Fixed weight buffer added on top of statistical safety stock.{{approx}}`,safetyMarginHintGApprox:` ≈ {{days}}d at current rate.`,individualSpools:`Individual spools`,labelWeight:`Label`,spoolCount_one:`{{count}} spool`,spoolCount_other:`{{count}} spools`,stockBreakRisk:`Stock break risk`,stockBreakDetail:`{{days}}d remaining, lead time {{lt}}d.`,stockBreakBefore:`Stock break before replenishment`,reorderNow:`Reorder now`,reorderTriggerPassed:`Trigger date {{date}} has passed.`,shoppingList:`Shopping List`,shoppingListItems_one:`({{count}} item)`,shoppingListItems_other:`({{count}} items)`,shoppingListEmpty:`Shopping list is empty. Click the cart icon on any row to add items.`,addToCart:`Add to shopping list`,alertsSnoozed:`Mute alerts for this SKU`,alertsEnabled:`Unmute alerts for this SKU`,addedToCart:`Added to shopping list`,failedAddItem:`Failed to add item`,listView:`List`,logisticsView:`Logistics`,qty:`Qty`,weight:`Weight`,leadTime:`Lead Time`,expectedRestock:`Expected Restock`,status:`Status`,note:`Note`,pending:`Pending`,purchased:`Purchased`,received:`Received`,markPurchased:`Mark as purchased`,markReceived:`Mark as received — adds spools to Stock inventory`,resetToPending:`Reset to pending`,remove:`Remove`,clearAll:`Clear all`,downloadCsv:`CSV`,addToCartTitle:`Add to Shopping List`,byQuantity:`By Quantity`,byDuration:`By Duration`,numberOfSpools:`Number of spools`,lastHowManyDays:`Should last how many days?`,noUsageQty:`No usage data — quantity set to 1.`,noteOptional:`Note (optional)`,notePlaceholder:`e.g. for project X, urgent…`,addNSpools_one:`Add {{count}} spool`,addNSpools_other:`Add {{count}} spools`,onArrival:`On Arrival`,stockBreakIn:`Stock break in {{days}}d.`,stockRunsOutBefore:`Stock runs out before the {{lt}}d lead time elapses.`,atRate:`At {{rate}}g/day you need`,moreSpools_one:`{{count}} more spool`,moreSpools_other:`{{count}} more spools`,bridgeGap:`to bridge the gap.`,noReadAccess:`You do not have permission to view inventory forecasts.`,noWriteAccess:`You do not have permission to modify forecast settings.`}}},de:{translation:{nav:{printers:`Drucker`,archives:`Archiv`,queue:`Druckwarteschlange`,stats:`Statistiken`,profiles:`Profile`,maintenance:`Wartung`,projects:`Projekte`,inventory:`Filament`,files:`Dateimanager`,makerworld:`MakerWorld`,notifications:`Benachrichtigungen`,settings:`Einstellungen`,system:`System`,collapseSidebar:`Seitenleiste einklappen`,expandSidebar:`Seitenleiste ausklappen`,update:`Aktualisieren`,updateAvailable:`Update verfügbar: v{{version}}`,updateAvailableBanner:`Version {{version}} ist verfügbar!`,viewUpdate:`Update anzeigen`,viewOnGithub:`Auf GitHub ansehen`,keyboardShortcuts:`Tastaturkürzel (?)`,switchToLight:`Zum hellen Modus wechseln`,switchToDark:`Zum dunklen Modus wechseln`,switchToSystem:`Zum Systemmodus wechseln`,smartSwitches:`Smart Switches`,logout:`Abmelden`,installApp:`App installieren`,installAppSuccess:`Bambuddy wurde installiert`},common:{save:`Speichern`,saving:`Speichern...`,cancel:`Abbrechen`,delete:`Löschen`,edit:`Bearbeiten`,add:`Hinzufügen`,close:`Schließen`,confirm:`Bestätigen`,loading:`Lädt...`,error:`Fehler`,errorLoading:`Fehler beim Laden`,retry:`Erneut versuchen`,success:`Erfolg`,warning:`Warnung`,enabled:`Aktiviert`,disabled:`Deaktiviert`,yes:`Ja`,no:`Nein`,on:`An`,off:`Aus`,all:`Alle`,none:`Keine`,search:`Suchen`,filter:`Filtern`,sort:`Sortieren`,refresh:`Aktualisieren`,download:`Herunterladen`,upload:`Hochladen`,uploading:`Hochladen...`,uploadFailed:`Hochladen fehlgeschlagen`,actions:`Aktionen`,status:`Status`,name:`Name`,description:`Beschreibung`,date:`Datum`,time:`Zeit`,hours:`Stunden`,minutes:`Minuten`,seconds:`Sekunden`,days:`Tage`,enable:`Aktivieren`,disable:`Deaktivieren`,permissions:`Berechtigungen`,noPrinters:`Keine Drucker konfiguriert`,noData:`Keine Daten verfügbar`,linkNotFound:`Link nicht gefunden`,required:`Erforderlich`,optional:`Optional`,dismiss:`Schließen`,apply:`Anwenden`,reset:`Zurücksetzen`,export:`Exportieren`,import:`Importieren`,clear:`Leeren`,selectAll:`Alle auswählen`,deselectAll:`Auswahl aufheben`,noChange:`— Keine Änderung —`,unchanged:`Unverändert`,unassigned:`Nicht zugewiesen`,unknown:`Unbekannt`,unknownError:`Unbekannter Fehler`,today:`Heute`,tomorrow:`Morgen`,asap:`Sofort`,overdue:`Überfällig`,now:`Jetzt`,collapse:`Einklappen`,expand:`Ausklappen`,previous:`Zurück`,next:`Weiter`,viewArchive:`Archiv anzeigen`,viewInFileManager:`Im Dateimanager anzeigen`,addedBy:`Hinzugefügt von {{username}}`,prints:`Drucke`,more:`+{{count}} weitere`,ascending:`Aufsteigend`,descending:`Absteigend`,back:`Zurück`,copy:`Kopieren`,copied:`Kopiert!`,printer:`Drucker`,remove:`Entfernen`,type:`Typ`,print:`Drucken`,rename:`Umbenennen`,move:`Verschieben`,create:`Erstellen`,duplicate:`Duplizieren`,left:`Links`,right:`Rechts`},printers:{addPreflight:{checking:`Verbindung wird geprüft...`,warning:`Einige Verbindungsprüfungen sind fehlgeschlagen. Dieser Drucker wird möglicherweise als offline angezeigt. Prüfe die Punkte unten, behebe was möglich ist, oder speichere trotzdem.`,back:`Zurück`,saveAnyway:`Trotzdem speichern`},title:`Drucker`,addPrinter:`Drucker hinzufügen`,editPrinter:`Drucker bearbeiten`,deletePrinter:`Drucker löschen`,printerName:`Druckername`,serialNumber:`Seriennummer`,ipAddress:`IP-Adresse / Hostname`,accessCode:`Zugangscode`,model:`Modell`,nozzleCount:`Düsenanzahl`,autoArchive:`Automatische Archivierung`,status:{available:`Verfügbar`,idle:`Bereit`,printing:`Druckt`,paused:`Pausiert`,offline:`Offline`,problem:`Problem`,error:`Fehler`,finished:`Fertig`,unknown:`Unbekannt`},temperatures:{nozzle:`Düse`,bed:`Druckbett`,chamber:`Kammer`},heaterHistory:{title:`Heizungsverlauf`,openLabel:`Heizungsverlauf anzeigen`,nozzle:`Düse`,nozzle2:`Düse 2`,bed:`Druckbett`,chamber:`Kammer`,error:`Verlauf konnte nicht geladen werden`,empty:`Noch keine Daten aufgezeichnet`},progress:`{{percent}}% abgeschlossen`,timeRemaining:`Noch {{time}}`,deleteConfirm:`Möchten Sie "{{name}}" wirklich löschen?`,maintenanceOk:`Wartung OK`,maintenanceWarning:`{{count}} Warnung`,maintenanceWarning_plural:`{{count}} Warnungen`,maintenanceDue:`{{count}} fällig`,maintenanceDue_plural:`{{count}} fällig`,sort:{name:`Name`,status:`Status`,model:`Modell`,location:`Standort`,eta:`Restzeit`,ascending:`Aufsteigend sortieren`,descending:`Absteigend sortieren`},cardSize:{small:`Kleine Karten`,medium:`Mittlere Karten`,large:`Große Karten`,extraLarge:`Extra große Karten`},pageView:{openCamWallPage:`Kamera-Wand als Seite öffnen`,cards:`Karten`,camWall:`Kamera-Wand`},camWall:{page:{tokenRejected:`Dieser Kamera-Wand-Link ist nicht mehr gültig. Das Token ist möglicherweise abgelaufen oder wurde widerrufen.`,loadFailed:`Die Drucker konnten nicht geladen werden.`},noPrinters:`Keine Drucker anzuzeigen`,noSignal:`Kein Signal`,live:`Live`,snap:`Foto`,off:`Aus`,summary:`{{live}} live, {{snap}} Schnappschüsse, {{total}} insgesamt`,layer:`Schicht {{cur}}/{{total}}`,timeLeft:`noch {{time}}`,statusMode:{off:`Aus`,compact:`Kompakt`,full:`Voll`},settings:{title:`Kamera-Wand-Einstellungen`,maxLive:`Max. Live-Streams`,maxLiveHint:`Wie viele Kacheln gleichzeitig live streamen. Andere aktualisieren als Schnappschüsse.`,snapshotInterval:`Schnappschuss-Intervall (Sekunden)`,snapshotIntervalHint:`Wie oft Nicht-Live-Kacheln einen neuen Schnappschuss abrufen.`,statusOverlay:`Status-Overlay`,statusOverlayHint:`Kompakt: nur Status-Plakette. Voll: + Fortschritt, Schicht, Restzeit.`}},hideOffline:`Offline ausblenden`,nextAvailable:`Nächster verfügbar`,powerOn:`Einschalten`,offlinePrintersWithPlugs:`Offline-Drucker mit Smart-Plugs`,noPrintersConfigured:`Noch keine Drucker konfiguriert`,search:`Drucker suchen...`,noSearchResults:`Keine Drucker entsprechen deiner Suche oder deinen Filtern`,filter:{allStatuses:`Alle Status`,allLocations:`Alle Standorte`},toolbar:{filters:`Filter`,view:`Ansicht`,actions:`Aktionen`},readyToPrint:`Druckbereit`,external:`Extern`,extL:`Ext-L`,extR:`Ext-R`,deleteArchives:`Druckarchive löschen`,noLabel:`Keine Bezeichnung`,printPreview:`Druckvorschau`,width:`Breite`,height:`Höhe`,noObjectsFound:`Keine Objekte gefunden`,objectsLoadedOnPrintStart:`Objekte werden beim Druckstart geladen`,willBeSkipped:`Wird übersprungen`,name:`Name`,serialCannotBeChanged:`Seriennummer kann nicht geändert werden`,locationHelp:`Dient zur Gruppierung von Druckern und zum Filtern von Warteschlangenaufträgen`,wifiSignal:{veryWeak:`Sehr schwach`,weak:`Schwach`,fair:`Ausreichend`,good:`Gut`,excellent:`Ausgezeichnet`},maintenanceUpToDate:`Alle Wartungen aktuell - Klicken zum Anzeigen`,maintenance:{title:`In Wartung`,subtitle:`Dieser Drucker ist pausiert — keine Verbindung, nicht für die Warteschlange verfügbar, keine Benachrichtigungen.`,pillLabel:`Wartung`,exitButton:`Wartung beenden`,menuEnter:`In den Wartungsmodus wechseln`,menuExit:`Wartungsmodus beenden`,toastEntered:`{{name}} ist jetzt im Wartungsmodus`,toastExited:`{{name}} ist wieder online`,confirmMidPrintTitle:`Wartungsmodus während des Drucks aktivieren?`,confirmMidPrintMessage:`{{name}} druckt gerade. Der Wartungsmodus trennt die MQTT-Verbindung und beendet das Fortschritts-Tracking sowie Abschlussbenachrichtigungen für diesen Auftrag. Fortfahren?`,editFieldLabel:`Wartungsmodus`,editFieldHelp:`Wenn aktiviert, ist dieser Drucker von MQTT, Warteschlangenversand und Benachrichtigungen pausiert — nützlich für Reparaturen, parallele Bambuddy-Installationen oder temporäre Außerbetriebnahme.`},chamberLightOn:`Kammerbeleuchtung einschalten`,chamberLightOff:`Kammerbeleuchtung ausschalten`,files:`Dateien`,browseFiles:`Druckerdateien durchsuchen`,autoOffAfterPrint:`Automatisches Ausschalten nach Druck`,autoOffExecuted:`Auto-off wurde ausgeführt - Drucker einschalten zum Zurücksetzen`,hmsErrors:`HMS-Fehler`,viewHmsErrors:`{{count}} HMS-Fehler anzeigen`,resume:`Fortsetzen`,pause:`Pausieren`,stop:`Stoppen`,camera:`Kamera`,skipObject:`Objekt überspringen`,reconnect:`Neu verbinden`,forceRefresh:`Aktualisierung erzwingen`,forceRefreshSuccess:`Aktualisierung angefordert`,mqttDebug:`MQTT-Debug`,printerInformation:`Druckerinformationen`,copyToClipboard:`Kopieren`,copied:`Kopiert!`,state:`Zustand`,wifiSignalLabel:`WLAN-Signal`,developerMode:`Entwicklermodus`,enabled:`Aktiviert`,disabled:`Deaktiviert`,addedOn:`Hinzugefügt`,sdCard:`SD-Karte`,inserted:`Eingelegt`,notInserted:`Nicht eingelegt`,totalPrintHours:`Druckstunden`,activeNozzle:`Aktiv: {{nozzle}} Düse`,nozzleRack:`Düsenhalter`,nozzleDocked:`Angedockt`,nozzleMounted:`Montiert`,nozzleActive:`Aktiv`,nozzleIdle:`Inaktiv`,nozzleDiameter:`Durchmesser`,nozzleType:`Typ`,nozzleStatus:`Status`,nozzleFilament:`Filament`,nozzleWear:`Verschleiß`,nozzleMaxTemp:`Max. Temp`,nozzleSerial:`Seriennr.`,nozzleHardenedSteel:`Gehärteter Stahl`,nozzleStainlessSteel:`Edelstahl`,nozzleTungstenCarbide:`Wolframkarbid`,nozzleFlow:`Durchfluss`,nozzleHighFlow:`Hoher Durchfluss`,nozzleStandardFlow:`Standard`,firmwareUpdate:`Firmware-Update`,firmwareInstructions:`Gehen Sie auf dem Touchscreen des Druckers zu`,firmwareNav:`Navigieren Sie zu`,settings:`Einstellungen`,firmware:`Firmware`,discoverPrinters:`Drucker entdecken`,searching:`Suche...`,manualEntry:`Manuelle Eingabe`,addFromCloud:`Aus Cloud hinzufügen`,toast:{printerDeleted:`Drucker gelöscht`,missingSpoolAssignment:`Druck gestartet auf {{printer}}. Fehlende Spulenzuordnung für: {{slots}}`,assignmentVerified:`Filament in Slot {{slot}} geladen ({{printer}})`,assignmentVerifiedNoKprofile:`Slot {{slot}} auf {{printer}} geladen, aber das Fluss-Kalibrierungsprofil (K-Profil) wurde nicht übernommen`,assignmentNotConfirmed:`Zuordnung für Slot {{slot}} auf {{printer}} konnte nicht bestätigt werden – bitte den AMS-Slot prüfen`,printerAdded:`Drucker hinzugefügt`,printerUpdated:`Drucker aktualisiert`,failedToDelete:`Drucker konnte nicht gelöscht werden`,failedToAdd:`Drucker konnte nicht hinzugefügt werden`,connectionFailedNotAdded:`Keine Verbindung zum Drucker möglich. Prüfen Sie IP-Adresse, Seriennummer und Zugangscode und stellen Sie sicher, dass der Nur-LAN-Modus aktiv ist. Der Drucker wurde nicht hinzugefügt.`,failedToUpdate:`Drucker konnte nicht aktualisiert werden`,commandSent:`Befehl gesendet`,failedToSendCommand:`Befehl konnte nicht gesendet werden`,turnedOn:`{{name}} eingeschaltet`,failedToPowerOn:`{{name}} konnte nicht eingeschaltet werden`,scriptTriggered:`Skript ausgelöst`,printStopped:`Druck gestoppt`,printPaused:`Druck pausiert`,printResumed:`Druck fortgesetzt`,referenceDeleted:`Referenz gelöscht`,detectionAreaSaved:`Erkennungsbereich gespeichert`,failedToRunScript:`Skript konnte nicht ausgeführt werden`,failedToStopPrint:`Druck konnte nicht gestoppt werden`,failedToPausePrint:`Druck konnte nicht pausiert werden`,failedToResumePrint:`Druck konnte nicht fortgesetzt werden`,failedToControlChamberLight:`Kammerbeleuchtung konnte nicht gesteuert werden`,failedToSetSpeed:`Druckgeschwindigkeit konnte nicht eingestellt werden`,failedToUpdateSetting:`Einstellung konnte nicht aktualisiert werden`,failedToSkipObjects:`Objekte konnten nicht übersprungen werden`,failedToRereadRfid:`RFID konnte nicht erneut gelesen werden`,failedToCheckPlate:`Platte konnte nicht überprüft werden`,failedToUpdateLabel:`Bezeichnung konnte nicht aktualisiert werden`,failedToDeleteReference:`Referenz konnte nicht gelöscht werden`,failedToSaveDetectionArea:`Erkennungsbereich konnte nicht gespeichert werden`,plateCheckEnabled:`Plattenprüfung aktiviert`,plateCheckDisabled:`Plattenprüfung deaktiviert`,calibrationSaved:`Kalibrierung gespeichert!`,calibrationFailed:`Kalibrierung fehlgeschlagen`,rfidRereadInitiated:`RFID-Neueinlesen gestartet`,loadInitiated:`Filament wird geladen…`,unloadInitiated:`Filament wird entladen…`,failedToLoad:`Filament konnte nicht geladen werden`,failedToUnload:`Filament konnte nicht entladen werden`},connection:{connected:`Verbunden`,offline:`Offline`},plateStatus:{markCleared:`Platte als freigegeben markieren`,cleared:`Platte freigegeben`,notCleared:`Platte nicht freigegeben`,inUse:`Platte in Benutzung`},queue:{inQueue:`{{count}} Druck in Warteschlange`,inQueue_plural:`{{count}} Drucke in Warteschlange`},controls:`Steuerung`,rfid:{reread:`RFID neu lesen`},ams:{load:`Laden`,unload:`Entladen`},bedJog:{limitWarning:`Verfahrwege werden bei manuellen Bewegungen nicht begrenzt – ein Firmware-Fehler von Bambu ignoriert die Software-Endschalter bei Remote-Befehlen. Bewegen Sie vorsichtig, um Kollisionen zu vermeiden.`,title:`Jog-Steuerung`,bed:`Bett`,step:`Schritt (mm)`,up:`Platte hoch`,down:`Platte runter`,disabledWhilePrinting:`Während des Drucks deaktiviert`,notHomedTitle:`Drucker ist nicht referenziert`,notHomedMessage:`Der Drucker wurde seit dem letzten Druck nicht referenziert. Führen Sie zuerst die automatische Referenzfahrt aus (parkt den Werkzeugkopf und referenziert dann X, Y und Z) oder bewegen Sie trotzdem — die Software-Endschalter werden dabei umgangen.`,homeZ:`Automatische Referenzfahrt`,moveAnyway:`Trotzdem bewegen`,homingStarted:`Drucker wird automatisch referenziert…`},permission:{noAdd:`Sie haben keine Berechtigung, Drucker hinzuzufügen`,noEdit:`Sie haben keine Berechtigung, Drucker zu bearbeiten`,noDelete:`Sie haben keine Berechtigung, Drucker zu löschen`,noControl:`Sie haben keine Berechtigung, Drucker zu steuern`,noFiles:`Sie haben keine Berechtigung, auf Druckerdateien zuzugreifen`,noAmsRfid:`Sie haben keine Berechtigung, AMS-RFID erneut zu lesen`,noSmartPlugControl:`Sie haben keine Berechtigung, Smart Plugs zu steuern`,noCamera:`Sie haben keine Berechtigung, Kameras anzuzeigen`},modal:{addTitle:`Drucker hinzufügen`,editTitle:`Drucker bearbeiten`,myPrinter:`Mein Drucker`,selectModel:`Modell auswählen...`,locationGroup:`Standort / Gruppe (optional)`,locationPlaceholder:`z.B. Werkstatt, Büro, Keller`,autoArchiveLabel:`Abgeschlossene Drucke automatisch archivieren`,fromPrinterSettings:`Aus Druckereinstellungen`,modelOptional:`Modell (optional)`,saveChanges:`Änderungen speichern`},skipObjects:{tooltip:`Objekte überspringen`,onlyWhilePrinting:`Objekte überspringen (nur während des Drucks)`,requiresMultiple:`Objekte überspringen (erfordert 2+ Objekte)`,title:`Objekte überspringen`,matchIdsInfo:`IDs mit Drucker-Display abgleichen`,printerShowsIds:`Der Druckerbildschirm zeigt Objekt-IDs auf der Bauplatte`,skipSelected:`Ausgewählte überspringen`,skipping:`Überspringe...`,noObjectsSelected:`Keine Objekte ausgewählt`,selectObjectsToSkip:`Wählen Sie Objekte aus, die Sie vom aktuellen Druck überspringen möchten`,skipped:`übersprungen`,objectsSkipped:`Objekte übersprungen`,activeCount:`{{count}} aktiv`,waitForLayer:`Warten Sie auf Schicht 2+ zum Überspringen von Objekten (aktuell Schicht {{layer}})`,skip:`Überspringen`,confirmTitle:`Objekt überspringen?`,confirmMessage:`Möchten Sie "{{name}}" wirklich überspringen? Dies kann nicht rückgängig gemacht werden.`,confirmAllMessage:`Alle verbleibenden Objekte sind ausgewählt. Dadurch wird der Druckauftrag beendet. Fortfahren?`,confirmMultipleMessage:`{{count}} ausgewählte Objekte überspringen? Dies kann nicht rückgängig gemacht werden.`},confirm:{deleteTitle:`Drucker löschen`,deleteMessage:`Möchten Sie "{{name}}" wirklich löschen? Alle Verbindungseinstellungen werden entfernt.`,deleteArchivesNote:`Der gesamte Druckverlauf für diesen Drucker wird dauerhaft gelöscht.`,keepArchivesNote:`Der Druckverlauf wird beibehalten, aber nicht mehr mit diesem Drucker verknüpft.`,stopTitle:`Druck stoppen`,stopMessage:`Möchten Sie den aktuellen Druck auf "{{name}}" wirklich stoppen? Der Druckauftrag wird abgebrochen.`,stopButton:`Druck stoppen`,pauseTitle:`Druck pausieren`,pauseMessage:`Möchten Sie den aktuellen Druck auf "{{name}}" wirklich pausieren?`,pauseButton:`Druck pausieren`,resumeTitle:`Druck fortsetzen`,resumeMessage:`Möchten Sie den Druck auf "{{name}}" fortsetzen?`,resumeButton:`Druck fortsetzen`,powerOnTitle:`Drucker einschalten`,powerOnMessage:`Möchten Sie die Stromversorgung für "{{name}}" wirklich EINSCHALTEN?`,powerOnButton:`Einschalten`,powerOffTitle:`Drucker ausschalten`,powerOffMessage:`Möchten Sie die Stromversorgung für "{{name}}" wirklich AUSSCHALTEN?`,powerOffWarning:`WARNUNG: "{{name}}" druckt gerade! Möchten Sie die Stromversorgung wirklich AUSSCHALTEN? Dies unterbricht den Druck und kann den Drucker beschädigen.`,powerOffButton:`Ausschalten`,haToggleTitle:`"{{name}}" umschalten`,haToggleMessage:`Home-Assistant-Entität {{entity}} umschalten? Das kann die Stromversorgung ausschalten, falls sie gerade an ist.`,haToggleWarning:`WARNUNG: "{{name}}" druckt gerade! Umschalten von {{entity}} kann die Stromversorgung trennen und den Druck abbrechen. Fortfahren?`,haToggleButton:`Umschalten`},bulk:{select:`Auswählen`,selectAll:`Alle auswählen`,selectByLocation:`Nach Standort auswählen`,selected:`{{count}} ausgewählt`,actions:{stop:`Stoppen`,pause:`Pausieren`,resume:`Fortsetzen`,clearPlate:`Druckbett leeren`,clearHMS:`Benachrichtigungen löschen`},confirm:{stopTitle:`{{count}} Drucke stoppen`,stopMessage:`Dies wird aktive Drucke auf {{count}} Drucker(n) abbrechen. Diese Aktion kann nicht rückgängig gemacht werden.`,stopButton:`Alle stoppen`,pauseTitle:`{{count}} Drucke pausieren`,pauseMessage:`Dies wird aktive Drucke auf {{count}} Drucker(n) pausieren.`,pauseButton:`Alle pausieren`,clearPlateTitle:`{{count}} Druckbetten leeren`,clearPlateMessage:`Dies wird das Druckbett auf {{count}} Drucker(n) leeren und kann wartende Aufträge starten.`,clearPlateButton:`Alle leeren`},success:`{{action}} auf {{count}} Drucker(n) abgeschlossen`,partial:`{{succeeded}} erfolgreich, {{failed}} fehlgeschlagen`,noneApplicable:`Keine ausgewählten Drucker sind im richtigen Zustand für diese Aktion`,selectByState:`Nach Status auswählen`},discovery:{title:`Drucker entdecken`,searching:`Suche...`,scanning:`Scanne...`,scanProgress:`Scanne... {{scanned}}/{{total}}`,foundPrinters:`{{count}} Drucker gefunden`,noPrintersFound:`Keine Drucker gefunden`,noPrintersFoundSubnet:`Keine Drucker im angegebenen Subnetz gefunden.`,noPrintersFoundNetwork:`Keine Drucker im Netzwerk gefunden.`,allConfigured:`Alle erkannten Drucker sind bereits konfiguriert.`,alreadyAdded:`Bereits hinzugefügt`,select:`Auswählen`,manualEntry:`Manuelle Eingabe`,addFromCloud:`Aus Cloud hinzufügen`,subnetToScan:`Zu scannendes Subnetz`,dockerNote:`Docker erkannt. Geben Sie das Subnetz Ihres Druckers in CIDR-Notation ein. Erfordert network_mode: host in docker-compose.yml.`,scanSubnet:`Subnetz nach Druckern scannen`,discoverNetwork:`Drucker im Netzwerk suchen`,scanningSubnet:`Subnetz wird nach Bambu-Druckern gescannt...`,scanningNetwork:`Netzwerk wird gescannt...`,serialRequired:`Seriennummer erforderlich`,unknown:`Unbekannt`,failedToStart:`Erkennung konnte nicht gestartet werden`,customSubnetOption:`Eigenes Subnetz...`,customSubnetLabel:`Eigenes Subnetz (CIDR)`,customSubnetNote:`Wähle ein eigenes Subnetz, wenn dein Drucker in einem anderen Netzwerk als dieser Server steht. Die Ports FTP (990) und MQTT (8883) müssen über die Routinggrenze erreichbar sein.`},drying:{start:`Trocknung starten`,stop:`Trocknung stoppen`,temperature:`Temperatur`,duration:`Dauer`,hours:`Stunden`,timeRemaining:`{{time}} verbleibend`,active:`Trocknung`,targetSummary:`{{filament}} @ {{temp}}°C`,notSupported:`Trocknung nicht unterstützt`,powerRequired:`AMS-Netzteil anschließen, um Trocknung zu aktivieren`,startingDrying:`Trocknung wird gestartet...`,toastCommandSent:`Trocknungsbefehl gesendet`,toastStopped:`Trocknung gestoppt`,toastNotStarted:`Der Drucker hat den Befehl angenommen, aber das AMS hat die Trocknung nicht gestartet. Prüfe, ob das AMS-Netzteil angeschlossen ist und der Drucker im Leerlauf ist.`,screenOnly:`Die AMS-Trocknung kann bei diesem Drucker nur am Bildschirm des Druckers selbst gesteuert werden (Einschränkung von Bambu)`,stoppingDrying:`Trocknung wird gestoppt...`,rotateTray:`Spule während der Trocknung drehen`,rotateUnavailableReason:`Nicht verfügbar — in diesem AMS ist ein Slot zum Druckkopf hin geladen. Die Spule ist durch den Zuführschlauch blockiert und kann nicht rotieren. Filament zuerst zurückziehen.`},amsBackup:{titleOn:`AMS Filament Backup ist EIN. Zum Deaktivieren klicken.`,titleOff:`AMS Filament Backup ist AUS. Zum Aktivieren klicken.`,titleUnknown:`AMS-Filament-Backup-Status auf diesem Drucker nicht verfügbar.`,toastEnabled:`AMS Filament Backup aktiviert`,toastDisabled:`AMS Filament Backup deaktiviert`,modalTitle:`AMS Filament Backup`,modalHelp:`Wenn der aktive Slot leer wird, wechselt der Drucker in dieser Reihenfolge zu Slots mit demselben Preset und derselben Farbe.`,modalNoSlots:`Kein Filament geladen.`,modalNoPairs:`Keine Backup-Paare — keine zwei Slots teilen sich Filament-Preset und Farbe.`,extruderRightShort:`R`,extruderLeftShort:`L`,stateOn:`Aktiviert`,stateOff:`Deaktiviert`,stateUnknown:`Auf diesem Drucker nicht unterstützt`},activeJobSlot:{title:`Dieser Slot ist Filament {{n}} im aktiven Druck`,ariaLabel:`Aktiver Druck-Slot {{n}}`},expectedSlot:{title:`Der Drucker wartet auf Filament in diesem Slot`,ariaLabel:`Erwarteter Filament-Slot {{n}}`,label:`{{ams}} · Slot {{slot}}`,external:`Externe Spule`},filaments:`Filamente`,openCameraOverlay:`Kamera-Overlay öffnen`,openCameraWindow:`Kamera in neuem Fenster öffnen`,firmwareUpdateAvailable:`Firmware-Update verfügbar: {{current}} → {{latest}}`,firmwareUpToDate:`Firmware {{version}} — Aktuell`,firmwareUpdateButton:`Aktualisieren`,plateDetection:{noPermission:`Sie haben keine Berechtigung, Drucker zu aktualisieren`,enabledClick:`Plattenprüfung aktiviert - Klicken zum Deaktivieren`,disabledClick:`Plattenprüfung deaktiviert - Klicken zum Aktivieren`,manageCalibration:`Platten-Erkennungskalibrierung verwalten`,calibrationRequired:`Kalibrierung erforderlich`,calibrationInstructions:`Bitte stellen Sie sicher, dass die Druckplatte vollständig leer ist, und klicken Sie dann auf Kalibrieren.`,calibrationDescription:`Die Kalibrierung erfasst ein Referenzbild der leeren Platte. Zukünftige Prüfungen vergleichen mit dieser Referenz, um Objekte zu erkennen.`,calibrationTip:`Tipp: Sie können bis zu 5 Kalibrierungen für verschiedene Platten speichern. Das System verwendet automatisch die beste Übereinstimmung bei der Prüfung.`,plateEmpty:`Platte erscheint leer`,objectsDetected:`Objekte auf Platte erkannt`,confidence:`Konfidenz`,difference:`Differenz`,analysisPreview:`Analysevorschau:`,analysisLegend:`Grüner Rahmen = Erkennungsbereich, Rote Überlagerung = Unterschiede zur Kalibrierung`,savedReferences:`Gespeicherte Referenzen ({{count}}/{{max}})`,deleteReference:`Referenz löschen`,labelPlaceholder:`Bezeichnung...`,clickToEdit:`{{label}} - Zum Bearbeiten klicken`,clickToAddLabel:`Zum Hinzufügen einer Bezeichnung klicken`},speed:{title:`Druckgeschwindigkeit`,silent:`Leise (50%)`,standard:`Standard (100%)`,sport:`Sport (124%)`,ludicrous:`Ludicrous (166%)`},airduct:{title:`Luftkanal-Modus`,cooling:`Kühlen`,heating:`Heizen`},noSdCard:`Keine SD`,door:{open:`Offen`,closed:`Zu`},fans:{partCooling:`Bauteilkühlung`,auxiliary:`Hilfsventilator`,leftAuxiliary:`Linker Hilfsventilator`,exhaust:`Abluft`,chamber:`Kammerventilator`},clickToViewHmsErrors:`Klicken, um HMS-Fehler anzuzeigen`,aiDetection:{safe:`Sicher`,warning:`Warnung`,failure:`Fehldruck`,idle:`Bereit`,tooltip:`KI-Fehlererkennung: {{status}} (Score {{score}}) - klicken für Details`,tooltipIdle:`KI-Fehlererkennung aktiviert - Überwachung startet mit dem nächsten Druck - klicken für Details`,modalTitle:`KI-Fehlererkennung - {{name}}`,currentStatus:`Status`,score:`Score`,framesAnalyzed:`Analysierte Bilder`,idleHint:`Derzeit wird kein Druck überwacht. Die Überwachung startet automatisch mit dem nächsten Druck.`,lastError:`Letzter Fehler`,openSettings:`Einstellungen öffnen`},estimatedCompletion:`Geschätzte Fertigstellungszeit`,plateNumber:`Platte {{number}}`,slotOptions:`Slot-Optionen`,amsPopup:{friendlyName:`AMS-Name`,friendlyNamePlaceholder:`z. B. AMS-Anzeigename`,serialNumber:`Seriennummer`,firmwareVersion:`Firmware`,save:`Speichern`,clear:`Löschen`,noEditPermission:`Sie haben keine Berechtigung, AMS-Einheiten umzubenennen`},firmwareModal:{title:`Firmware-Update`,titleUpToDate:`Firmware-Info`,currentVersion:`Aktuell:`,latestVersion:`Neueste:`,releaseNotes:`Versionshinweise`,checkingPrereqs:`Prüfe Voraussetzungen...`,sdCardReady:`SD-Karte bereit. Klicken Sie unten, um die Firmware hochzuladen.`,uploadedSuccess:`Firmware auf SD-Karte hochgeladen!`,applyInstructions:`So wenden Sie das Update auf Ihrem Drucker an:`,step1:`Gehen Sie auf dem Touchscreen des Druckers zu Einstellungen`,step2:`Navigieren Sie zu Firmware`,step3:`Wählen Sie Update von SD-Karte`,step4:`Das Update dauert 10-20 Minuten`,done:`Fertig`,starting:`Starte...`,uploadFirmware:`Firmware hochladen`,uploadFailed:`Upload fehlgeschlagen: {{error}}`,uploadedToast:`Firmware hochgeladen! Starten Sie das Update vom Druckerbildschirm.`,availableVersions:`Verfügbare Versionen`,usable:`Installierbar`,unavailable:`Nicht verfügbar`,installed:`Installiert`,newerBadge:`neuer`,olderBadge:`älter`,currentBadge:`aktuell`},accessCodePlaceholder:`Leer lassen, um den aktuellen zu behalten`,roi:{title:`Erkennungsbereich (ROI)`,xStart:`X-Start`,yStart:`Y-Start`,width:`Breite`,height:`Höhe`,instruction:`Passen Sie den Erkennungsbereich an, um sich auf die Druckplatte zu konzentrieren. Der grüne Rahmen in der Vorschau zeigt den aktuellen Bereich.`},developerModeWarning:`Der Entwickler-LAN-Modus ist nicht aktiviert auf: {{names}}. Einige Funktionen funktionieren möglicherweise nicht.`,howToEnable:`Aktivieren`,incompatibleFile:`Diese Datei wurde für {{slicedFor}} geslicet, aber dieser Drucker ist ein {{printerModel}}`,dropNotPrintable:`Nur .gcode- und .gcode.3mf-Dateien können gedruckt werden`,dropToPrint:`Zum Drucken ablegen`,cannotPrint:`Drucker beschäftigt`},archives:{title:`Druckarchiv`,no3mfBanner:{title:`Einige kürzliche Drucke konnten nicht mit Vorschaubild archiviert werden`,body:`Der Slicer hat die .gcode.3mf-Datei nicht auf der SD-Karte des Druckers hinterlegt, daher konnte Bambuddy weder Vorschaubild noch Slicer-Metadaten abrufen. Üblicherweise liegt das daran, dass "Gesendete Dateien auf externem Speicher speichern" im Slicer (Geräte-Tab in Bambu Studio / OrcaSlicer) deaktiviert ist.`,docsLink:`Installationsschritt 4 anzeigen`,dismissLabel:`Hinweis schließen`},searchPlaceholder:`Archiv durchsuchen...`,filterByPrinter:`Nach Drucker filtern`,filterByStatus:`Nach Status filtern`,sortBy:`Sortieren nach`,sortNewest:`Neueste zuerst`,sortOldest:`Älteste zuerst`,sortName:`Name`,sortDuration:`Dauer`,sortLargest:`Größte zuerst`,sortSmallest:`Kleinste zuerst`,sortSize:`Größe`,noArchives:`Keine Archive gefunden`,noArchivesSearch:`Keine Archive entsprechen Ihrer Suche`,originalPrintNotVisible:`Ursprünglicher Druck nicht sichtbar - versuchen Sie, die Filter zu löschen`,noArchivesYet:`Noch keine Archive`,prints:`Drucke`,pagination:{showing:`Zeige`,to:`bis`,of:`von`,show:`Zeige`,page:`Seite`,all:`Alle`},loadingArchives:`Lade Archive...`,releaseToUpload:`Loslassen zum Hochladen`,showAll:`Alle anzeigen`,showFavoritesOnly:`Nur Favoriten anzeigen`,gridView:`Rasteransicht`,listView:`Listenansicht`,calendarView:`Kalenderansicht`,logView:`Druckprotokoll`,manageTags:`Tags verwalten`,showFailedPrints:`Fehlgeschlagene Drucke anzeigen`,hideFailedPrints:`Fehlgeschlagene Drucke ausblenden`,hideDuplicates:`Duplikate ausblenden`,viewOriginalPrint:`Klicken, um den ursprünglichen Druck anzuzeigen (#{{id}})`,printTime:`Druckzeit`,filamentUsed:`Verbrauchtes Filament`,cost:`Kosten`,preview:`Vorschau`,deleteArchive:`Archiv löschen`,deleteConfirm:`Möchten Sie dieses Archiv wirklich löschen?`,favorite:`Favorit`,unfavorite:`Aus Favoriten entfernen`,viewDetails:`Details anzeigen`,status:{completed:`Abgeschlossen`,failed:`Fehlgeschlagen`,stopped:`Gestoppt`},toast:{source3mfAttached:`Quell-3MF angehängt: {{filename}}`,failedUploadSource3mf:`Fehler beim Hochladen der Quell-3MF`,source3mfRemoved:`Quell-3MF entfernt`,failedRemoveSource3mf:`Fehler beim Entfernen der Quell-3MF`,f3dAttached:`F3D angehängt: {{filename}}`,failedUploadF3d:`Fehler beim Hochladen der F3D`,f3dRemoved:`F3D entfernt`,failedRemoveF3d:`Fehler beim Entfernen der F3D`,timelapseAttached:`Zeitraffer angehängt: {{filename}}`,timelapseAlreadyAttached:`Zeitraffer bereits angehängt`,noMatchingTimelapse:`Kein passender Zeitraffer gefunden`,failedScanTimelapse:`Fehler beim Suchen nach Zeitraffer`,failedAttachTimelapse:`Fehler beim Anhängen des Zeitraffers`,timelapseRemoved:`Zeitraffer entfernt`,failedRemoveTimelapse:`Fehler beim Entfernen des Zeitraffers`,timelapseUploaded:`Zeitraffer hochgeladen: {{filename}}`,failedUploadTimelapse:`Fehler beim Hochladen des Zeitraffers`,archiveDeleted:`Archiv gelöscht`,failedDeleteArchive:`Fehler beim Löschen des Archivs`,addedToFavorites:`Zu Favoriten hinzugefügt`,removedFromFavorites:`Aus Favoriten entfernt`,projectUpdated:`Projekt aktualisiert`,failedUpdateProject:`Fehler beim Aktualisieren des Projekts`,linkCopied:`Link in die Zwischenablage kopiert`,failedCopyLink:`Fehler beim Kopieren des Links`,photoDeleted:`Foto gelöscht`,failedDeletePhoto:`Fehler beim Löschen des Fotos`,failedDeleteArchives:`Fehler beim Löschen der Archive`,failedUpdateFavorites:`Fehler beim Aktualisieren der Favoriten`,exportDownloaded:`Export heruntergeladen`,exportFailed:`Export fehlgeschlagen`},menu:{print:`Drucken`,openInBambuStudio:`Im Slicer öffnen`,slice:`Slicen`,externalLink:`Externer Link`,viewOnMakerWorld:`Auf MakerWorld ansehen`,preview3d:`3D-Vorschau`,viewTimelapse:`Zeitraffer ansehen`,scanForTimelapse:`Nach Zeitraffer suchen`,uploadTimelapse:`Zeitraffer hochladen`,removeTimelapse:`Zeitraffer entfernen`,downloadSource3mf:`Quell-3MF herunterladen`,uploadSource3mf:`Quell-3MF hochladen`,replaceSource3mf:`Quell-3MF ersetzen`,removeSource3mf:`Quell-3MF entfernen`,uploadF3d:`F3D hochladen`,replaceF3d:`F3D ersetzen`,downloadF3d:`F3D herunterladen`,removeF3d:`F3D entfernen`,download:`Herunterladen`,copyDownloadLink:`Download-Link kopieren`,qrCode:`QR-Code`,viewPhotos:`Fotos ansehen`,viewPhotosCount:`Fotos ansehen ({{count}})`,projectPage:`Projektseite`,addToFavorites:`Zu Favoriten hinzufügen`,removeFromFavorites:`Aus Favoriten entfernen`,edit:`Bearbeiten`,printLog:`Druckprotokoll`,goToProject:`Zum Projekt: {{name}}`,addToProject:`Zu Projekt hinzufügen`,removeFromProject:`Aus Projekt entfernen`,loading:`Laden...`,noProjectsAvailable:`Keine Projekte verfügbar`,searchProjects:`Projekte suchen…`,select:`Auswählen`,deselect:`Abwählen`,delete:`Löschen`},permission:{noReprint:`Sie haben keine Berechtigung, dieses Archiv erneut zu drucken`,noAddToQueue:`Sie haben keine Berechtigung, zur Warteschlange hinzuzufügen`,noUpdateArchives:`Sie haben keine Berechtigung, Archive zu aktualisieren`,noUploadFiles:`Sie haben keine Berechtigung, Dateien hochzuladen`,noDownload:`Sie haben keine Berechtigung, Archive herunterzuladen`,noCopyLink:`Sie haben keine Berechtigung, Download-Links zu kopieren`,noDelete:`Sie haben keine Berechtigung, dieses Archiv zu löschen`,noEdit:`Sie haben keine Berechtigung, diesen Eintrag zu bearbeiten`,noCreate:`Sie haben keine Berechtigung, Archive zu erstellen`},platePicker:{title:`Platte zur Vorschau auswählen`,hint:`Dieses Archiv enthält mehrere Platten. Wähle eine, um sie im GCode-Viewer zu öffnen.`,plateLabel:`Platte {{index}}`,objectCount:`{{count}} Objekt`,objectCount_plural:`{{count}} Objekte`,noGcode:`Dieses Archiv enthält keinen geschnittenen G-Code zur Vorschau. Öffne es zuerst in Bambu Studio zum Slicen.`},card:{previousPlate:`Vorherige Platte`,nextPlate:`Nächste Platte`,plateNumber:`Platte {{index}}`,moreOptions:`Rechtsklick für mehr Optionen`,addToFavorites:`Zu Favoriten hinzufügen`,removeFromFavorites:`Aus Favoriten entfernen`,cancelled:`abgebrochen`,failed:`fehlgeschlagen`,duplicate:`Duplikat`,duplicateTitle:`Dieses Modell wurde bereits zuvor gedruckt`,openSource3mf:`Quell-3MF in Bambu Studio öffnen (Rechtsklick für mehr Optionen)`,downloadF3d:`Fusion 360 Designdatei herunterladen`,viewTimelapse:`Zeitraffer ansehen`,viewPhoto:`1 Foto ansehen`,viewPhotos:`{{count}} Fotos ansehen`,openFolder:`Ordner öffnen: {{name}}`,slicedFile:`Geslicte Datei - druckbereit`,sourceFile:`Nur Quelldatei - keine AMS-Zuordnung verfügbar`,gcode:`GCODE`,source:`QUELLE`,project:`Projekt: {{name}}`,runsBadge:`{{count}} Drucke`,runsBadgeTitle:`Insgesamt {{count}} Drucke — {{successful}} erfolgreich, {{failed}} fehlgeschlagen. Klicken, um das vollständige Druckprotokoll zu öffnen.`,estimated:`Geschätzt: {{time}}`,actual:`Tatsächlich: {{time}}`,accuracy:`Genauigkeit: {{percent}}%`,filament:`{{weight}} g`,layer:`{{count}} Schicht`,layers:`{{count}} Schichten`,object:`{{count}} Objekt`,objects:`{{count}} Objekte`,slicedFor:`Geslict für {{model}}`,uploadedBy:`Hochgeladen von`,noPermissionReprint:`Sie haben keine Berechtigung, erneut zu drucken`,noFileForReprint:`Keine 3MF-Datei verfügbar — die Datei konnte beim Aufzeichnen des Drucks nicht vom Drucker heruntergeladen werden`,slicerAmsMapping:`AMS-Zuordnung gespeichert ({{printer}})`,slicerAmsMappingTooltip:`Die AMS-Steckplatzwahl des Slicers wurde für {{printer}} gespeichert. Steckplatznummern gelten nur für diesen Drucker, daher wird sie bei einem erneuten Druck nur wiederverwendet, wenn er wieder an {{printer}} geht.`,noPermissionEdit:`Sie haben keine Berechtigung, Archive zu bearbeiten`,noPermissionDelete:`Sie haben keine Berechtigung, Archive zu löschen`,openInBambuStudio:`Im Slicer öffnen`,openInBambuStudioToSlice:`Im Slicer öffnen zum Slicen`,slice:`Slicen`,externalLink:`Externer Link`,makerWorld:`MakerWorld – {{designer}}`,viewProject:`Projekt ansehen`,noExternalLink:`Kein externer Link`,preview3d:`3D-Vorschau`,download:`Herunterladen`,edit:`Bearbeiten`,delete:`Löschen`},runLog:{title:`Druckprotokoll`,modalTitle:`Druckprotokoll — {{name}}`,modalTitleFallback:`dieses Archiv`,empty:`Für dieses Archiv wurden noch keine Druckereignisse aufgezeichnet.`,col:{date:`Datum`,status:`Status`,duration:`Dauer`,filament:`Filament`,cost:`Kosten`},status:{completed:`Abgeschlossen`,failed:`Fehlgeschlagen`,cancelled:`Abgebrochen`,stopped:`Gestoppt`,skipped:`Übersprungen`,printing:`Druckt`}},modal:{deleteArchive:`Archiv löschen`,deleteConfirm:`Möchten Sie "{{name}}" wirklich löschen? Diese Aktion kann nicht rückgängig gemacht werden.`,deleteButton:`Löschen`,deletePurgeStats:`Diesen Druck auch aus den Quick Stats entfernen (Filament, Zeit, Kosten, Energie)`,deleteQueueItemsWarning:`{{count}} mit diesem Archiv verknüpfte Warteschlangeneinträge werden ebenfalls entfernt.`,deleteBlockedByPrinting:`Löschen nicht möglich — {{count}} Warteschlangeneinträge werden derzeit gedruckt. Druck zuerst stoppen und erneut versuchen.`,removeSource3mf:`Quell-3MF entfernen`,removeSource3mfConfirm:`Möchten Sie die Quell-3MF-Datei wirklich von "{{name}}" entfernen? Die ursprüngliche Slicer-Projektdatei wird gelöscht.`,removeButton:`Entfernen`,removeF3d:`F3D entfernen`,removeF3dConfirm:`Möchten Sie die Fusion 360 Designdatei wirklich von "{{name}}" entfernen?`,removeTimelapse:`Zeitraffer entfernen`,removeTimelapseConfirm:`Möchten Sie das Zeitraffervideo wirklich von "{{name}}" entfernen?`,timelapse:`{{name}} - Zeitraffer`,selectTimelapse:`Zeitraffer auswählen`,selectTimelapseDesc:`Keine automatische Übereinstimmung gefunden. Wählen Sie den Zeitraffer für diesen Druck:`,deleteArchives:`Archive löschen`,deleteArchivesConfirm:`Möchten Sie wirklich {{count}} Archiv(e) löschen? Diese Aktion kann nicht rückgängig gemacht werden.`,deleteCount:`{{count}} löschen`},page:{title:`Archive`,printsCount:`{{filtered}} von {{total}} Drucken`,dropFilesHere:`.3mf-Dateien hier ablegen`,releaseToUpload:`Loslassen zum Hochladen`,only3mfSupported:`Nur .3mf-Dateien werden unterstützt`,close:`Schließen`,selected:`{{count}} ausgewählt`,selectAll:`Alle auswählen`,tags:`Tags`,project:`Projekt`,favorite:`Favorit`,delete:`Löschen`,toggledFavorites:`Favoriten für {{count}} Archiv(e) umgeschaltet`,failedUpdateFavorites:`Fehler beim Aktualisieren der Favoriten`,archivesDeleted:`{{count}} Archiv(e) gelöscht`,failedDeleteArchives:`Fehler beim Löschen der Archive`,photoDeleted:`Foto gelöscht`,failedDeletePhoto:`Fehler beim Löschen des Fotos`},list:{name:`Name`,printer:`Drucker`,date:`Datum`,size:`Größe`,actions:`Aktionen`,hasTimelapse:`Hat Zeitraffer`},log:{date:`Datum`,printName:`Druckname`,printer:`Drucker`,user:`Benutzer`,status:`Status`,duration:`Dauer`,filament:`Filament`,allPrinters:`Alle Drucker`,allUsers:`Alle Benutzer`,allStatuses:`Alle Status`,cancelled:`Abgebrochen`,skipped:`Übersprungen`,dateFrom:`Von`,dateTo:`Bis`,noEntries:`Keine Druckprotokolleinträge gefunden`,showing:`{{count}} von {{total}} Einträgen`,rowsPerPage:`Zeilen`,page:`Seite`,prev:`Zurück`,next:`Weiter`,clearLog:`Protokoll löschen`,clearLogTitle:`Druckprotokoll löschen`,clearLogConfirm:`Alle Druckprotokolleinträge werden dauerhaft gelöscht. Archive und Warteschlangeneinträge sind nicht betroffen. Diese Aktion kann nicht rückgängig gemacht werden. Sind Sie sicher?`,clearLogButton:`Alle löschen`,cleared:`{{count}} Protokolleinträge gelöscht`,clearFailed:`Druckprotokoll konnte nicht gelöscht werden`,deleteEntryTitle:`Druckprotokoll-Eintrag löschen`,deleteEntryConfirm:`Dieser Eintrag wird aus dem Protokoll entfernt und sein Filament-, Zeit- und Kostenbeitrag verschwindet aus den Schnellstatistiken. Das zugehörige Archiv (falls vorhanden) ist nicht betroffen. Diese Aktion kann nicht rückgängig gemacht werden.`,entryDeleted:`Druckprotokoll-Eintrag gelöscht`,entryDeleteFailed:`Druckprotokoll-Eintrag konnte nicht gelöscht werden`,editEntryTitle:`Druckprotokoll-Eintrag bearbeiten`,editEntryDescription:`Diesen Druckdurchlauf klassifizieren. Das Fehleranalyse-Widget gruppiert nach diesen Werten, sodass Aktualisierungen sofort in die Statistik einfließen.`,entryUpdated:`Druckprotokoll-Eintrag aktualisiert`,entryUpdateFailed:`Druckprotokoll-Eintrag konnte nicht aktualisiert werden`,statuses:{completed:`Abgeschlossen`,failed:`Fehlgeschlagen`,stopped:`Gestoppt`,cancelled:`Abgebrochen`,skipped:`Übersprungen`}}},dispatchToast:{untitled:`Druckjob`,startingPrints:`Drucke starten`,progressSummary:`{{complete}}/{{total}} fertig • Verarbeitung: {{processing}}`,expandDetails:`Versanddetails ausklappen`,collapseDetails:`Versanddetails einklappen`,awaitingPrinter:`Warte auf Drucker…`,status:{processing:`Verarbeitung`,completed:`Fertig`,failed:`Fehlgeschlagen`},failed:{generic:`Versand fehlgeschlagen`,upload_failed:`Upload zum Drucker fehlgeschlagen`,start_command_failed:`Drucker hat Startbefehl abgelehnt`},dismiss:`Schließen`},pipelineRuns:{title:`Pipeline-Läufe`,loading:`Wird geladen…`,empty:`Noch keine Pipeline-Läufe.`,filter:{pipeline:`Pipeline`,status:`Status`,target:`Ziel`,all:`Alle`,allPipelines:`Alle Pipelines`,allStatus:`Alle Status`,allTargets:`Alle Ziele`,clear:`Filter zurücksetzen`,noMatches:`Keine Läufe entsprechen den aktuellen Filtern.`},totalCount_one:`{{n}} Lauf`,totalCount_other:`{{n}} Läufe`,copies:`{{n}} Kopien`,failedCount:`{{n}} fehlgeschlagen`,copyN:`Kopie {{n}}`,retryFailed:`Fehlgeschlagene wiederholen`,retryOf:`Wiederholung von #{{n}}`,pagination:`{{start}}–{{end}} von {{total}}`,toast:{cancelled:`Lauf abgebrochen`,cancelFailed:`Abbruch fehlgeschlagen`,retryStarted:`Wiederholung gestartet`,retryFailed:`Wiederholung fehlgeschlagen`,cleared:`{{n}} Läufe gelöscht`,clearFailed:`Löschen fehlgeschlagen`},clearLog:`Verlauf löschen`,clearConfirmTitle:`Verlauf löschen?`,clearConfirmBody:`Jeden abgeschlossenen, fehlgeschlagenen, abgebrochenen und teilweise fehlgeschlagenen Pipeline-Lauf löschen? Laufende Läufe bleiben erhalten. Dies kann nicht rückgängig gemacht werden.`,clearConfirmAction:`Löschen`,jobStatus:{pending:`ausstehend`,awaiting_printer:`wartet auf Drucker`,queued:`in Warteschlange`,printing:`druckt`,completed:`abgeschlossen`,failed:`fehlgeschlagen`,cancelled:`abgebrochen`},cancelledByUser:`Vom Benutzer abgebrochen`},queue:{filamentShort:{rowBadge:`Filament fuer die zugewiesene Spule reicht nicht`,rowTooltip:`Der Dispatcher hat diese Position markiert. Klicke auf Play, um den Pro-Slot-Fehlbestand zu sehen und zu entscheiden, ob trotzdem gedruckt werden soll.`,confirmTitle:`Filament reicht nicht`,confirmIntro:`Die zugewiesene Spule kann mindestens einen Slot nicht versorgen. Trotzdem drucken?`,lineItem:`Slot {{slot}}: benoetigt {{required}} g, {{remaining}} g verbleibend`,unknown:`unbekannt`,printAnyway:`Trotzdem drucken`},slicerAmsMapping:{rowBadge:`AMS-Steckplätze für diesen Drucker gespeichert`,rowTooltip:`Dieses Archiv enthält die genauen AMS-Steckplätze, die der Slicer ausgewählt hat, gespeichert für den Drucker dieses Eintrags. Ein erneuter Druck darauf kann diese Fächer wiederverwenden, statt erneut nach Typ und Farbe zuzuordnen.`},title:`Druckwarteschlange`,subtitle:`Planen und verwalten Sie Ihre Druckaufträge`,editQueueItem:`Warteschlangeneintrag bearbeiten`,selectAllPlates:`Alle {{count}} Platten auswählen`,deselectAll:`Alle abwählen`,printQueued:`Druck in Warteschlange`,printQueuedWillStartWhenIdle:`Startet, sobald der Drucker im Leerlauf ist`,itemsQueued:`{{count}} Einträge in Warteschlange`,sending:`Wird gesendet...`,sendingProgress:`Sende {{current}}/{{total}}...`,adding:`Wird hinzugefügt...`,addingProgress:`Füge hinzu {{current}}/{{total}}...`,savingProgress:`Speichere {{current}}/{{total}}...`,clearQueue:`Warteschlange leeren`,clearHistory:`Verlauf löschen`,emptyQueue:`Warteschlange ist leer`,position:`Position`,scheduledTime:`Geplante Zeit`,moveUp:`Nach oben`,moveDown:`Nach unten`,startNow:`Jetzt starten`,printingInProgress:`Druck läuft...`,viewArchive:`Archiv anzeigen`,viewInFileManager:`Im Dateimanager anzeigen`,itemCount:`{{count}} Element`,itemCount_plural:`{{count}} Elemente`,dragToReorder:`Ziehen zum Neuordnen (nur Sofort)`,reorderHint:`Position betrifft nur Sofort-Elemente. Geplante Elemente werden zur festgelegten Zeit ausgeführt.`,sjf:{label:`SJF`,tooltip:`Kürzester Auftrag zuerst — Scheduler bevorzugt kürzere Drucke`},addedBy:`Hinzugefügt von {{name}}`,nextInQueue:`Nächster in der Warteschlange`,clearPlateSuccess:`Druckplatte freigegeben — bereit für nächsten Druck`,plateNumber:`Platte {{index}}`,quantity:`Menge`,quantityHint:`Erstellt {{count}} Warteschlangeneinträge`,activeBatches:`Aktive Stapel`,batchProgress:`{{completed}} von {{total}} abgeschlossen`,cancelBatch:`Verbleibende abbrechen`,batchCancelled:`Verbleibende Stapeleinträge abgebrochen`,cancelBatchConfirmTitle:`Stapel abbrechen`,cancelBatchConfirmMessage:`Alle verbleibenden ausstehenden Einträge in diesem Stapel abbrechen?`,batch:{defaultName:`Stapel`,label:`{{count}} Eintrag`,label_plural:`{{count}} Einträge`,pendingCount:`{{count}} ausstehend`,pendingCount_plural:`{{count}} ausstehend`,expand:`Stapel ausklappen`,collapse:`Stapel einklappen`,groupAsBatch:`Als Stapel gruppieren…`,groupAsBatchDescription:`Fasse die {{count}} ausgewählten Einträge zu einem einklappbaren Stapel zusammen.`,nameLabel:`Stapelname`,namePlaceholder:`z. B. Freitagsgeschenke`,create:`Stapel erstellen`,ungroup:`Gruppierung aufheben`,ungroupConfirmTitle:`Stapel auflösen?`,ungroupConfirmMessage:`Die Einträge bleiben in der Warteschlange, sind aber nicht mehr gruppiert.`,dragGroup:`Gruppe ziehen`},tabs:{queue:`Warteschlange`,history:`Verlauf`,timeline:`Zeitachse`,pipelines:`Druckabläufe`},layout:{flatList:`Liste`,byPrinter:`Nach Drucker`,groupByPrinter:`Nach Drucker gruppieren`},history:{emptyTitle:`Noch kein Verlauf`,emptyDescription:`Abgeschlossene, abgebrochene und fehlgeschlagene Drucke erscheinen hier.`,showMore:`Mehr anzeigen`,showingCount:`{{shown}} von {{total}} werden angezeigt`},dragGhost:{multiCount:`{{count}} Einträge`,batch:`{{name}} ({{count}} Kopie)`,batch_plural:`{{name}} ({{count}} Kopien)`},sections:{currentlyPrinting:`Aktuell druckend`,queued:`In Warteschlange`,history:`Verlauf`},status:{pending:`Ausstehend`,waiting:`Wartend`,printing:`Druckt`,paused:`Pausiert`,completed:`Abgeschlossen`,failed:`Fehlgeschlagen`,skipped:`Übersprungen`,cancelled:`Abgebrochen`},summary:{printing:`Druckt`,queued:`In Warteschlange`,totalTime:`Gesamte Wartezeit`,totalWeight:`Gesamtgewicht der Warteschlange`,history:`Verlauf`},filter:{allPrinters:`Alle Drucker`,unassigned:`Nicht zugewiesen`,allStatus:`Alle Status`,allLocations:`Alle Standorte`,any:`Beliebig`},sort:{byPosition:`Nach Position sortieren`,byName:`Nach Name sortieren`,byPrinter:`Nach Drucker sortieren`,bySchedule:`Nach Zeitplan sortieren`,byDate:`Nach Datum sortieren`,ascendingOldest:`Aufsteigend (älteste zuerst)`,descendingNewest:`Absteigend (neueste zuerst)`},badges:{staged:`Bereitgestellt`,requiresPrevious:`Erfordert vorherigen Erfolg`,autoPowerOff:`Automatisch ausschalten`,gcodeInjection:`G-Code`},empty:{title:`Keine Drucke geplant`,description:`Planen Sie einen Druck von der Archivseite über die Option "Planen" im Kontextmenü oder ziehen Sie Dateien hierher.`},time:{etaIfStartedNow:`Fertigstellungszeit, wenn dieser Auftrag jetzt starten würde`,asap:`Sofort`,overdue:`Überfällig`,now:`Jetzt`,lessThanMinute:`In weniger als einer Minute`,inMinutes:`In {{count}} Min`,inHours:`In {{count}} Stunden`},actions:{startPrint:`Druck starten`,stopPrint:`Druck stoppen`,requeue:`Erneut einreihen`},bulkEdit:{title:`{{count}} Element bearbeiten`,title_plural:`{{count}} Elemente bearbeiten`,description:`Nur geänderte Einstellungen werden auf ausgewählte Elemente angewendet.`,printer:`Drucker`,noChange:`— Keine Änderung —`,queueOptions:`Warteschlangenoptionen`,staged:`Bereitgestellt (manueller Start)`,autoPowerOff:`Nach Druck automatisch ausschalten`,requirePrevious:`Vorherigen Erfolg erfordern`,printOptions:`Druckoptionen`,bedLevelling:`Bett-Nivellierung`,flowCalibration:`Fluss-Kalibrierung`,vibrationCalibration:`Vibrations-Kalibrierung`,layerInspection:`Erste-Schicht-Prüfung`,timelapse:`Zeitraffer`,useAms:`AMS verwenden`,nozzleOffsetCali:`Düsenversatz-Kalibrierung`,applyChanges:`Änderungen übernehmen`,selectAll:`Alle auswählen`,deselectAll:`Auswahl aufheben`,selected:`{{count}} ausgewählt`,editSelected:`Ausgewählte bearbeiten`,cancelSelected:`Ausgewählte abbrechen`},confirm:{cancelTitle:`Geplanten Druck abbrechen`,cancelMessage:`Möchten Sie "{{name}}" wirklich abbrechen?`,stopTitle:`Druck stoppen`,stopMessage:`Möchten Sie den aktuellen Druck "{{name}}" wirklich stoppen? Der Druckauftrag wird am Drucker abgebrochen.`,removeTitle:`Aus Verlauf entfernen`,removeMessage:`Möchten Sie "{{name}}" wirklich aus dem Warteschlangenverlauf entfernen?`,clearHistoryTitle:`Verlauf löschen`,clearHistoryMessage:`Möchten Sie alle {{count}} Element(e) aus dem Verlauf entfernen?`,cancelButton:`Druck abbrechen`,stopButton:`Druck stoppen`,thisPrint:`diesen Druck`,thisItem:`dieses Element`},toast:{cancelled:`Warteschlangenelement abgebrochen`,cancelFailed:`Element konnte nicht abgebrochen werden`,removed:`Warteschlangenelement entfernt`,removeFailed:`Element konnte nicht entfernt werden`,stopped:`Druck gestoppt`,stopFailed:`Druck konnte nicht gestoppt werden`,released:`Druck in Warteschlange freigegeben`,startFailed:`Druck konnte nicht gestartet werden`,reorderFailed:`Warteschlange konnte nicht neu geordnet werden`,historyCleared:`{{count}} Verlaufselement(e) gelöscht`,clearHistoryFailed:`Verlauf konnte nicht gelöscht werden`,updateFailed:`Elemente konnten nicht aktualisiert werden`,bulkCancelled:`{{count}} Element(e) abgebrochen`,bulkCancelFailed:`Elemente konnten nicht abgebrochen werden`,batchCreated:`Stapel „{{name}}“ erstellt`,batchCreateFailed:`Stapel konnte nicht erstellt werden`,batchUngrouped:`{{count}} Eintrag/Einträge aus Stapel gelöst`,batchUngroupFailed:`Stapel konnte nicht aufgelöst werden`,resumedAfterFailure:`Warteschlange fortgesetzt — {{restored}} Auftrag/Aufträge wieder eingereiht`,resumeAfterFailureFailed:`Warteschlange konnte nicht fortgesetzt werden`},resumeAfterFailure:{banner:`{{printer}} ist durch einen vorherigen Druckfehler blockiert — {{count}} Auftrag/Aufträge übersprungen`,bannerHint:`Behebe das Druckerproblem und setze die Warteschlange dann fort, um die übersprungenen Aufträge wiederherzustellen und die Sperre aufzuheben.`,button:`Nach Fehler fortsetzen`,confirmTitle:`Warteschlange nach Fehler fortsetzen?`,confirmMessage:`Setze {{count}} übersprungenen Auftrag/Aufträge auf {{printer}} wieder auf „Ausstehend“ und hebe die Vorgängersperre auf. Stelle vorher sicher, dass der Drucker bereit ist.`},timeline:{listView:`Liste`,timelineView:`Zeitstrahl`,unassigned:`Nicht zugewiesen`,noData:`Keine geplanten Drucke für diesen Tag`,nothingCommitted:`Keine festgelegten Pläne in diesem Zeitfenster. Vorgemerkte Einträge, wartende Einträge und ASAP-Aufträge auf inaktiven Druckern werden nicht angezeigt — leg eine geplante Zeit fest oder gib einen vorgemerkten Eintrag frei, damit er hier erscheint.`,allDoneBy:`Alle Drucke voraussichtlich fertig um {{time}}`,staged:`Bereitgestellt`,filterAll:`Alle anzeigen`,filterPrinting:`Druckend`,filterQueued:`Warteschlange`,time:{anyMoment:`jeden Moment`,minutesLeft:`{{minutes}}m übrig`,hoursLeft:`{{hours}}h übrig`,hoursMinutesLeft:`{{hours}}h {{minutes}}m übrig`},day:{previous:`Vorheriger Tag`,next:`Nächster Tag`,today:`Heute`},window:{back12h:`12 Stunden zurück`,forward12h:`12 Stunden vor`,now:`Jetzt`},printerColumnHeader:`Drucker`},permissions:{noStopPrint:`Sie haben keine Berechtigung, Drucke zu stoppen`,noStartPrint:`Sie haben keine Berechtigung, Drucke zu starten`,noEdit:`Sie haben keine Berechtigung, dieses Warteschlangenelement zu bearbeiten`,noCancel:`Sie haben keine Berechtigung, dieses Warteschlangenelement abzubrechen`,noRequeue:`Sie haben keine Berechtigung, Elemente erneut einzureihen`,noRemove:`Sie haben keine Berechtigung, dieses Warteschlangenelement zu entfernen`,noClearHistory:`Sie haben keine Berechtigung, den gesamten Verlauf zu löschen`,noEditItems:`Sie haben keine Berechtigung, Warteschlangenelemente zu bearbeiten`,noCancelItems:`Sie haben keine Berechtigung, Warteschlangenelemente abzubrechen`}},stats:{title:`Statistiken`,subtitle:`Widgets zum Neuanordnen ziehen. Auf das Augensymbol klicken zum Ausblenden.`,overview:`Übersicht`,totalPrints:`Gesamtdrucke`,successRate:`Erfolgsrate`,totalPrintTime:`Gesamtdruckzeit`,printTime:`Druckzeit`,totalFilament:`Gesamtverbrauch Filament`,filamentUsed:`Filamentverbrauch`,filamentCost:`Filamentkosten`,totalCost:`Gesamtkosten`,energyUsed:`Energieverbrauch`,energyCost:`Energiekosten`,energyWarmingUpTooltip:`Die Energieerfassung sammelt noch stündliche Snapshots. Zeitraumwerte werden genau, sobald vor dem gewählten Bereich mindestens ein Snapshot vorliegt. Frühe Werte können zu niedrig sein.`,averagePrintTime:`Durchschnittliche Druckzeit`,printsPerDay:`Drucke pro Tag`,byPrinter:`Nach Drucker`,printsByPrinter:`Drucke nach Drucker`,byMaterial:`Nach Material`,byMonth:`Nach Monat`,last7Days:`Letzte 7 Tage`,last30Days:`Letzte 30 Tage`,last90Days:`Letzte 90 Tage`,allTime:`Gesamt`,quickStats:`Schnellstatistiken`,printActivity:`Druckaktivität`,filamentTypes:`Filamenttypen`,filamentTrends:`Filamenttrends`,failureAnalysis:`Fehleranalyse`,timeAccuracy:`Zeitgenauigkeit`,successful:`Erfolgreich:`,failed:`Fehlgeschlagen:`,cancelled:`Abgebrochen:`,perfectEstimate:`100% = perfekte Schätzung`,noTimeAccuracyData:`Noch keine Zeitgenauigkeitsdaten`,noFilamentData:`Keine Filamentdaten verfügbar`,noPrinterData:`Keine Druckerdaten verfügbar`,noPrintData:`Keine Druckdaten verfügbar`,noPrintDataLast30Days:`Keine Druckdaten in den letzten 30 Tagen`,failureReasons:`Fehlerursachen`,topFailureReasons:`Häufigste Fehlerursachen`,failedPrintsCount:`{{failed}} / {{total}} Drucke fehlgeschlagen`,lastWeekRate:`Letzte Woche: {{rate}}%`,resetLayout:`Layout zurücksetzen`,recalculateCosts:`Kosten neu berechnen`,recalculateCostsHint:`Alle Archivkosten mit aktuellen Filamentpreisen neu berechnen`,exportStats:`Statistiken exportieren`,exportAsCsv:`Als CSV exportieren`,exportAsExcel:`Als Excel exportieren`,hiddenCount:`{{count}} ausgeblendet`,exportDownloaded:`Export heruntergeladen`,exportFailed:`Export fehlgeschlagen`,layoutReset:`Layout zurückgesetzt`,recalculatedCosts:`Kosten für {{count}} Archive neu berechnet`,recalculateFailed:`Kosten konnten nicht neu berechnet werden`,loadingStats:`Statistiken werden geladen...`,noPermissionResetLayout:`Sie haben keine Berechtigung, das Layout zurückzusetzen`,noPermissionRecalculate:`Sie haben keine Berechtigung, Kosten neu zu berechnen`,noPrintDataInRange:`Keine Druckdaten im ausgewählten Zeitraum`,periodFilament:`Filamentverbrauch`,periodCost:`Kosten`,avgPerPrint:`Durchschnitt pro Druck`,usageOverTime:`Verbrauch im Zeitverlauf`,energyOverTime:`Energie im Zeitverlauf`,filamentByWeight:`Gewicht`,printDuration:`Druckdauer`,printerUtilization:`Druckerauslastung`,filamentSuccess:`Erfolg nach Material`,printHabits:`Druckgewohnheiten`,printTimeOfDay:`Druck-Tageszeit`,colorDistribution:`Farbverteilung`,noColorData:`Keine Farbdaten verfügbar`,records:`Rekorde`,longestPrint:`Längster Druck`,heaviestPrint:`Schwerster Druck`,mostExpensivePrint:`Teuerster Druck`,busiestDay:`Aktivster Tag`,successStreak:`Erfolgsserie`,streakPrint:`aufeinanderfolgender Druck`,streakPrints:`{{count}} aufeinanderfolgende Drucke`,printerStats:`Druckerstatistiken`,hours:`Stunden`,avgPrints:`Ø Drucke`,noArchiveData:`Keine Druckdaten verfügbar`,filamentByTime:`Zeitverlauf`,avgWeight:`Ø Gewicht`,avgTime:`Ø Zeit`,filamentByPrints:`Drucke`,timeframe:{today:`Heute`,"this-week":`Diese Woche`,"this-month":`Dieser Monat`,"last-7":`Letzte 7 Tage`,"last-30":`Letzte 30 Tage`,"last-90":`Letzte 90 Tage`,"this-year":`Dieses Jahr`,"all-time":`Gesamt`,custom:`Benutzerdefiniert`,from:`Von`,to:`Bis`},allUsers:`Alle Benutzer`,noUser:`Kein Benutzer (System)`,filterByUser:`Nach Benutzer filtern`},maintenance:{title:`Wartung`,overview:`Übersicht`,allOk:`Alle Wartungen aktuell`,dueCount:`{{count}} Aufgabe fällig`,dueCount_plural:`{{count}} Aufgaben fällig`,warningCount:`{{count}} Warnung`,warningCount_plural:`{{count}} Warnungen`,totalPrintTime:`Gesamtdruckzeit`,nextMaintenance:`Nächste Wartung`,nothingDue:`Nichts fällig`,tasks:`Aufgaben`,lastPerformed:`Zuletzt durchgeführt`,interval:`Intervall`,hoursRemaining:`{{hours}}h verbleibend`,hoursOverdue:`{{hours}}h überfällig`,markDone:`Als erledigt markieren`,performMaintenance:`Wartung durchführen`,history:`Verlauf`,noHistory:`Kein Wartungsverlauf`,editPrintHours:`Druckstunden bearbeiten`,currentHours:`Aktuelle Stunden`,statusTab:`Status`,settingsTab:`Einstellungen`,overdueCount:`{{count}} überfällig`,dueSoonCount:`{{count}} bald fällig`,dueSoon:`Bald fällig`,allGood:`Alles in Ordnung`,overdueBy:`Überfällig um {{duration}}`,dueIn:`Fällig in {{duration}}`,timeLeft:`{{duration}} verbleibend`,day:`1 Tag`,days:`{{count}} Tage`,week:`1 Woche`,weeks:`{{count}} Wochen`,month:`1 Monat`,months:`{{count}} Monate`,year:`1 Jahr`,maintenanceTypes:`Wartungstypen`,maintenanceTypesDescription:`Systemtypen und Ihre benutzerdefinierten Wartungsaufgaben`,addCustomType:`Benutzerdefinierten Typ hinzufügen`,restoreDefaults:`Standardaufgaben wiederherstellen`,intervalType:`Intervalltyp`,intervalValue:`Intervall ({{type}})`,icon:`Symbol`,documentationLink:`Dokumentationslink (optional)`,assignToPrinters:`Druckern zuweisen`,selectAtLeastOnePrinter:`Wählen Sie mindestens einen Drucker`,addType:`Typ hinzufügen`,custom:`Benutzerdefiniert`,printHours:`Druckstunden`,calendarDays:`Kalendertage`,exampleName:`z.B. HEPA-Filter ersetzen`,viewDocumentation:`Dokumentation anzeigen`,timeBasedInterval:`Zeitbasiertes Intervall`,intervalOverrides:`Intervall-Überschreibungen`,intervalOverridesDescription:`Intervalle für bestimmte Drucker anpassen`,assignedToPrinters:`Druckern zugewiesen:`,noPrintersAssigned:`Keine Drucker zugewiesen`,addPrinterShort:`Hinzufügen:`,printersAssignedClick:`{{count}} Drucker zugewiesen - klicken zum Verwalten`,removeFromPrinter:`Von diesem Drucker entfernen`,types:{lubricateCarbonRods:`Karbonstäbe schmieren`,lubricateRails:`Linearschienen schmieren`,cleanNozzle:`Düse/Hotend reinigen`,checkBelts:`Riemenspannung prüfen`,cleanBuildPlate:`Druckbett reinigen`,checkExtruder:`Extruderzahnräder prüfen`,checkCooling:`Kühlungslüfter prüfen`,generalInspection:`Allgemeine Inspektion`,cleanCarbonRods:`Kohlenstoffstangen reinigen`,lubricateSteelRods:`Stahlstangen schmieren`,cleanSteelRods:`Stahlstangen reinigen`,cleanLinearRails:`Linearschienen reinigen`,checkPtfeTube:`PTFE-Schlauch prüfen`,replaceHepaFilter:`HEPA-Filter ersetzen`,replaceCarbonFilter:`Aktivkohlefilter ersetzen`,lubricateLeftNozzleRail:`Linke Düsenschiene schmieren`},maintenanceComplete:`Wartung als abgeschlossen markiert`,typeUpdated:`Wartungstyp aktualisiert`,typeDeleted:`Wartungstyp gelöscht`,defaultsRestored:`{{count}} Standardaufgabe(n) wiederhergestellt`,printHoursUpdated:`Druckstunden aktualisiert`,printerAssigned:`Drucker zugewiesen`,printerRemoved:`Drucker entfernt`,deleteTypeConfirm:`"{{name}}" löschen?`,deleteSystemTypeTitle:`Standard-Wartungsaufgabe löschen?`,deleteSystemTypeMessage:`Möchten Sie die Standard-Wartungsaufgabe "{{name}}" wirklich löschen?`,noPermissionUpdate:`Sie haben keine Berechtigung, Wartungselemente zu aktualisieren`,noPermissionPerform:`Sie haben keine Berechtigung, Wartungen durchzuführen`,noPermissionEditTypes:`Sie haben keine Berechtigung, Wartungstypen zu bearbeiten`,noPermissionDeleteTypes:`Sie haben keine Berechtigung, Wartungstypen zu löschen`,noPermissionEditHours:`Sie haben keine Berechtigung, Druckstunden zu bearbeiten`,noPermissionRemovePrinter:`Sie haben keine Berechtigung, Druckerzuweisungen zu entfernen`,noPermissionAssignPrinter:`Sie haben keine Berechtigung, Drucker zuzuweisen`,noPermissionEditIntervals:`Sie haben keine Berechtigung, Intervalle zu bearbeiten`,configureSettings:`Wartungstypen und Intervalle konfigurieren`},settings:{title:`Einstellungen`,general:`Allgemein`,tabs:{general:`Allgemein`,smartPlugs:`Smart Plugs`,notifications:`Benachrichtigungen`,queue:`Workflow`,queueDispatch:`Warteschlange & Dispatch`,queuePipelines:`Pipelines`,filament:`Filament`,network:`Netzwerk`,apiKeys:`API-Schlüssel`,virtualPrinter:`Virtueller Drucker`,spoolbuddy:`SpoolBuddy`,failureDetection:`Fehlererkennung`,users:`Authentifizierung`,backup:`Sicherung`,emailAuth:`E-Mail-Authentifizierung`,ldap:`LDAP`,twoFa:`Zwei-Faktor-Auth`,oidc:`SSO / OIDC`,security:`Sicherheit`},spoolbuddy:{infoTitle:`SpoolBuddy-Geräte`,infoBody:`SpoolBuddy-Kioske registrieren sich automatisch per Heartbeat. Ein Gerät hier abmelden, wenn es nicht mehr verwendet wird oder wenn ein veralteter Eintrag nach einem Daemon-Absturz übrig geblieben ist.`,duplicatesTitle:`{{count}} Geräte registriert`,duplicatesBody:`Die Kiosk-Oberfläche verwendet nur das zuerst registrierte Gerät. Falls eines davon ein veralteter Doppeleintrag nach einem Absturz ist, kann es hier entfernt werden — ein laufendes Gerät registriert sich beim nächsten Heartbeat automatisch neu.`,empty:`Noch keine SpoolBuddy-Geräte registriert.`,online:`Online`,offline:`Offline`,unregister:`Abmelden`,unregisterSuccess:`Gerät abgemeldet`,unregisterError:`Gerät konnte nicht abgemeldet werden`,confirmTitle:`SpoolBuddy-Gerät abmelden?`,confirmBody:`Dies entfernt „{{hostname}}" ({{deviceId}}) aus der Datenbank. Ein laufendes Gerät registriert sich beim nächsten Heartbeat automatisch neu.`,ipAddress:`IP-Adresse`,firmware:`Firmware`,lastSeen:`Zuletzt gesehen`,daemonUptime:`Daemon-Laufzeit`,systemUptime:`System-Laufzeit`,never:`nie`,nfc:`NFC`,scale:`Waage`,cpuTemp:`CPU-Temp.`,cpuLoad:`CPU-Last`,memory:`Speicher`,disk:`Festplatte`,update:`Aktualisieren`,updateConfirmTitle:`Spoolbuddy-Daemon aktualisieren?`,updateConfirmBody:`Software-Update auf „{{hostname}}" auslösen? Der Daemon startet nach dem Update neu.`,restartBrowser:`Browser neu starten`,restartBrowserConfirmTitle:`Kiosk-Browser neu starten?`,restartBrowserConfirmBody:`Kiosk-Browser auf „{{hostname}}" neu starten? Die Anzeige wird kurz schwarz.`,restartDaemon:`Daemon neu starten`,restartDaemonConfirmTitle:`Spoolbuddy-Daemon neu starten?`,restartDaemonConfirmBody:`Spoolbuddy-Daemon auf „{{hostname}}" neu starten? Das Gerät ist für einige Sekunden offline.`,reboot:`Neustart`,rebootConfirmTitle:`Gerät neu starten?`,rebootConfirmBody:`„{{hostname}}" neu starten? Das Gerät ist für etwa eine Minute offline.`,shutdown:`Herunterfahren`,shutdownConfirmTitle:`Gerät herunterfahren?`,shutdownConfirmBody:`„{{hostname}}" herunterfahren? Physischer Zugriff ist nötig, um es wieder einzuschalten.`,commandConfirm:`Bestätigen`,commandQueued:`Befehl eingereiht`,commandError:`Befehl konnte nicht gesendet werden`},ldap:{title:`LDAP-Authentifizierung`,enabledDesc:`LDAP-Authentifizierung ist aktiviert`,disabledDesc:`LDAP-Authentifizierung ist deaktiviert`,disabledHint:`LDAP-Einstellungen unten konfigurieren und speichern, dann aktivieren.`,enabled:`LDAP-Authentifizierung aktiviert`,disabled:`LDAP-Authentifizierung deaktiviert`,feature1:`Benutzer können sich mit LDAP-Anmeldedaten anmelden`,feature2:`Lokales Admin-Konto bleibt als Fallback erhalten`,feature3:`LDAP-Gruppen werden bei der Anmeldung BamBuddy-Gruppen zugeordnet`,serverConfig:`LDAP-Server-Konfiguration`,serverUrl:`Server-URL`,serverUrlHint:`Verwenden Sie ldap:// für Standard oder ldaps:// für SSL-Verbindungen`,security:`Sicherheit`,securityHint:`StartTLS aktualisiert eine einfache Verbindung auf TLS. LDAPS verwendet TLS von Anfang an.`,bindDn:`Bind-DN (Dienstkonto)`,bindPassword:`Bind-Passwort`,searchBase:`Such-Basis-DN`,userFilter:`Benutzer-Suchfilter`,userFilterHint:`{username} wird durch den Anmeldenamen ersetzt. Verwenden Sie (uid={username}) für OpenLDAP.`,advanced:`Erweitert`,autoProvision:`Benutzer automatisch anlegen`,autoProvisionHint:`Automatisch ein BamBuddy-Konto bei der ersten LDAP-Anmeldung erstellen`,defaultGroup:`Standardgruppe`,defaultGroupNone:`— Keine (kein Fallback) —`,defaultGroupHint:`Fallback-Gruppe, die zugewiesen wird, wenn sich ein LDAP-Benutzer authentifiziert, aber in keiner zugeordneten LDAP-Gruppe enthalten ist. Leer lassen, um nicht zugeordnete Benutzer ohne Berechtigungen zu belassen.`,groupMapping:`Gruppenzuordnung (JSON)`,groupMappingHint:`LDAP-Gruppen-DNs BamBuddy-Gruppen zuordnen. Verfügbare Gruppen: `,testConnection:`Verbindung testen`,settingsSaved:`LDAP-Einstellungen gespeichert`,errors:{serverRequired:`LDAP-Server-URL ist erforderlich`,searchBaseRequired:`Such-Basis-DN ist erforderlich`,enableAuthFirst:`Authentifizierung zuerst aktivieren`,configureLdapFirst:`LDAP-Einstellungen zuerst speichern`}},email:{smtpSettings:`SMTP-Konfiguration`,smtpHost:`SMTP-Server`,smtpPort:`SMTP-Port`,security:`Sicherheit`,authentication:`Authentifizierung`,username:`Benutzername`,password:`Passwort`,fromEmail:`Absender-E-Mail`,fromName:`Absendername`,testConnection:`SMTP-Verbindung testen`,testRecipient:`Test-Empfänger-E-Mail`,sendTest:`Test-E-Mail senden`,sending:`Wird gesendet...`,save:`Einstellungen speichern`,saving:`Wird gespeichert...`,advancedAuth:`Erweiterte Authentifizierung`,advancedAuthEnabled:`Erweiterte Authentifizierung ist aktiviert`,advancedAuthEnabledDesc:`E-Mail-basierte Benutzerverwaltungsfunktionen sind aktiv. Neue Benutzer erhalten automatisch generierte Passwörter per E-Mail und können ihr Passwort über die Passwort vergessen Funktion zurücksetzen.`,advancedAuthDisabled:`Erweiterte Authentifizierung ist deaktiviert`,advancedAuthDisabledDesc:`Aktivieren Sie die erweiterte Authentifizierung, um E-Mail-basierte Funktionen für die Benutzerverwaltung zu aktivieren.`,enable:`Aktivieren`,disable:`Deaktivieren`,feature1:`Passwörter werden automatisch generiert und an neue Benutzer gesendet`,feature2:`Benutzer können sich mit Benutzername oder E-Mail anmelden`,feature3:`Passwort vergessen Funktion ist verfügbar`,feature4:`Administratoren können Benutzerpasswörter per E-Mail zurücksetzen`,errors:{requiredFields:`Bitte füllen Sie alle Pflichtfelder aus`,usernameRequired:`Benutzername ist erforderlich, wenn Authentifizierung aktiviert ist`,enterTestEmail:`Bitte geben Sie eine Test-E-Mail-Adresse ein`,smtpServerAndEmail:`Bitte füllen Sie SMTP-Server und Absender-E-Mail aus, bevor Sie testen`,usernamePasswordRequired:`Benutzername und Passwort sind erforderlich, wenn Authentifizierung aktiviert ist`,configureSmtpFirst:`Bitte konfigurieren und testen Sie zuerst die SMTP-Einstellungen`,enableAuthFirst:`Bitte aktivieren Sie zuerst die Authentifizierung, um E-Mail-basierte Funktionen nutzen zu können.`},success:{settingsSaved:`SMTP-Einstellungen erfolgreich gespeichert`},securityOptions:{starttls:`STARTTLS (Port 587)`,ssl:`SSL/TLS (Port 465)`,none:`Keine (Port 25)`},authOptions:{enabled:`Aktiviert`,disabled:`Deaktiviert`}},appearance:`Erscheinungsbild`,notifications:`Benachrichtigungen`,smartPlugs:`Smart Plugs`,spoolman:`Spoolman`,updates:`Aktualisierungen`,language:`Sprache`,languageDescription:`Wählen Sie Ihre bevorzugte Sprache`,theme:`Design`,themeLight:`Hell`,themeDark:`Dunkel`,themeSystem:`System`,defaultView:`Standardansicht`,defaultViewDescription:`Seite, die beim Öffnen der App angezeigt wird`,checkForUpdates:`Nach Updates suchen`,autoUpdate:`Automatische Updates`,currentVersion:`Aktuelle Version`,latestVersion:`Neueste Version`,upToDate:`Sie sind auf dem neuesten Stand`,updateAvailable:`Update verfügbar`,notificationLanguage:`Benachrichtigungssprache`,notificationLanguageDescription:`Sprache für Push-Benachrichtigungen`,bedCooledThreshold:`Bett-Abkühlung Schwellenwert`,bedCooledThresholdDescription:`Temperatur, unter der das Bett nach einem Druck als abgekühlt gilt`,userNotificationsEnabled:`Benutzerbenachrichtigungen`,userNotificationsEnabledDescription:`Aktiviert das Benutzerbenachrichtigungsmenü und E-Mail-Benachrichtigungen für Druckereignisse. Erfordert Erweiterte Authentifizierung.`,userNotificationsDisabledHint:`Erweiterte Authentifizierung aktivieren, um Benutzerbenachrichtigungen zu verwenden.`,notificationProviders:`Benachrichtigungsanbieter`,addProvider:`Anbieter hinzufügen`,editProvider:`Anbieter bearbeiten`,providerType:`Anbietertyp`,testNotification:`Testbenachrichtigung`,testSuccess:`Testbenachrichtigung erfolgreich gesendet`,testFailed:`Testbenachrichtigung konnte nicht gesendet werden`,quietHours:`Ruhezeiten`,quietHoursDescription:`Keine Störungen während dieser Zeiten`,quietHoursStart:`Beginn`,quietHoursEnd:`Ende`,events:{title:`Benachrichtigungsereignisse`,printStart:`Druck gestartet`,printComplete:`Druck abgeschlossen`,printFailed:`Druck fehlgeschlagen`,printStopped:`Druck gestoppt`,printProgress:`Fortschrittsmeldungen`,printProgressDescription:`Bei 25%, 50%, 75% benachrichtigen`,printerOffline:`Drucker offline`,printerError:`Druckerfehler`,filamentLow:`Filament niedrig`,maintenanceDue:`Wartung fällig`,maintenanceDueDescription:`Benachrichtigen, wenn Wartung erforderlich`},smartPlug:{title:`Smart Plugs`,add:`Smart Plug hinzufügen`,edit:`Smart Plug bearbeiten`,name:`Name`,ipAddress:`IP-Adresse`,linkedPrinter:`Verknüpfter Drucker`,autoOn:`Automatisch einschalten`,autoOnDescription:`Einschalten beim Druckstart`,autoOff:`Automatisch ausschalten`,autoOffDescription:`Ausschalten nach Druckende`,offDelay:`Ausschaltverzögerung`,offDelayMinutes:`Minuten nach Druck`,offDelayTemp:`Wenn Düse unter Temperatur`,currentState:`Aktueller Status`,turnOn:`Einschalten`,turnOff:`Ausschalten`},filamentTracking:`Filament-Verfolgung`,filamentTrackingDesc:`Wählen Sie, wie Sie Ihre Filamentspulen verfolgen möchten. Sie können das integrierte Inventar oder einen externen Spoolman-Server verwenden.`,autoAddUnknownRfid:`Unbekannte RFID-Spulen automatisch hinzufügen`,autoAddUnknownRfidDesc:`Erstellt automatisch einen Inventareintrag, wenn eine Spule mit unbekanntem RFID-Tag erkannt wird. Deaktivieren, wenn Sie neue Spulen vorab manuell anlegen, um Duplikate zu vermeiden.`,filamentChecks:`Filament-Prüfungen`,disableFilamentWarnings:`Filament-Warnungen deaktivieren`,disableFilamentWarningsDesc:`Keine Warnungen über unzureichendes Filament beim Drucken oder Einreihen anzeigen`,preferLowestFilament:`Niedrigsten Filamentrest bevorzugen`,preferLowestFilamentDesc:`Bei mehreren passenden Spulen die mit dem geringsten Restfilament verwenden`,preferLowestFilamentBackupNote:`Wirkt nur, wenn AMS Filament Backup am Drucker aktiviert ist — sonst kann der Drucker beim Aufbrauchen der ersten Spule nicht auf eine zweite Spule wechseln.`,trackingModeBuiltIn:`Integriertes Inventar`,trackingModeBuiltInDesc:`RFID-Erkennung und Verbrauchserfassung inklusive`,trackingModeSpoolmanDesc:`Externer Filament-Management-Server`,builtInFeatureRfid:`Erkennt automatisch Bambu Lab RFID-Spulen im AMS`,builtInFeatureUsage:`Erfasst den Filamentverbrauch pro Druck`,builtInFeatureCatalog:`Spulen, Farben und K-Faktor-Profile verwalten`,builtInFeatureThirdParty:`Drittanbieter-Spulen können Inventarspulen zugewiesen werden`,amsSyncButton:`Gewichte vom AMS synchronisieren`,amsSyncTitle:`Spulengewichte vom AMS synchronisieren`,amsSyncMessage:`Alle Inventar-Spulengewichte werden mit den aktuellen AMS-Restwerten der verbundenen Drucker überschrieben. Verwenden Sie dies zur Wiederherstellung beschädigter Gewichtsdaten. Drucker müssen online sein.`,amsSyncing:`Synchronisiere...`,amsSyncSuccess:`{{synced}} Spule(n) synchronisiert, {{skipped}} übersprungen`,amsSyncError:`Synchronisierung der Gewichte vom AMS fehlgeschlagen`,spoolmanAmsSyncButton:`Spoolman-Gewichte vom AMS synchronisieren`,spoolmanAmsSyncTitle:`Spoolman-Spulengewichte vom AMS synchronisieren`,spoolmanAmsSyncMessage:`Dabei werden alle Spoolman-Spulengewichte anhand der aktuellen AMS-Füllstandswerte der verbundenen Drucker aktualisiert. Die Drucker müssen online sein.`,spoolmanAmsSyncing:`Synchronisiere...`,spoolmanAmsSyncSuccess:`{{synced}} Spule(n) synchronisiert, {{skipped}} übersprungen`,spoolmanAmsSyncError:`Synchronisierung der Spoolman-Gewichte vom AMS fehlgeschlagen`,spoolmanAmsSyncErrorUnreachable:`Synchronisierung fehlgeschlagen (Spoolman nicht erreichbar)`,spoolmanAmsSyncErrorNotConfigured:`Synchronisierung fehlgeschlagen (Spoolman nicht konfiguriert)`,spoolmanNotConfigured:`Spoolman nicht konfiguriert`,spoolmanFilamentCatalogTitle:`Spoolman-Filamentkatalog`,spoolmanFilamentCatalogDesc:`Filamentnamen und Leergewichte aus deiner Spoolman-Instanz. Name und Spulengewicht sind hier editierbar; alle anderen Eigenschaften werden direkt in Spoolman verwaltet.`,spoolmanUrl:`Spoolman URL`,spoolmanUrlHint:`URL Ihres Spoolman-Servers (z.B. http://localhost:7912)`,spoolmanConnected:`Verbunden`,spoolmanDisconnected:`Nicht verbunden`,status:`Status`,connect:`Verbinden`,disconnect:`Trennen`,howSyncWorks:`So funktioniert die Synchronisierung`,syncInfoRfidOnly:`Nur offizielle Bambu Lab Spulen mit RFID werden synchronisiert`,syncInfoAutoCreate:`Neue Spulen werden bei der ersten Synchronisierung automatisch in Spoolman erstellt`,syncInfoThirdPartySkipped:`Nicht-Bambu-Lab-Spulen (Drittanbieter, nachgefüllt) werden übersprungen`,linkingExistingSpools:`Vorhandene Spulen verknüpfen`,linkingExistingSpoolsDesc:`Um vorhandene Spoolman-Spulen mit Ihrem AMS zu verknüpfen, fahren Sie über einen AMS-Slot und klicken Sie auf "Mit Spoolman verknüpfen".`,syncMode:`Synchronisierungsmodus`,syncModeAuto:`Automatisch`,syncModeManual:`Nur manuell`,syncModeAutoDesc:`AMS-Daten werden automatisch synchronisiert, wenn Änderungen erkannt werden`,syncModeManualDesc:`Nur bei manueller Auslösung synchronisieren`,syncAmsData:`AMS-Daten synchronisieren`,syncAmsDataDesc:`AMS-Daten des Druckers manuell mit Spoolman synchronisieren`,allPrinters:`Alle Drucker`,noDefaultPrinter:`Kein Standard (jedes Mal fragen)`,sidebarOrder:`Seitenleisten-Reihenfolge`,saveThumbnails:`Vorschaubilder speichern`,captureFinishPhoto:`Abschlussfoto aufnehmen`,noPrintersConfigured:`Keine Drucker konfiguriert`,archiveMode:{always:`Immer Archiveintrag erstellen`,never:`Nie Archiveintrag erstellen`,ask:`Jedes Mal fragen`},checkForUpdatesLabel:`Nach Updates suchen`,checkPrinterFirmware:`Drucker-Firmware prüfen`,includeBetaUpdates:`Beta-Versionen einschließen`,includeBetaUpdatesDesc:`Über Beta- und Vorabversionen bei der Updateprüfung benachrichtigen`,localLogin:{disable:`Lokale Benutzername-/Passwort-Anmeldung deaktivieren`,disableHint:`Wenn aktiviert, ist nur die Anmeldung über SSO möglich. LDAP ist davon nicht betroffen. Setzen Sie BAMBUDDY_LOCAL_LOGIN=true auf dem Server, um einen Wiederherstellungsweg offen zu halten.`},enableRetry:`Wiederholung aktivieren`,homeAssistantDescription:`Smart Plugs über Home Assistant steuern`,environmentManagedLabel:`(Umgebungsvariable)`,autoEnabledViaEnv:`Automatisch über Umgebungsvariablen aktiviert`,urlFromEnvReadOnly:`Wert wird über HA_URL Umgebungsvariable gesetzt (schreibgeschützt)`,tokenFromEnvReadOnly:`Wert wird über HA_TOKEN Umgebungsvariable gesetzt (schreibgeschützt)`,mqttConnectedTo:`Verbunden mit`,prometheusDescription:`Druckerdaten im Prometheus-Format bereitstellen`,noSmartPlugsTitle:`Keine Smart Plugs konfiguriert`,noSmartPlugsDescription:`Fügen Sie einen Tasmota-basierten Smart Plug hinzu, um den Energieverbrauch zu verfolgen und die Stromsteuerung zu automatisieren.`,noProvidersTitle:`Keine Anbieter konfiguriert`,noProvidersDescription:`Fügen Sie einen Anbieter hinzu, um Benachrichtigungen zu erhalten.`,noTemplatesAvailable:`Keine Vorlagen verfügbar. Starten Sie das Backend neu, um Standardvorlagen zu laden.`,apiPermissionView:`Druckerstatus und Warteschlange anzeigen`,apiPermissionEdit:`Elemente zur Druckwarteschlange hinzufügen und entfernen`,apiKeysEmptyTitle:`Keine API-Schlüssel`,apiKeysEmptyDescription:`Erstellen Sie einen API-Schlüssel zur Integration mit externen Diensten.`,noUsersFound:`Keine Benutzer gefunden`,noGroupsFound:`Keine Gruppen gefunden`,noGroupsAvailable:`Keine Gruppen verfügbar`,passwordsDoNotMatch:`Passwörter stimmen nicht überein`,systemGroupWarning:`System-Gruppennamen können nicht geändert werden`,authDisabledTitle:`Authentifizierung ist deaktiviert`,authDisabledFeature1:`Anmeldung zum Zugriff auf das System erforderlich`,authDisabledFeature2:`Mehrere Benutzer mit gruppenbasierten Berechtigungen erstellen`,authDisabledFeature3:`Zugriff mit über 50 granularen Berechtigungen steuern`,userHasCreated:`Dieser Benutzer hat erstellt:`,userItemsQuestion:`Was möchten Sie mit diesen Elementen tun?`,deleteUserConfirm:`Möchten Sie diesen Benutzer wirklich löschen?`,actionCannotBeUndone:`Diese Aktion kann nicht rückgängig gemacht werden.`,addFirstSmartPlug:`Ersten Smart Plug hinzufügen`,providers:`Anbieter`,log:`Protokoll`,testAll:`Alle testen`,testResults:`Testergebnisse`,testPassedCount:`{{count}} bestanden`,testFailedCount:`{{count}} fehlgeschlagen`,messageTemplates:`Nachrichtenvorlagen`,messageTemplatesDescription:`Passen Sie Benachrichtigungen für jedes Ereignis an.`,apiKeys:`API-Schlüssel`,apiKeysDescription:`Erstellen Sie API-Schlüssel für externe Integrationen und Webhooks.`,createKey:`Schlüssel erstellen`,apiKeyCreated:`API-Schlüssel erfolgreich erstellt`,apiKeyCopyWarning:`Kopieren Sie diesen Schlüssel jetzt - er wird nicht mehr angezeigt!`,useInApiBrowser:`Im API-Browser verwenden`,apiKeyQrButton:`QR-Code`,apiKeyQrTitle:`Zum Einrichten scannen`,apiKeyQrCaption:`Mit deiner mobilen App scannen, um diesen Server und API-Schlüssel hinzuzufügen.`,apiKeyQrWarning:`Enthält deinen geheimen API-Schlüssel – nicht teilen oder dort abfotografieren, wo andere ihn sehen können.`,createNewApiKey:`Neuen API-Schlüssel erstellen`,keyName:`Schlüsselname`,keyNamePlaceholder:`z.B. Home Assistant, OctoPrint`,readStatus:`Status lesen`,readStatusDescription:`Druckerstatus und Warteschlange anzeigen`,manageQueue:`Warteschlange verwalten`,manageQueueDescription:`Elemente zur Druckwarteschlange hinzufügen und entfernen`,controlPrinter:`Drucker steuern`,controlPrinterDescription:`Drucke pausieren, fortsetzen und stoppen`,manageLibrary:`Bibliothek verwalten`,manageLibraryDescription:`Bibliotheksdateien hochladen, umbenennen und löschen; Modelle aus MakerWorld importieren`,manageInventory:`Bestand verwalten`,manageInventoryDescription:`Spulen und Bestandseinträge anlegen, ändern und löschen. Erforderlich für SpoolBuddy-Kioske (NFC-Scan, Waagenmessungen, Kiosk-Systembefehle).`,manageMaintenance:`Wartung verwalten`,manageMaintenanceDescription:`Abgeschlossene Wartungen protokollieren, Zähler zurücksetzen, Intervalle bearbeiten und den Wartungstyp-Katalog verwalten. Geeignet für Home-Assistant-Automatisierungen, die „Düse gereinigt" protokollieren, ohne umfassendere Druckersteuerung zu gewähren.`,manageArchives:`Archive verwalten`,manageArchivesDescription:`Druckarchive bearbeiten und löschen, einschließlich des Entfernens alter Drucke. Umfasst nicht das Bereinigen ihres Statistikbeitrags. Geeignet für Automatisierungen, die den Druckverlauf ausdünnen.`,manageProjects:`Projekte verwalten`,manageProjectsDescription:`Projekte erstellen, aktualisieren und löschen sowie Archive zu ihnen hinzufügen. Geeignet für Automatisierungen, die Drucke in Projekten organisieren.`,maintenanceBadge:`Wartung`,archivesBadge:`Archive`,projectsBadge:`Projekte`,libraryBadge:`Bibliothek`,inventoryBadge:`Bestand`,cloudAccess:`Cloud-Zugriff erlauben`,cloudAccessDescription:`Liest Bambu-Cloud-Presets und -Filamente in Ihrem Namen. Erfordert eine Anmeldung in Bambu Cloud.`,cloudBadge:`Cloud`,updateEnergyCost:`Strompreis aktualisieren`,updateEnergyCostDescription:`Erlaubt diesem Schlüssel, einen neuen Strompreis pro kWh an /settings/electricity-price zu senden. Nützlich für Home-Assistant-Automatisierungen mit dynamischen Tarifen (Tibber, Octopus usw.). Dies ist das einzige Einstellungsfeld, das per API-Schlüssel schreibbar ist.`,energyCostBadge:`Energie`,legacyKey:`Alt`,legacyKeyTooltip:`Wurde vor der nutzerbezogenen Eigentümerschaft erstellt; neu erstellen, um Cloud-Zugriff zu nutzen`,unnamedKey:`Unbenannter Schlüssel`,lastUsed:`Zuletzt verwendet`,read:`Lesen`,control:`Steuern`,createFirstKey:`Ersten Schlüssel erstellen`,webhookEndpoints:`Webhook-Endpunkte`,webhookApiKeyHint:`Verwenden Sie Ihren API-Schlüssel im X-API-Key-Header.`,webhook:{getAllStatus:`Alle Druckerstatus abrufen`,getSpecificStatus:`Spezifischen Druckerstatus abrufen`,addToQueue:`Zur Druckwarteschlange hinzufügen`,pausePrint:`Druck pausieren`,resumePrint:`Druck fortsetzen`,stopPrint:`Druck stoppen`},apiBrowser:`API-Browser`,apiBrowserDescription:`Erkunden und testen Sie alle verfügbaren API-Endpunkte.`,apiKeyForTesting:`API-Schlüssel zum Testen`,apiKeyPlaceholder:`Fügen Sie hier Ihren API-Schlüssel ein, um authentifizierte Endpunkte zu testen...`,apiKeyHint:`Dieser Schlüssel wird als X-API-Key-Header mit Anfragen gesendet.`,deleteApiKeyTitle:`API-Schlüssel löschen`,deleteApiKeyMessage:`Möchten Sie diesen API-Schlüssel wirklich löschen? Alle Integrationen, die diesen Schlüssel verwenden, funktionieren nicht mehr.`,deleteKey:`Schlüssel löschen`,amsDisplayThresholds:`AMS-Anzeigeschwellenwerte`,amsThresholdsDescription:`Konfigurieren Sie Farbschwellenwerte für AMS-Feuchtigkeits- und Temperaturanzeigen.`,humidity:`Luftfeuchtigkeit`,goodGreen:`Gut (grün)`,fairOrange:`Mittel (orange)`,aboveFairBad:`Über dem mittleren Schwellenwert wird rot angezeigt (schlecht)`,fairAlsoDryingThreshold:`Dieser Schwellenwert wird auch für die automatische Trocknung verwendet`,temperature:`Temperatur`,goodBlue:`Gut (blau)`,aboveFairHot:`Über dem mittleren Schwellenwert wird rot angezeigt (heiß)`,historyRetention:`Verlaufsaufbewahrung`,keepSensorHistory:`Sensorverlauf behalten für`,historyRetentionDescription:`Ältere Feuchtigkeits- und Temperaturdaten werden automatisch gelöscht`,defaultPrintOptions:`Standard-Druckoptionen`,defaultPrintOptionsDescription:`Standardwerte für Druckoptionen bei neuen Drucken festlegen. Diese können im Druckdialog pro Druck überschrieben werden.`,defaultBedLevelling:`Bett-Nivellierung`,defaultBedLevellingDesc:`Bett vor dem Druck automatisch nivellieren`,defaultFlowCali:`Fluss-Kalibrierung`,defaultFlowCaliDesc:`Extrusionsfluss kalibrieren`,defaultVibrationCali:`Vibrationskalibrierung`,defaultVibrationCaliDesc:`Ringing-Artefakte reduzieren`,defaultLayerInspect:`Erste-Schicht-Inspektion`,defaultLayerInspectDesc:`KI-Inspektion der ersten Schicht`,defaultTimelapse:`Zeitraffer`,defaultTimelapseDesc:`Zeitraffervideo aufnehmen`,defaultNozzleOffsetCali:`Düsenversatz-Kalibrierung`,defaultNozzleOffsetCaliDesc:`Düsenversatz zwischen Extrudern kalibrieren`,tempFanPresetsTitle:`Temperatur- und Lüfter-Vorgaben`,tempFanPresetsDescription:`Passen Sie die Schnellwahlwerte in den Temperatur- und Lüfter-Popovers der Druckerkarte an. Die Aus-Schaltfläche wird immer angezeigt.`,tempFanPresetsNozzle:`Düsentemperatur`,tempFanPresetsBed:`Betttemperatur`,tempFanPresetsChamber:`Kammertemperatur`,tempFanPresetsFan:`Lüftergeschwindigkeit`,tempFanPresetsReset:`Auf Standardwerte zurücksetzen`,concurrentUploadsTitle:`Gleichzeitige Uploads`,concurrentUploadsDescription:`Wie viele Drucker die Warteschlange gleichzeitig mit Dateien versorgen darf. Drucker nehmen Dateien nur langsam entgegen (ein großer Druck kann mehrere Minuten dauern), und jeder wartet, bis er an der Reihe ist — bei größeren Farmen verhindert ein höherer Wert also, dass der letzte Drucker eines Stapels erst alle anderen Übertragungen abwarten muss. Verringern Sie ihn, wenn Ihr Netzwerk oder der Bambuddy-Host mit parallelen Übertragungen Probleme hat.`,concurrentUploadsLabel:`Gleichzeitig belieferte Drucker`,concurrentUploadsHelp:`1 beliefert immer nur einen Drucker (das bisherige Verhalten). Standard ist 4.`,staggeredStart:`Versetzter Start`,staggeredStartDescription:`Standard-Gruppengröße und -Intervall beim Staffeln von Mehrdrucker-Batchstarts. Pro Batch im Druck-Dialog überschreibbar.`,preheatTitle:`Vorheizen & Heat Soak`,preheatDescription:`Heizt das Bett (und die Kammer, sofern unterstützt) auf und hält die Temperatur, bevor jeder Druck aus der Warteschlange startet. Hilfreich für technische Filamente (PA, ABS) auf Druckern ohne aktive Kammerheizung — das Bett wärmt die Kammer per Abstrahlung, während der Soak-Timer läuft. Die Bett-Zieltemperatur wird aus der Druckdatei gelesen; das Kammerverhalten hängt vom Druckermodell ab.`,preheatEnabled:`Vorheizen & Soak aktivieren`,preheatEnabledDesc:`Wenn aus, starten Drucke aus der Warteschlange sofort. Jeder Warteschlangeneintrag kann das pro Druck überschreiben.`,preheatFilamentTargetsLabel:`Kammer-Ziel je Filament (°C)`,preheatFilamentTargetsHint:`Bambuddy wählt das höchste Ziel über die geladenen AMS-Slots; reine PLA-Drucke ergeben 0 und überspringen die Kammerphase automatisch.`,preheatFilamentTargetsReset:`Auf Standardwerte zurücksetzen`,preheatFilamentTargetsDefaultRow:`Sonstige / nicht zugeordnet`,preheatMaxWait:`Max. Wartezeit (Sekunden)`,preheatMaxWaitHelp:`Obergrenze für die Aufwärmphase, bevor in den Soak gewechselt wird.`,preheatSoak:`Soak (Sekunden)`,preheatSoakHelp:`Haltezeit nach Erreichen des Ziels oder nach Ablauf der Max-Wartezeit.`,preheatHardwareTitle:`Verhalten je Drucker:`,preheatHardwareDetail:`H2C/H2D/H2D Pro/H2S/X2D/X1E heizen die Kammer aktiv per M141. X1C/P2S lesen die Kammertemperatur, heizen sie aber nur per Bett-Abstrahlung. P1S/P1P/A1/A1 Mini haben keinen Kammersensor — nur der Soak-Timer greift.`,preheatPerItemDesc:`Bett und Kammer vor diesem Druck aufheizen. Standardmäßig wird der globale Umschalter aus Einstellungen → Workflow verwendet.`,preheatOverride_inherit:`Übernehmen`,preheatOverride_on:`An`,preheatOverride_off:`Aus`,calibrationMode_off:`Aus`,calibrationMode_on:`An`,calibrationMode_auto:`Auto`,preheatTargetOverride:`Kammer-Ziel überschreiben (°C, leer = Filament-Standard)`,plateClear:`Druckplatte-Bestätigung`,requirePlateClear:`Druckplatte-Bestätigung erforderlich`,requirePlateClearDescription:`Wenn aktiviert, wartet der Scheduler auf eine Druckplatten-Bestätigung pro Drucker, bevor geplante Drucke auf Druckern mit abgeschlossenen Aufträgen gestartet werden. Wenn dies deaktiviert ist, werden auch das Druckplatten-Status-Badge und die Schaltfläche "Druckplatte als freigegeben markieren" auf den Druckerkarten ausgeblendet.`,gcodeInjection:`G-Code-Injektion`,gcodeInjectionDescription:`Konfigurieren Sie benutzerdefinierten G-code, der am Anfang und/oder Ende von Drucken für Auto-Print-Systeme wie Farmloop, SwapMod, AutoClear und Printflow 3D eingefügt wird. Snippets werden pro Druckermodell konfiguriert und angewendet, wenn "G-code einfügen" bei einem Warteschlangen-Element aktiviert ist.`,gcodeInjectionNoPrinters:`Keine Drucker gefunden. Fügen Sie Drucker hinzu, um G-code-Snippets zu konfigurieren.`,gcodeStartLabel:`Start-G-Code`,gcodeEndLabel:`End-G-Code`,gcodeStartPlaceholder:`G-code, der vor dem Druckstart eingefügt wird...`,gcodeEndPlaceholder:`G-code, der nach dem Druckende angefügt wird...`,staggerGroupSize:`Gruppengröße`,staggerGroupSizeHelp:`Anzahl gleichzeitig zu startender Drucker pro Gruppe`,staggerInterval:`Intervall (Minuten)`,staggerIntervalHelp:`Verzögerung zwischen Gruppenstart`,queueDrying:`Automatische Trocknung`,queueDryingDescription:`AMS-Filament automatisch trocknen, wenn der Drucker zwischen Warteschlangen-Drucken im Leerlauf ist. Verwendet den Feuchtigkeitsschwellenwert oben.`,queueDryingEnabled:`Automatische Trocknung aktivieren`,queueDryingEnabledDescription:`AMS-Trocknung automatisch starten, wenn der Drucker im Leerlauf ist und die Feuchtigkeit über dem Schwellenwert liegt`,queueDryingBlock:`Auf Trocknung warten`,queueDryingBlockDescription:`Druckwarteschlange blockieren, bis die Trocknung abgeschlossen ist. Wenn aus, haben Drucke Vorrang.`,ambientDryingEnabled:`Umgebungstrocknung`,ambientDryingEnabledDescription:`Filament auf inaktiven Druckern automatisch trocknen, wenn die Luftfeuchtigkeit den Schwellenwert überschreitet — auch ohne Warteschlange.`,printDryingEnabled:`Trocknen während des Drucks`,printDryingEnabledDescription:`Automatische Trocknung auch während eines laufenden Drucks auf unterstützter Hardware (H2D, H2C, H2S, P2S, H2D Pro, X2D, X1C, A2L mit aktueller Firmware). Die Trocknungstemperatur wird zum Schutz der Spulen automatisch um 5°C unter dem Leerlaufwert begrenzt.`,dryingPresets:`Trocknungsvoreinstellungen`,dryingPresetsDescription:`Temperatur und Dauer pro Filamenttyp. AMS 2 Pro verwendet niedrigere Temperaturen, AMS-HT unterstützt höhere.`,dryingFilament:`Filament`,humidityThresholds:`Feuchtigkeitsschwellen`,humidityThresholdsDescription:`Feuchtigkeitsauslöser pro Filamenttyp für Auto-Trocknung und Alarme. Bei gemischter Bestückung gilt der niedrigste Wert.`,humidityThresholdCol:`Schwellenwert`,humidityThresholdDefault:`Standard (unbekannte Typen)`,printModal:`Druckdialog`,expandCustomMapping:`Benutzerdefinierte Zuordnung standardmäßig erweitern`,expandCustomMappingDescription:`Bei Druck auf mehrere Drucker die AMS-Zuordnung pro Drucker erweitert anzeigen`,authentication:`Authentifizierung`,authEnabledDescription:`Ihre Instanz ist mit Benutzerauthentifizierung gesichert`,authDisabledDescription:`Aktivieren Sie die Anmeldepflicht und verwalten Sie den Benutzerzugriff`,authDisabledMessage:`Aktivieren Sie die Authentifizierung, um Benutzerkonten zu erstellen, Berechtigungen zu verwalten und Ihre Bambuddy-Instanz zu sichern.`,enableAuthentication:`Authentifizierung aktivieren`,currentUser:`Aktueller Benutzer`,changePassword:`Passwort ändern`,admin:`Admin`,users:`Benutzer`,addUser:`Benutzer hinzufügen`,groups:`Gruppen`,addGroup:`Gruppe hinzufügen`,system:`System`,noDescription:`Keine Beschreibung`,userCount:`{{count}} Benutzer`,permissionCount:`{{count}} Berechtigungen`,createUser:`Benutzer erstellen`,username:`Benutzername`,enterUsername:`Benutzername eingeben`,password:`Passwort`,enterPassword:`Passwort eingeben`,passwordRequirements:`Mindestens 8 Zeichen, davon ein Großbuchstabe, ein Kleinbuchstabe, eine Ziffer und ein Sonderzeichen.`,confirmPassword:`Passwort bestätigen`,confirmPasswordPlaceholder:`Passwort bestätigen`,viewReleaseOnGitHub:`Release auf GitHub anzeigen`,turnAllPlugsOn:`Alle Stecker einschalten`,turnAllPlugsOff:`Alle Stecker ausschalten`,clearNotificationLogs:`Benachrichtigungsprotokolle löschen`,clearLogsMessage:`Dadurch werden alle Benachrichtigungsprotokolle, die älter als 30 Tage sind, dauerhaft gelöscht. Diese Aktion kann nicht rückgängig gemacht werden.`,clearLogs:`Protokolle löschen`,resetUiPreferences:`UI-Einstellungen zurücksetzen`,resetUiPreferencesMessage:`Dadurch werden alle UI-Einstellungen auf Standardwerte zurückgesetzt: Seitenleisten-Reihenfolge, Theme, Dashboard-Layout, Ansichtsmodi und Sortiereinstellungen. Ihre Drucker, Archive und Servereinstellungen werden NICHT beeinträchtigt. Die Seite wird nach dem Löschen neu geladen.`,resetPreferences:`Einstellungen zurücksetzen`,deleteGroupTitle:`Gruppe löschen`,deleteGroupMessage:`Möchten Sie diese Gruppe wirklich löschen? Benutzer in dieser Gruppe verlieren diese Berechtigungen.`,deleteGroup:`Gruppe löschen`,disableAuthenticationTitle:`Authentifizierung deaktivieren`,disableAuthenticationMessage:`Möchten Sie die Authentifizierung wirklich deaktivieren? Dadurch wird Ihre Bambuddy-Instanz ohne Anmeldung zugänglich. Alle Benutzer bleiben in der Datenbank, aber die Authentifizierung wird deaktiviert.`,disableAuthentication:`Authentifizierung deaktivieren`,configureBambuddy:`Bambuddy konfigurieren`,systemDefault:`Systemstandard`,archiveSettings:`Archiv-Einstellungen`,newWindow:`Neues Fenster`,embeddedOverlay:`Eingebettetes Overlay`,preferredSlicer:`Bevorzugter Slicer`,preferredSlicerDescription:`Slicer für das In-App-Slicen über das API-Sidecar`,openInSlicerLabel:`Im Slicer öffnen`,openInSlicerInherit:`Wie API-Slicer`,openInSlicerDescription:`Desktop-Slicer, der vom „Im Slicer öffnen"-Button verwendet wird. Auf „Wie API-Slicer" belassen, um zu erben, oder einen anderen Slicer für die lokale Nutzung wählen.`,orcaslicerKnownIssuesWarning:`OrcaSlicer 2.3.2 / 2.4.0-dev haben bekannte CLI-Bugs, die das Slicen vieler von BambuStudio erstellter 3MF-Dateien blockieren — siehe Upstream-Issues #12426 (Segfault bei bemalten Multi-Extruder-Dateien) und #13386 (zu strikte Parameter-Range-Validierung). Bis die Upstream-Fixes verfügbar sind, wird Bambu Studio empfohlen.`,useSlicerApi:`Slicer-API verwenden`,useSlicerApiDescription:`Wenn aktiv, öffnen "Slice"-Aktionen das in-App Slicer-Modal und rufen den Slicer-API-Sidecar. Aus (Standard): Übergabe an den Desktop-Slicer per URI-Schema.`,slicerCard:`Slicer`,orcaslicerApiUrl:`OrcaSlicer Sidecar-URL`,bambuStudioApiUrl:`Bambu Studio Sidecar-URL`,slicerStallTimeout:`Zeitlimit bei Slicer-Stillstand (Minuten)`,slicerStallTimeoutDescription:`Bricht einen Slice-Vorgang ab, wenn der Sidecar so lange keinen Fortschritt meldet. Aufwendige Modelle, die weiter Fortschritt melden, werden nie abgebrochen, egal wie lange sie brauchen. Sidecars ohne Fortschrittsmeldung nutzen diesen Wert stattdessen als Gesamtzeitlimit.`,slicerApiUrlDescription:`URL des Slicer-API-Sidecar-Containers. Leer lassen, um die SLICER_API_URL- bzw. BAMBU_STUDIO_API_URL-Umgebungsvariablen zu nutzen.`,slicerBundlesRemoved:{title:`Slicer-Bundles (entfernt)`,description:`Der Import von Drucker-Voreinstellungs-Bundles (.bbscfg) wurde entfernt. Der Bundle-Export von BambuStudio enthält nur benutzerdefinierte Voreinstellungen, daher lieferte der Import nie die Standard-Prozesse / -Filamente, und das Slicen fiel auf eingebettete Einstellungen zurück.`,alternatives:`Verwende Einzel-Voreinstellungs-Import für individuelle Anpassungen oder synchronisiere via Bambu Cloud / Orca Cloud. Standard-Voreinstellungen kommen automatisch vom Slicer-Sidecar.`,lookupOrder:`Reihenfolge der Voreinstellungssuche beim Slicen: 1) Importiert (lokal), 2) Orca Cloud, 3) Bambu Cloud, 4) Standard (Sidecar-Fallback).`},externalCameras:`Externe Kameras`,costTracking:`Kostenverfolgung`,printsOnly:`Nur Drucke`,totalConsumption:`Gesamtverbrauch`,dataManagement:`Datenverwaltung`,storageUsage:`Speichernutzung`,storageUsageDescription:`Aufschlüsselung der Datennutzung nach Kategorie`,storageUsageTotal:`Gesamt`,storageUsageErrors:`Fehler`,storageUsageOtherBreakdown:`Sonstiges (enthält statische Assets, Skripte und Konfigurationsdateien)`,storageUsageSystem:`System`,storageUsageData:`Daten`,storageUsageUnavailable:`Speichernutzungsinformationen nicht verfügbar`,clearNotificationLogsDescription:`Benachrichtigungsprotokolle älter als 30 Tage löschen`,resetUiPreferencesDescription:`Seitenleisten-Reihenfolge, Theme, Ansichtsmodi und Layout-Einstellungen zurücksetzen. Drucker, Archive und Einstellungen werden nicht beeinflusst.`,enableHomeAssistant:`Home Assistant aktivieren`,enableMqtt:`MQTT aktivieren`,useTls:`TLS verwenden`,enableMetricsEndpoint:`Metrik-Endpunkt aktivieren`,availableMetrics:`Verfügbare Metriken`,editUser:`Benutzer bearbeiten`,deleteUserTitle:`Benutzer löschen`,groupName:`Gruppenname`,leaveEmptyForAnonymous:`Leer lassen für anonym`,leaveEmptyForNoAuth:`Leer lassen für keine Authentifizierung`,enterNewPassword:`Neues Passwort eingeben`,confirmNewPassword:`Neues Passwort bestätigen`,enterGroupName:`Gruppenname eingeben`,enterDescriptionOptional:`Beschreibung eingeben (optional)`,enterCurrentPassword:`Aktuelles Passwort eingeben`,enterNewPasswordMin6:`Neues Passwort eingeben (min. 6 Zeichen)`,toast:{keyCopied:`Schlüssel in Zwischenablage kopiert`,copyFailed:`Schlüssel konnte nicht kopiert werden`,keyAddedToBrowser:`Schlüssel zum API-Browser hinzugefügt`,clearLogsFailed:`Protokolle konnten nicht gelöscht werden`,uiPreferencesReset:`UI-Einstellungen zurückgesetzt. Wird neu geladen...`,authDisabled:`Authentifizierung erfolgreich deaktiviert`,authDisableFailed:`Authentifizierung konnte nicht deaktiviert werden`,apiKeyCreated:`API-Schlüssel erstellt`,apiKeyDeleted:`API-Schlüssel gelöscht`,userCreated:`Benutzer erfolgreich erstellt`,userUpdated:`Benutzer erfolgreich aktualisiert`,userDeleted:`Benutzer erfolgreich gelöscht`,groupCreated:`Gruppe erfolgreich erstellt`,groupUpdated:`Gruppe erfolgreich aktualisiert`,groupDeleted:`Gruppe erfolgreich gelöscht`,fillRequiredFields:`Bitte füllen Sie alle erforderlichen Felder aus`,passwordsDoNotMatch:`Passwörter stimmen nicht überein`,passwordTooShort:`Passwort muss mindestens 8 Zeichen lang sein`,passwordNeedsUppercase:`Passwort muss mindestens einen Großbuchstaben enthalten`,passwordNeedsLowercase:`Passwort muss mindestens einen Kleinbuchstaben enthalten`,passwordNeedsDigit:`Passwort muss mindestens eine Ziffer enthalten`,passwordNeedsSpecial:`Passwort muss mindestens ein Sonderzeichen enthalten`,enterGroupName:`Bitte geben Sie einen Gruppennamen ein`,settingsSaved:`Einstellungen gespeichert`,noPermissionUpdate:`Sie haben keine Berechtigung, Einstellungen zu ändern`,cameraSettingsSaved:`Kamera-Einstellungen gespeichert`,enterCameraUrl:`Bitte geben Sie eine Kamera-URL ein`,passwordChanged:`Passwort erfolgreich geändert`,connectionFailed:`Verbindung fehlgeschlagen`,testFailed:`Test fehlgeschlagen`,cameraConnected:`Kamera verbunden{{resolution}}`,cameraConnectedCoalesced:`Kamera verbunden{{resolution}} (geteilt mit einer bereits laufenden Aufnahme)`},testConnection:`Verbindung testen`,catalog:{spoolCatalog:`Spulenkatalog`,spoolCatalogDescription:`Leerspulengewichte nach Marke/Typ. Wird für die automatische Gewichtssuche beim Hinzufügen von Spulen verwendet.`,searchCatalog:`Katalog durchsuchen...`,addNewEntry:`Neuen Eintrag hinzufügen`,namePlaceholder:`Name (z.B. Bambu Lab - Plastik)`,weight:`Gewicht`,type:`Typ`,default:`Standard`,custom:`Benutzerdefiniert`,noMatch:`Keine Einträge entsprechen Ihrer Suche`,empty:`Keine Einträge im Katalog`,deleteEntry:`Eintrag löschen`,deleteConfirm:`Möchten Sie "{{name}}" wirklich löschen?`,resetCatalog:`Katalog zurücksetzen`,resetConfirm:`Katalog auf Standardwerte zurücksetzen? Alle benutzerdefinierten Einträge werden entfernt.`,loadFailed:`Spulenkatalog konnte nicht geladen werden`,nameWeightRequired:`Name und Gewicht sind erforderlich`,entryAdded:`Eintrag hinzugefügt`,addFailed:`Eintrag konnte nicht hinzugefügt werden`,entryUpdated:`Eintrag aktualisiert`,updateFailed:`Eintrag konnte nicht aktualisiert werden`,entryDeleted:`Eintrag gelöscht`,deleteFailed:`Eintrag konnte nicht gelöscht werden`,resetSuccess:`Katalog auf Standardwerte zurückgesetzt`,resetFailed:`Katalog konnte nicht zurückgesetzt werden`,exported:`{{count}} Einträge exportiert`,imported:`{{added}} Einträge importiert ({{skipped}} übersprungen)`,importFailed:`Import fehlgeschlagen: ungültiges JSON-Format`,exportTooltip:`Katalog als JSON exportieren`,importTooltip:`Katalog aus JSON importieren`,resetTooltip:`Auf Standardwerte zurücksetzen`,selectedCount:`{{count}} ausgewählt`,deleteSelected:`Ausgewählte löschen`,bulkDeleteConfirm:`Möchten Sie {{count}} Einträge wirklich löschen?`,bulkDeleted:`{{count}} Einträge gelöscht`,bulkDeleteFailed:`Fehler beim Löschen der Einträge`,material:`Material`,spoolWeight:`Spulengewicht`,color:`Farbe`,updateSpoolWeight:`Spulengewicht aktualisieren`,filamentUpdated:`Filament aktualisiert`,filamentUpdateFailed:`Filament konnte nicht aktualisiert werden`,filamentUpdateInvalid:`Ungültige Filamentdaten`,keepExistingSpoolWeight:`Altes Gewicht für bestehende Spulen behalten`,keepExistingSpoolWeightDesc:`Bereits erstellte Spulen dieses Filamenttyps behalten das alte Leergewicht. Neue Spulen nutzen den neuen Wert.`,applyToAllSpools:`Auf alle Spulen anwenden`,applyToAllSpoolsDesc:`Alle Gewichtsberechnungen für diesen Filamenttyp nutzen sofort das neue Leergewicht.`},colorCatalog:{title:`Farbkatalog`,description:`Filamentfarben nach Hersteller/Material. Wird für die automatische Farbsuche beim Hinzufügen von Spulen verwendet.`,searchColors:`Farben durchsuchen...`,allManufacturers:`Alle Hersteller`,addNewColor:`Neue Farbe hinzufügen`,manufacturer:`Hersteller`,colorName:`Farbname`,hex:`Hex`,materialOptional:`Material (optional)`,showing:`{{filtered}} von {{total}} Farben angezeigt`,noMatch:`Keine Farben entsprechen Ihrer Suche`,empty:`Keine Farben im Katalog`,deleteColor:`Farbe löschen`,deleteConfirm:`Möchten Sie "{{name}}" wirklich löschen?`,resetCatalog:`Farbkatalog zurücksetzen`,resetConfirm:`Katalog auf Standardwerte zurücksetzen? Alle benutzerdefinierten Farben werden entfernt.`,sync:`Synchron.`,starting:`Starten...`,syncTooltip:`Von FilamentColors.xyz synchronisieren (2000+ Farben)`,loadFailed:`Farbkatalog konnte nicht geladen werden`,fieldsRequired:`Hersteller, Farbname und Hex-Farbe sind erforderlich`,colorAdded:`Farbe hinzugefügt`,addFailed:`Farbe konnte nicht hinzugefügt werden`,colorUpdated:`Farbe aktualisiert`,updateFailed:`Farbe konnte nicht aktualisiert werden`,colorDeleted:`Farbe gelöscht`,deleteFailed:`Farbe konnte nicht gelöscht werden`,resetSuccess:`Farbkatalog auf Standardwerte zurückgesetzt`,resetFailed:`Katalog konnte nicht zurückgesetzt werden`,syncUpToDate:`Bereits aktuell ({{count}} Farben geprüft)`,syncComplete:`{{added}} neue Farben hinzugefügt ({{skipped}} bereits vorhanden)`,syncError:`Sync-Fehler`,syncFailed:`Synchronisierung von FilamentColors.xyz fehlgeschlagen`,exported:`{{count}} Farben exportiert`,imported:`{{added}} Farben importiert ({{skipped}} übersprungen)`,importFailed:`Import fehlgeschlagen: ungültiges JSON-Format`,selectedCount:`{{count}} ausgewählt`,deleteSelected:`Ausgewählte löschen`,bulkDeleteConfirm:`Möchten Sie {{count}} Farben wirklich löschen?`,bulkDeleted:`{{count}} Farben gelöscht`,bulkDeleteFailed:`Fehler beim Löschen der Farben`},dateFormat:`Datumsformat`,dateFormatUs:`US (MM/TT/JJJJ)`,dateFormatEu:`EU (TT/MM/JJJJ)`,dateFormatIso:`ISO (JJJJ-MM-TT)`,timeFormat:`Zeitformat`,timeFormat12:`12-Stunden (3:30 PM)`,timeFormat24:`24-Stunden (15:30)`,defaultPrinter:`Standarddrucker`,defaultPrinterDescription:`Diesen Drucker für Uploads, Nachdrucke und andere Vorgänge vorauswählen.`,slicerBambuStudio:`Bambu Studio`,slicerOrcaSlicer:`OrcaSlicer`,sidebarOrderDescription:`Nutze das Seitenleisten-Layout, um Elemente neu anzuordnen, Sichtbarkeit zurückzusetzen und benutzerdefinierte Links zu verwalten.`,setDefault:`Standard setzen`,sidebarOrderSetDefaultHint:`Standard setzen übernimmt die aktuelle Menüreihenfolge für Benutzer, die ihre noch nicht angepasst haben.`,sidebarDefaultSet:`Standard-Menüreihenfolge wurde festgelegt.`,sidebarDefaultCleared:`Standard-Menüreihenfolge gelöscht.`,sidebarDefaultFailed:`Festlegen der Standard-Menüreihenfolge fehlgeschlagen.`,reset:`Zurücksetzen`,darkMode:`Dunkelmodus`,lightMode:`Hellmodus`,active:`(aktiv)`,background:`Hintergrund`,accent:`Akzent`,style:`Stil`,bgNeutral:`Neutral`,bgWarm:`Warm`,bgCool:`Kühl`,bgOled:`OLED Schwarz`,bgSlate:`Schieferblau`,bgForest:`Waldgrün`,accentGreen:`Grün`,accentTeal:`Türkis`,accentBlue:`Blau`,accentOrange:`Orange`,accentPurple:`Lila`,accentRed:`Rot`,styleClassic:`Klassisch`,styleGlow:`Leuchtend`,styleVibrant:`Lebendig`,themeToggleHint:`Zwischen Dunkel-, Hell- und Systemmodus mit dem Symbol in der Seitenleiste wechseln.`,progressInTitle:`Druckfortschritt im Tab`,progressInTitleDescription:`Zeigt den Prozentsatz des aktiven Drucks und einen Fortschrittsring im Browser-Tab an.`,autoArchivePrints:`Drucke automatisch archivieren`,autoArchiveDescription:`3MF-Dateien automatisch speichern, wenn Drucke abgeschlossen sind`,saveThumbnailsDescription:`Vorschaubilder aus 3MF-Dateien extrahieren und speichern`,captureFinishPhotoDescription:`Foto von der Druckerkamera aufnehmen, wenn der Druck abgeschlossen ist. Bambuddy zeichnet während des Drucks einen kurzen Zeitraffer auf, damit das Foto aus dem Moment vor dem Absenken der Druckplatte stammen kann. Die Zeitraffer-Datei bleibt erhalten, wenn du den Zeitraffer für diesen Druck aktiviert hast, andernfalls wird sie nach Aufnahme des Fotos automatisch gelöscht.`,finishPhotoRestorePlate:`Druckplatte für Abschlussfoto anheben`,finishPhotoRestorePlateDescription:`Der Drucker senkt die Druckplatte am Druckende um etwa 100 mm ab, wodurch der fertige Druck unterhalb des Kamerabildausschnitts liegt. Bambuddy hebt sie wieder bis knapp über die zuletzt gedruckte Schicht an, nimmt das Foto auf und senkt sie danach wieder ab. Wird übersprungen, wenn die Druckhöhe unbekannt ist oder ein weiterer Auftrag in der Warteschlange steht.`,ffmpegNotInstalled:`ffmpeg nicht installiert`,ffmpegRequired:`Kameraaufnahme benötigt ffmpeg. Installieren über brew install ffmpeg (macOS) oder apt install ffmpeg (Linux).`,camera:`Kamera`,cameraViewMode:`Kamera-Ansichtsmodus`,cameraOverlayDescription:`Kamera öffnet sich als größenveränderbares Overlay auf dem Hauptbildschirm`,cameraWindowDescription:`Kamera öffnet sich in einem separaten Browserfenster`,externalCamerasDescription:`Externe Kameras konfigurieren, um die eingebaute Druckerkamera zu ersetzen. Unterstützt MJPEG-Streams, RTSP, HTTP-Snapshots und USB-Kameras (V4L2). Wenn aktiviert, wird die externe Kamera für Live-Ansicht und Abschlussfotos verwendet.`,cameraPlaceholderUsb:`Gerätepfad (/dev/video0)`,cameraPlaceholderUrl:`Kamera-URL (rtsp://... oder http://...)`,cameraTypeMjpeg:`MJPEG-Stream`,cameraTypeRtsp:`RTSP-Stream`,cameraTypeSnapshot:`HTTP-Snapshot`,cameraTypeUsb:`USB-Kamera (V4L2)`,cameraSnapshotUrl:`Snapshot-URL (optional)`,cameraSnapshotUrlPlaceholder:`http://192.168.1.61:1984/api/frame.jpeg?src=printer`,cameraSnapshotUrlHelp:`URL für Einzelbildaufnahmen — wird für Benachrichtigungs-Vorschaubilder, Abschlussfotos, Schicht-Zeitraffer und Plattenerkennung verwendet. Zeitraffer und Plattenerkennung benötigen jeweils eigene drucker-spezifische Schalter — diese URL ist nur die Bildquelle, die sie verwenden, wenn sie aktiv sind. Leer lassen, um Bilder aus dem oben konfigurierten Live-Stream zu verwenden. Nützlich für go2rtc (/api/frame.jpeg) und IP-Kameras mit dediziertem Snapshot-Endpunkt.`,cameraRotation:`Drehung`,test:`Testen`,connected:`Verbunden`,disconnected:`Getrennt`,currency:`Währung`,defaultFilamentCost:`Standard-Filamentkosten (pro kg)`,electricityCost:`Stromkosten pro kWh`,energyDisplayMode:`Energieanzeige-Modus`,energyModePrintDescription:`Dashboard zeigt Summe der während Drucken verbrauchten Energie`,energyModeTotalDescription:`Dashboard zeigt Gesamtenergie der Smart Plugs`,fileManager:`Dateimanager`,createArchiveEntry:`Archiveintrag beim Drucken erstellen`,createArchiveEntryDescription:`Beim Drucken aus dem Dateimanager optional einen Archiveintrag erstellen`,lowDiskSpaceWarning:`Warnung bei wenig Speicherplatz`,lowDiskSpaceDescription:`Warnung anzeigen, wenn freier Speicherplatz unter diesen Schwellenwert fällt`,printerFirmware:`Drucker-Firmware`,checkFirmwareDescription:`Nach Firmware-Updates von Bambu Lab suchen`,bambuddySoftware:`Bambuddy-Software`,autoCheckDescription:`Automatisch beim Start nach neuen Versionen suchen`,checkNow:`Jetzt prüfen`,updateAvailableVersion:`Update verfügbar: v{{version}}`,releaseNotes:`Versionshinweise`,updateViaDocker:`Update über Docker Compose:`,updateViaHomeAssistant:`Updates werden vom Home Assistant Supervisor verwaltet. Öffne Einstellungen → Add-ons → Bambuddy in Home Assistant, um die neue Version zu installieren.`,updateViaWindowsInstaller:`Windows-Installationen werden durch erneutes Ausführen des Installers aktualisiert. Lade die neue Version unten herunter — deine Daten, Einstellungen und Drucker bleiben erhalten.`,downloadWindowsInstaller:`Installer für v{{version}} herunterladen`,installUpdate:`Update installieren`,latestVersionRunning:`Sie verwenden die neueste Version`,failedToCheckUpdates:`Update-Prüfung fehlgeschlagen: {{error}}`,backupRestore:`Sicherung & Wiederherstellung`,backupRestoreDescription:`Einstellungen exportieren/importieren und GitHub-Backup konfigurieren`,goToBackup:`Zur Sicherung`,externalUrl:`Externe URL`,externalUrlDescription:`Die externe URL, unter der Bambuddy erreichbar ist. Wird für Benachrichtigungsbilder und externe Integrationen verwendet.`,bambuddyUrl:`Bambuddy-URL`,externalUrlHint:`Protokoll und Port angeben (z.B. http://192.168.1.100:8000)`,ftpRetry:`FTP-Wiederholung`,ftpRetryDescription:`FTP-Operationen bei unzuverlässigem Drucker-WLAN wiederholen. Gilt für 3MF-Downloads, Druck-Uploads, Zeitraffer-Downloads und Firmware-Updates.`,autoRetryDescription:`Fehlgeschlagene FTP-Operationen automatisch wiederholen`,retryAttempts:`Wiederholungsversuche`,retryDelay:`Wiederholungsverzögerung`,connectionTimeout:`Verbindungs-Timeout`,time_one:`{{count}} Mal`,time_other:`{{count}} Mal`,second_one:`{{count}} Sekunde`,second_other:`{{count}} Sekunden`,nSeconds:`{{count}} Sekunden`,increaseForWeakWifi:`Erhöhen für Drucker mit schwachem WLAN`,homeAssistant:`Home Assistant`,homeAssistantFullDescription:`Mit Home Assistant verbinden, um Smart Plugs über die HA REST-API zu steuern. Unterstützt Switch-, Light-, Input_Boolean- und Script-Entitäten.`,homeAssistantUrl:`Home Assistant URL`,longLivedAccessToken:`Langlebiges Zugriffstoken`,haTokenHint:`Token in HA erstellen: Profil → Langlebige Zugriffstoken → Token erstellen`,connectionSuccessful:`Verbindung erfolgreich`,connectionFailed:`Verbindung fehlgeschlagen`,haConnectionSuccess:`Erfolgreich mit Home Assistant verbunden.`,haConnectionFailed:`Verbindung zu Home Assistant fehlgeschlagen.`,mqttPublishing:`MQTT-Veröffentlichung`,mqttDescription:`BamBuddy-Ereignisse an einen externen MQTT-Broker zur Integration mit Node-RED, Home Assistant und anderen Automatisierungssystemen veröffentlichen.`,mqttEnableDescription:`Ereignisse an externen MQTT-Broker veröffentlichen`,brokerHostname:`Broker-Hostname`,port:`Port`,usernameOptional:`Benutzername (optional)`,passwordOptional:`Passwort (optional)`,topicPrefix:`Topic-Präfix`,topicPrefixHint:`Topics werden sein: {{prefix}}/printers//status, etc.`,prometheusMetrics:`Prometheus-Metriken`,prometheusEndpointDescription:`Druckermetriken unter /api/v1/metrics für Prometheus/Grafana-Überwachung bereitstellen.`,bearerTokenOptional:`Bearer-Token (optional)`,bearerTokenHint:`Wenn gesetzt, müssen Anfragen Authorization: Bearer enthalten`,metricsConnectionStatus:`Verbindungsstatus`,metricsPrinterState:`Druckerstatus (idle/printing/etc)`,metricsPrintProgress:`Druckfortschritt 0-100%`,metricsBedTemp:`Betttemperatur`,metricsNozzleTemp:`Düsentemperatur`,metricsPrintsTotal:`Gesamtdrucke nach Ergebnis`,metricsMore:`...und mehr (Schichten, Lüfter, Warteschlange, Filamentverbrauch)`,smartPlugsDescription:`Smart Plugs (Tasmota oder Home Assistant) verbinden, um Stromsteuerung zu automatisieren und Energieverbrauch für Ihre Drucker zu verfolgen.`,allOn:`Alle Ein`,allOff:`Alle Aus`,addSmartPlug:`Smart Plug hinzufügen`,energySummary:`Energieübersicht`,currentPower:`Aktuelle Leistung`,plugsOnline:`{{reachable}}/{{total}} Plugs online`,today:`Heute`,yesterday:`Gestern`,total:`Gesamt`,enablePlugsForSummary:`Plugs aktivieren, um Energieübersicht zu sehen`,addNotificationProvider:`Hinzufügen`,systemBadge:`(System)`,creating:`Erstellen...`,changing:`Ändern...`,deleteUserAndItems:`Benutzer UND dessen Elemente löschen`,deleteUserKeepItems:`Benutzer löschen, Elemente behalten (werden herrenlos)`,ok:`OK`,twoFa:{totpTitle:`Authenticator-App (TOTP)`,totpDesc:`Verwende eine Authenticator-App wie Google Authenticator, Aegis oder Authy.`,emailOtpTitle:`E-Mail OTP`,emailOtpDesc:`Sende einen Einmalcode an {{email}} beim Einloggen.`,emailOtpNoEmail:`Füge eine E-Mail-Adresse zu deinem Konto hinzu, um diese Methode zu aktivieren.`,addEmailFirst:`Dein Konto hat keine E-Mail-Adresse. Bitte einen Administrator, eine hinzuzufügen.`,setupTotp:`Authenticator-App einrichten`,setupAuthApp:`Authenticator-App einrichten`,setupInstructions:`Scanne den QR-Code mit deiner Authenticator-App und bestätige mit einem Code.`,manualEntry:`Kein Scanner? Gib dieses Secret manuell ein:`,scannedContinue:`Code gescannt — weiter`,enterCodeToConfirm:`Gib den 6-stelligen Code aus deiner Authenticator-App ein, um die Einrichtung zu bestätigen.`,activate:`Aktivieren`,disableTotp:`Authenticator deaktivieren`,disableConfirmHint:`Gib einen gültigen TOTP-Code oder einen Backup-Code ein, um den Authenticator zu deaktivieren.`,totpDisabled:`Authenticator-App deaktiviert.`,emailOtpEnabled:`E-Mail OTP aktiviert.`,emailOtpDisabled:`E-Mail OTP deaktiviert.`,smtpRequired:`Bitte konfigurieren und testen Sie zuerst die SMTP-Einstellungen.`,invalidCode:`Ungültiger Code. Bitte erneut versuchen.`,enableEmailOtp:`E-Mail OTP aktivieren`,disableEmailOtp:`E-Mail OTP deaktivieren`,emailSetupEnterCode:`Ein Bestätigungscode wurde an Ihre E-Mail-Adresse gesendet. Geben Sie ihn unten ein, um zu bestätigen, dass Ihnen dieses Postfach gehört.`,verifyAndEnable:`Verifizieren & Aktivieren`,emailDisablePasswordHint:`Geben Sie Ihr Kontopasswort ein, um die Deaktivierung des E-Mail OTP zu bestätigen.`,passwordPlaceholder:`Passwort eingeben`,backupCodesTitle:`Backup-Codes sichern`,backupCodesWarning:`Speichere diese Codes sicher. Jeder Code kann nur einmal verwendet werden und wird nicht erneut angezeigt.`,backupCodesRemaining:`{{count}} Backup-Codes verbleibend`,savedCodes:`Codes gespeichert`,regenBackup:`Backup-Codes neu generieren`,regenBackupHint:`Gib deinen aktuellen TOTP-Code ein, um 10 neue Backup-Codes zu generieren. Alle bestehenden Codes werden ungültig.`,newBackupCodes:`Neue Backup-Codes`,linkedAccounts:`Verknüpfte SSO-Konten`,linkedAccountsDesc:`Diese externen Identitätsanbieter sind mit deinem Konto verknüpft.`,oidcUnlinked:`Konto getrennt.`},sessionPolicy:{title:`Sitzungsrichtlinie`,description:`Maximale Sitzungsdauer für neue Benutzeranmeldungen. Bereits ausgegebene Token behalten ihren ursprünglichen Ablauf.`,preset24h:`24 Stunden`,preset7d:`7 Tage`,preset30d:`30 Tage`,customHoursLabel:`Individuelle Sitzungsdauer in Stunden`,hoursSuffix:`Stunden`,warning:`Längere Sitzungen reduzieren den automatischen Abmeldeschutz. Nur für vertrauenswürdige Einzelnutzer-Installationen empfohlen.`},oidc:{title:`SSO / OIDC-Anbieter`,desc:`Konfiguriere OpenID Connect-Anbieter für Single Sign-On.`,addProvider:`Anbieter hinzufügen`,newProvider:`Neuer Anbieter`,empty:`Noch keine OIDC-Anbieter konfiguriert.`,created:`Anbieter erstellt.`,updated:`Anbieter aktualisiert.`,deleted:`Anbieter gelöscht.`,refreshIcon:`Icon neu laden`,removeIcon:`Icon entfernen`,iconRefreshed:`Icon aktualisiert.`,iconRemoved:`Icon entfernt.`,iconFetchFailed:`Icon konnte von der Anbieter-URL nicht geladen werden.`,deleteTitle:`Anbieter löschen`,deleteMessage:`"{{name}}" löschen? Alle verknüpften Benutzerkonten werden getrennt.`,form:{name:`Anzeigename`,issuerUrl:`Aussteller-URL`,clientId:`Client-ID`,clientSecret:`Client-Secret`,scopes:`Bereiche`,iconUrl:`Symbol-URL (optional)`,enabled:`Aktiviert`,autoCreate:`Benutzer automatisch anlegen`,autoCreateDesc:`Erstellt beim ersten Login automatisch ein lokales Konto.`,autoLink:`Bestehende Konten automatisch verknüpfen`,autoLinkDesc:`Verknüpft beim ersten Login vorhandene lokale Konten anhand der E-Mail-Adresse.`,secretHint:`leer lassen zum Beibehalten`,secretPlaceholder:`neues Secret`,emailClaim:`E-Mail-Claim`,emailClaimDesc:`JWT-Claim für die E-Mail-Identität. Für Azure Entra ID 'preferred_username' oder 'upn' verwenden (sendet kein email_verified). Nur vertrauenswürdige Claim-Namen verwenden.`,emailClaimPlaceholder:`E-Mail`,emailClaimCustomClaimAutoLinkWarning:`Benutzerdefinierte Claims sind für die Auto-Verknüpfung nur sicher, wenn der Wert vom Mandanten verwaltet wird (z. B. Azure Entra ID upn / preferred_username). Aktiviere Auto-Verknüpfung nicht, wenn dein IdP Benutzern erlaubt, diesen Claim selbst zu setzen.`,requireEmailVerified:`E-Mail-Verifizierung erforderlich`,requireEmailVerifiedDesc:`E-Mail-Claim nur akzeptieren, wenn der Provider ihn als verifiziert markiert.`,requireEmailVerifiedWarning:`Warnung: E-Mail wird auch ohne Verifizierung akzeptiert. Nur bei vertrauenswürdigen Providern verwenden.`,requireEmailVerifiedAutoLink:`Auto-Verknüpfung zuerst deaktivieren, um diese Einstellung zu ändern.`,defaultGroup:`Standardgruppe`,defaultGroupDesc:`Gruppe, der automatisch erstellte Benutzer zugewiesen werden. Fallback auf Viewers, wenn nicht gesetzt.`,defaultGroupViewersFallback:`Viewers (Standard)`,autologin:`Automatische Anmeldung`,autologinDesc:`Nicht angemeldete Besucher direkt zu diesem Anbieter weiterleiten. Diese Option kann nur für einen Anbieter aktiv sein.`}},encryption:{title:`MFA-Verschlüsselungsstatus`,enabledFromEnv:`At-Rest-Verschlüsselung aktiv (Schlüssel aus Umgebungsvariable MFA_ENCRYPTION_KEY)`,enabledFromFile:`At-Rest-Verschlüsselung aktiv (Schlüssel aus dem Datenverzeichnis geladen)`,enabledGenerated:`At-Rest-Verschlüsselung aktiv mit automatisch generiertem Schlüssel`,notConfigured:`At-Rest-Verschlüsselung nicht konfiguriert`,notConfiguredDesc:`TOTP-Geheimnisse und OIDC-Client-Secrets werden im Klartext gespeichert. Setze MFA_ENCRYPTION_KEY oder starte Bambuddy mit beschreibbarem Datenverzeichnis neu, damit ein Schlüssel automatisch erzeugt wird.`,allEncrypted:`Alle MFA-Geheimnisse sind verschlüsselt gespeichert.`,legacyRowsLabel:`Klartext-Zeilen (Altbestand)`,encryptedRowsLabel:`Verschlüsselte Zeilen`,legacyRowsWarning:`{{count}} Klartext-Zeile(n) erkannt. Den OIDC-Provider neu speichern oder den Authenticator des Benutzers neu einrichten, um die Daten verschlüsselt abzulegen.`,backupHint:`Der automatisch erzeugte Schlüssel liegt unter DATA_DIR/.mfa_encryption_key und wird in lokalen Backup-ZIPs mitgesichert. Backups sicher aufbewahren oder MFA_ENCRYPTION_KEY explizit setzen.`,decryptionBrokenTitle:`Verschlüsselungsschlüssel fehlt`,decryptionBrokenError:`{{count}} verschlüsselte Datensätze können nicht entschlüsselt werden, weil der Schlüssel nicht mehr verfügbar ist. Den vorherigen MFA_ENCRYPTION_KEY oder DATA_DIR/.mfa_encryption_key wiederherstellen.`,migrationErrorWarning:`{{count}} Legacy-Eintrag/Einträge konnten beim Start nicht verschlüsselt werden. Prüfen Sie die Server-Logs und starten Sie Bambuddy neu.`},pipelineLimits:{title:`Slicer-Pipeline-Limits`,maxCopiesLabel:`Max. Kopien pro Lauf`,maxCopiesDesc:`Obergrenze für die Anzahl an Kopien, die Operatoren beim Ausführen einer Pipeline anfordern können. Serverseitige Obergrenze ist 1000.`},pipelines:{title:`Slicer-Pipelines`,subtitle:`Wiederverwendbare Preset-Bundles (Drucker + Prozess + Filamente + Druckplatte). Speichere eines aus dem Slice-Dialog und wende es beim nächsten Datei-Slice mit einem Klick an.`,loading:`Pipelines werden geladen…`,loadError:`Pipelines konnten nicht geladen werden.`,confirmDelete:`Diese Pipeline löschen? Das kann nicht rückgängig gemacht werden.`,staleWarning:`Eines oder mehrere referenzierte Presets existieren nicht mehr. Speichere diese Pipeline erneut aus dem Slice-Dialog, um sie zu reparieren.`,empty:{title:`Noch keine Pipelines.`,howto:`Öffne den Slice-Dialog für eine beliebige Datei, wähle Drucker / Prozess / Filamente / Druckplatte und klicke „Als Pipeline speichern“. Deine gespeicherten Pipelines erscheinen hier.`},field:{name:`Pipeline-Name`,description:`Beschreibung`,targetPrinter:`Zieldrucker`,noTarget:`— Kein Ziel —`,targetKind:`Zielart`,targetKindSpecific:`Spezifischer Drucker`,targetKindClass:`Druckerklasse`,targetModelClass:`Druckermodell`,fanoutStrategy:`Verteilungsstrategie`,fanout:{max_parallel:`Max parallel — auf alle verfügbaren passenden Drucker verteilen`,round_robin:`Reihum — durch geeignete Drucker rotieren`,fill_one_first:`Erst einen füllen — alle Kopien an einen Drucker binden`},fanoutShort:{max_parallel:`parallel`,round_robin:`Reihum`,fill_one_first:`einer zuerst`}},action:{save:`Speichern`,cancel:`Abbrechen`,rename:`Umbenennen`,delete:`Löschen`},slot:{printer:`Drucker`,process:`Prozess`,filament:`Filament`,filamentN:`Filament {{n}}`,filamentAll:`Alle {{n}} Slots`,bed:`Druckplatte`},group:{profiles:`Profile`,filaments:`Filamente`},searchPlaceholder:`Pipelines durchsuchen…`,filterTargetType:`Nach Zielart filtern`,filterTarget:`Nach Ziel filtern`,filter:{all:`Alle Ziele`,noTarget:`Kein Ziel festgelegt`,count:`{{shown}} / {{total}}`,noMatches:`Keine Pipelines entsprechen den aktuellen Filtern.`},toast:{saved:`Pipeline gespeichert`,saveFailed:`Speichern fehlgeschlagen`,deleted:`Pipeline gelöscht`,deleteFailed:`Löschen fehlgeschlagen`},noTargetHint:`Lege einen Zieldrucker fest, um diese auszuführen`,noTargetWarning:`Lege einen Zieldrucker fest, bevor du diese Pipeline ausführst.`,runs:{lastRun:`Letzter Lauf`,status:{queued:`in Warteschlange`,slicing:`wird geschnitten`,dispatching:`wird gesendet`,in_progress:`druckt`,completed:`abgeschlossen`,failed:`fehlgeschlagen`,partial_failure:`teilweise fehlgeschlagen`,cancelled:`abgebrochen`}}}},notification:{printStarted:{title:`Druck gestartet`,body:`{{printer}}: {{filename}} wird gedruckt`},printCompleted:{title:`Druck abgeschlossen`,body:`{{printer}}: {{filename}} erfolgreich abgeschlossen`},printFailed:{title:`Druck fehlgeschlagen`,body:`{{printer}}: {{filename}} ist fehlgeschlagen`},printStopped:{title:`Druck gestoppt`,body:`{{printer}}: {{filename}} wurde gestoppt`},printProgress:{title:`Druckfortschritt`,body:`{{printer}}: {{filename}} ist zu {{percent}}% abgeschlossen`},printerOffline:{title:`Drucker offline`,body:`{{printer}} ist offline`},printerError:{title:`Druckerfehler`,body:`{{printer}} – {{error}}`},filamentLow:{title:`Filament niedrig`,body:`{{printer}}: Filament geht zur Neige`},maintenanceDue:{title:`Wartung fällig`,body:`{{printer}}: {{items}} benötigen Aufmerksamkeit`}},errors:{generic:`Etwas ist schiefgelaufen`,networkError:`Netzwerkfehler. Bitte überprüfen Sie Ihre Verbindung.`,notFound:`Nicht gefunden`,unauthorized:`Nicht autorisiert`,serverError:`Serverfehler`,validationError:`Bitte überprüfen Sie Ihre Eingabe`,printerConnectionFailed:`Verbindung zum Drucker fehlgeschlagen`,saveFailed:`Speichern fehlgeschlagen`,deleteFailed:`Löschen fehlgeschlagen`,loadFailed:`Laden der Daten fehlgeschlagen`},hmsErrors:{title:`Fehler - {{name}}`,noErrors:`Keine Fehler`,viewOnWiki:`Im Bambu Lab Wiki ansehen`,mqttVerifyFailedRemedy:`Aktiviere den Entwicklermodus am Drucker, starte den Drucker neu und starte den Auftrag dann erneut.`,unknownCode:`Unbekannter HMS-Code — Details siehe Bambu Lab Wiki.`,clearInstructions:`Löschen Sie die Fehler am Drucker, um sie hier zu entfernen.`,clearErrors:`Fehler löschen`,clearSuccess:`HMS-Fehler gelöscht`,clearFailed:`HMS-Fehler konnten nicht gelöscht werden`,actionSuccess:`Aktion an Drucker gesendet`,actionFailed:`Aktion konnte nicht gesendet werden`,runoutExpectedSlot:`Das Filament in {{ranOut}} ist aufgebraucht. Der Drucker wartet jetzt auf kompatibles Filament in {{expected}}. Legen Sie eine Spule in {{expected}} ein und wählen Sie dann Wiederholen.`,runoutExpectedSlotOnly:`Der Drucker wartet auf kompatibles Filament in {{expected}}. Legen Sie dort eine Spule ein und wählen Sie dann Wiederholen.`,runoutSlotUnknown:`Das Filament ist aufgebraucht und der Druck ist pausiert. Bambuddy konnte nicht ermitteln, welchen Slot der Drucker jetzt erwartet — prüfen Sie am Druckerdisplay, welcher Slot angefordert wird.`,actions:{RESUME_PRINTING:`Druck fortsetzen`,RESUME_PRINTING_DEFECTS:`Fortsetzen (Mängel akzeptabel)`,RESUME_PRINTING_PROBELM_SOLVED:`Fortsetzen (Problem gelöst)`,STOP_PRINTING:`Druck stoppen`,CHECK_ASSISTANT:`Assistent öffnen`,FILAMENT_EXTRUDED:`Filament extrudiert, weiter`,RETRY_FILAMENT_EXTRUDED:`Noch nicht extrudiert, erneut`,CONTINUE:`Fertig, weiter`,LOAD_VIRTUAL_TRAY:`Filament laden`,OK_BUTTON:`OK`,FILAMENT_LOAD_RESUME:`Filament geladen, fortsetzen`,JUMP_TO_LIVEVIEW:`Live-Ansicht öffnen`,NO_REMINDER_NEXT_TIME:`Nicht mehr erinnern`,REFRESH_NOZZLE:`Erneut prüfen`,IGNORE_NO_REMINDER_NEXT_TIME:`Ignorieren und nicht mehr erinnern`,IGNORE_RESUME:`Ignorieren und fortsetzen`,PROBLEM_SOLVED_RESUME:`Problem gelöst, fortsetzen`,TURN_OFF_FIRE_ALARM:`Verstanden, Brandalarm ausschalten`,RETRY_PROBLEM_SOLVED:`Erneut versuchen (Problem gelöst)`,CANCLE:`Abbrechen`,STOP_DRYING:`Trocknen stoppen`,PROCEED:`Fortfahren`,OK_JUMP_RACK:`OK`,ABORT:`Abbrechen`,DISABLE_PURIFICATION:`Luftreinigung für diesen Druck deaktivieren`,DONT_REMIND_NEXT_TIME:`Nicht mehr erinnern`,DBL_CHECK_CANCEL:`Abbrechen`,DBL_CHECK_DONE:`Fertig`,DBL_CHECK_RETRY:`Erneut versuchen`,DBL_CHECK_RESUME:`Fortsetzen`,DBL_CHECK_OK:`Bestätigen`,REMOVE_CLOSE_BTN:`Schließen`}},mqttDebug:{title:`MQTT-Debug-Protokoll`,searchPlaceholder:`Topic oder Payload suchen...`,noMessages:`Noch keine Nachrichten protokolliert`,startLoggingHint:`Klicken Sie auf "Protokollierung starten", um MQTT-Nachrichten aufzuzeichnen`,noMessagesMatch:`Keine Nachrichten entsprechen Ihrem Filter`,adjustFilterHint:`Versuchen Sie, Ihre Such- oder Filterkriterien anzupassen`,incoming:`Eingehend`,outgoing:`Ausgehend`,loggingStopped:`Protokollierung gestoppt`,loggingActive:`Protokollierung aktiv - Nachrichten werden automatisch aktualisiert`,startLogging:`Protokollierung starten`,stopLogging:`Protokollierung stoppen`,clearLog:`Protokoll löschen`,topic:`Thema`,timestamp:`Zeitstempel`,direction:`Richtung`,all:`Alle`},printerFiles:{title:`Dateimanager`,storageUsed:`Belegt:`,storageFree:`Frei:`,filterPlaceholder:`Dateien filtern...`,deleteButton:`Löschen`,deleteFiles:`{{count}} Dateien löschen`,deleteFileConfirm:`"{{name}}" löschen? Dies kann nicht rückgängig gemacht werden.`,deleteFilesConfirm:`{{count}} ausgewählte Dateien löschen? Dies kann nicht rückgängig gemacht werden.`,noFiles:`Keine Dateien auf dem Drucker`,loadingFiles:`Dateien werden geladen...`,failedToLoad:`Dateien konnten nicht geladen werden`,toast:{filesDeleted:`{{count}} Datei(en) gelöscht`,deleteFailed:`Löschen fehlgeschlagen: {{error}}`}},confirm:{delete:`Möchten Sie dies wirklich löschen?`,unsavedChanges:`Sie haben ungespeicherte Änderungen. Möchten Sie wirklich verlassen?`,clearQueue:`Möchten Sie die Warteschlange wirklich leeren?`},login:{title:`Bambuddy Anmeldung`,subtitle:`Melden Sie sich bei Ihrem Konto an`,username:`Benutzername`,usernamePlaceholder:`Benutzername eingeben`,usernameOrEmail:`Benutzername oder E-Mail`,usernameOrEmailPlaceholder:`Benutzername oder @ E-Mail`,password:`Passwort`,passwordPlaceholder:`Passwort eingeben`,signIn:`Anmelden`,signingIn:`Anmeldung läuft...`,rememberMe:`Angemeldet bleiben`,forgotPassword:`Passwort vergessen?`,autologinFailed:`Automatische SSO-Anmeldung fehlgeschlagen. Bitte wählen Sie unten einen Anbieter.`,localDisabledNotice:`Lokale Anmeldung ist deaktiviert. Bitte verwenden Sie einen der SSO-Anbieter unten.`,loginSuccess:`Erfolgreich angemeldet`,loginFailed:`Anmeldung fehlgeschlagen`,enterCredentials:`Bitte Benutzername und Passwort eingeben`,enterEmail:`Bitte geben Sie Ihre E-Mail-Adresse ein`,oidcLoginFailed:`OIDC-Anmeldung fehlgeschlagen`,oidcErrors:{providerError:`Der Identity-Provider hat einen Fehler zurückgegeben`,missingParameters:`Dem OIDC-Callback fehlen erforderliche Parameter`,invalidState:`OIDC-State ist ungültig oder wurde bereits verwendet`,stateExpired:`OIDC-Sitzung abgelaufen — bitte erneut versuchen`,providerNotFound:`OIDC-Provider nicht gefunden`,discoveryFailed:`OIDC-Discovery-Dokument konnte nicht abgerufen werden`,invalidDiscovery:`OIDC-Discovery-Dokument ist ungültig`,networkError:`Netzwerkfehler beim OIDC-Token-Austausch`,badResponse:`Unerwartete Antwort beim OIDC-Token-Austausch`,noIdToken:`OIDC-Provider hat kein ID-Token zurückgegeben`,validationFailed:`OIDC-Token-Validierung fehlgeschlagen`,nonceMismatch:`OIDC-Nonce stimmt nicht überein — möglicher Replay-Angriff`,missingSubClaim:`OIDC-Token enthält keinen Sub-Claim`,noLinkedAccount:`Kein lokales Konto mit dieser OIDC-Identität verknüpft`,accountInactive:`Ihr Konto ist inaktiv`,userResolutionFailed:`Ihr Konto konnte nicht aufgelöst werden`,internalError:`Interner Fehler beim OIDC-Login`,tokenExchangeFailed:`OIDC-Token-Austausch fehlgeschlagen`},forgotPasswordTitle:`Passwort vergessen`,forgotPasswordMessage:`Wenn Sie Ihr Passwort vergessen haben, wenden Sie sich bitte an Ihren Systemadministrator.`,forgotPasswordEmailMessage:`Geben Sie Ihre E-Mail-Adresse ein und wir senden Ihnen ein neues Passwort.`,emailAddress:`E-Mail-Adresse`,emailPlaceholder:`ihre.email@beispiel.de`,cancel:`Abbrechen`,sending:`Wird gesendet...`,sendResetEmail:`Zurücksetzungs-E-Mail senden`,howToReset:`So setzen Sie Ihr Passwort zurück:`,resetStep1:`Kontaktieren Sie Ihren Bambuddy-Administrator`,resetStep2:`Bitten Sie ihn, Ihr Passwort in der Benutzerverwaltung zurückzusetzen`,resetStep3:`Er kann ein neues temporäres Passwort für Sie festlegen`,resetStep4:`Melden Sie sich mit dem neuen Passwort an und ändern Sie es in den Einstellungen`,gotIt:`Verstanden`,resetPassword:{title:`Neues Passwort festlegen`,subtitle:`Geben Sie unten Ihr neues Passwort ein und bestätigen Sie es.`,newPassword:`Neues Passwort`,newPasswordPlaceholder:`Mindestens 8 Zeichen`,confirmPassword:`Passwort bestätigen`,confirmPasswordPlaceholder:`Neues Passwort wiederholen`,saving:`Wird gespeichert…`,submit:`Neues Passwort festlegen`,backToLogin:`Zurück zur Anmeldung`,passwordsDoNotMatch:`Passwörter stimmen nicht überein`,passwordTooShort:`Passwort muss mindestens 8 Zeichen lang sein`,resetFailed:`Passwort zurücksetzen fehlgeschlagen. Der Link ist möglicherweise abgelaufen.`},twoFA:{title:`Zwei-Faktor-Authentifizierung`,subtitle:`Ihr Konto ist mit 2FA geschützt. Geben Sie unten den Bestätigungscode ein.`,methodAuthenticator:`Authenticator-App`,methodEmail:`E-Mail-Code`,methodBackup:`Wiederherstellungscode`,instructionsTotp:`Öffnen Sie Ihre Authenticator-App und geben Sie den 6-stelligen Code für Bambuddy ein.`,instructionsEmail:`Ein 6-stelliger Code wurde an Ihre E-Mail-Adresse gesendet. Er ist 10 Minuten gültig.`,instructionsEmailNotSent:`Klicken Sie unten, um einen Bestätigungscode per E-Mail zu erhalten.`,instructionsBackup:`Geben Sie einen Ihrer 8-stelligen Wiederherstellungscodes ein. Jeder Code kann nur einmal verwendet werden.`,sendCodeButton:`Code per E-Mail senden`,sendingCode:`Wird gesendet...`,resendCode:`Code erneut senden`,codeLabel:`Bestätigungscode`,backupCodeLabel:`Wiederherstellungscode`,codePlaceholder:`000000`,backupCodePlaceholder:`XXXXXXXX`,verifyButton:`Bestätigen`,verifyingButton:`Wird überprüft...`,backToLogin:`← Zurück zur Anmeldung`,orContinueWith:`oder anmelden mit`,signInWith:`Anmelden mit {{provider}}`,enterCode:`Bitte geben Sie den Bestätigungscode ein`,sendCodeFailed:`Bestätigungscode konnte nicht gesendet werden`,invalidCode:`Ungültiger Code. Bitte erneut versuchen.`}},setup:{title:`Bambuddy Einrichtung`,subtitle:`Konfigurieren Sie die Authentifizierung für Ihre Bambuddy-Instanz`,enableAuth:`Authentifizierung aktivieren`,adminAccount:`Admin-Konto`,adminAccountDesc:`Wenn bereits Admin-Benutzer existieren, wird die Authentifizierung mit den vorhandenen Admin-Konten aktiviert. Lassen Sie die Felder unten leer, um vorhandene Admins zu verwenden, oder geben Sie neue Anmeldedaten ein, um einen neuen Admin-Benutzer zu erstellen.`,adminUsername:`Admin-Benutzername`,adminPassword:`Admin-Passwort`,optionalIfAdminExists:`(optional, wenn Admin-Benutzer existieren)`,adminUsernamePlaceholder:`Admin-Benutzernamen eingeben (optional)`,adminPasswordPlaceholder:`Admin-Passwort eingeben (optional)`,confirmPassword:`Passwort bestätigen`,confirmPasswordPlaceholder:`Admin-Passwort bestätigen`,settingUp:`Einrichtung läuft...`,completeSetup:`Einrichtung abschließen`,toast:{authEnabledAdminCreated:`Authentifizierung aktiviert und Admin-Benutzer erstellt`,authEnabledExistingAdmins:`Authentifizierung mit vorhandenen Admin-Benutzern aktiviert`,setupCompleted:`Einrichtung abgeschlossen`,enterBothCredentials:`Bitte geben Sie sowohl Admin-Benutzernamen als auch Passwort ein, oder lassen Sie beide leer, um vorhandene Admin-Benutzer zu verwenden`,passwordsDoNotMatch:`Passwörter stimmen nicht überein`,passwordTooShort:`Passwort muss mindestens 6 Zeichen lang sein`}},changePassword:{title:`Passwort ändern`,currentPassword:`Aktuelles Passwort`,currentPasswordPlaceholder:`Aktuelles Passwort eingeben`,newPassword:`Neues Passwort`,newPasswordPlaceholder:`Neues Passwort eingeben (min. 6 Zeichen)`,confirmPassword:`Neues Passwort bestätigen`,confirmPasswordPlaceholder:`Neues Passwort bestätigen`,passwordsDoNotMatch:`Passwörter stimmen nicht überein`,passwordTooShort:`Passwort muss mindestens 6 Zeichen lang sein`,changing:`Wird geändert...`,success:`Passwort erfolgreich geändert`,failed:`Passwortänderung fehlgeschlagen`},plateAlert:{title:`Druck pausiert!`,message:`Objekte auf dem Druckbett erkannt. Der Druck wurde automatisch pausiert. Bitte räumen Sie das Druckbett und setzen Sie den Druck fort.`,understand:`Verstanden`},camera:{title:`Kameraansicht`,invalidPrinterId:`Ungültige Drucker-ID`,live:`Live`,snapshot:`Schnappschuss`,restartStream:`Stream neu starten`,refreshSnapshot:`Schnappschuss aktualisieren`,fullscreen:`Vollbild`,exitFullscreen:`Vollbild beenden`,connectingToCamera:`Verbinde mit Kamera...`,capturingSnapshot:`Schnappschuss wird aufgenommen...`,connectionLost:`Verbindung verloren`,connectionFailed:`Kameraverbindung fehlgeschlagen`,reconnecting:`Neuverbindung in {{countdown}}s... (Versuch {{attempt}}/{{max}})`,reconnectNow:`Jetzt verbinden`,cameraUnavailable:`Kamera nicht verfügbar`,cameraUnavailableDesc:`Stellen Sie sicher, dass der Drucker eingeschaltet und verbunden ist.`,noCamera:`Keine Kamera verfügbar`,retry:`Erneut versuchen`,cameraStream:`Kamera-Stream`,zoomOut:`Verkleinern`,zoomIn:`Vergrößern`,resetZoom:`Zoom zurücksetzen`,recording:`Aufnahme`,startRecording:`Aufnahme starten`,stopRecording:`Aufnahme stoppen`,chamberLight:`Kammerbeleuchtung umschalten`,unavailable:`Kamera nicht verfügbar`,diagnose:{button:`Diagnose`,modalTitle:`Kamera-Diagnose`,running:`Diagnose läuft...`,runFailed:`Diagnose konnte nicht ausgeführt werden: {{error}}`,retry:`Erneut ausführen`,stage:{tcp_reachable:`Netzwerk-Erreichbarkeit`,first_frame:`Bilderfassung`,live_stream_active:`Live-Stream aktiv`},summary:{all_ok:`Kamera funktioniert. Die Diagnose hat alle Phasen erfolgreich abgeschlossen.`,live_stream_active_healthy:`Kamera streamt gerade mit aktuellen Bildern — kein Test nötig.`,printer_unreachable:`Drucker ist nicht erreichbar. Prüfe IP-Adresse, Netzwerkverbindung und ob der Drucker eingeschaltet ist.`,camera_port_closed:`Drucker ist erreichbar, aber der Kamera-Port ist geschlossen. Stelle sicher, dass LAN-Modus und Entwicklermodus in den Druckereinstellungen aktiviert sind.`,no_frame:`Verbindung zur Kamera hergestellt, aber keine Bilder empfangen. Versuche es erneut oder prüfe, ob die Kamera in den Druckereinstellungen aktiviert ist.`,unknown_failure:`Kamera-Diagnose aus unbekanntem Grund fehlgeschlagen. Prüfe das Support-Log für Details.`},meta:{protocol:`Protokoll`,port:`Port`,profile:`Profil`}}},groups:{title:`Gruppenverwaltung`,subtitle:`Berechtigungsgruppen für Zugriffskontrolle verwalten`,backToSettings:`Zurück zu Einstellungen`,createGroup:`Gruppe erstellen`,noPermission:`Sie haben keine Berechtigung, auf diese Seite zuzugreifen.`,system:`System`,noDescription:`Keine Beschreibung`,usersCount:`{{count}} Benutzer`,permissionsCount:`{{count}} Berechtigungen`,edit:`Bearbeiten`,delete:`Löschen`,toast:{created:`Gruppe erfolgreich erstellt`,updated:`Gruppe erfolgreich aktualisiert`,deleted:`Gruppe erfolgreich gelöscht`,enterGroupName:`Bitte geben Sie einen Gruppennamen ein`},modal:{editGroup:`Gruppe bearbeiten`,createGroup:`Gruppe erstellen`,cancel:`Abbrechen`,saving:`Speichern...`,creating:`Erstellen...`,saveChanges:`Änderungen speichern`},form:{groupName:`Gruppenname`,groupNamePlaceholder:`Gruppennamen eingeben`,systemGroupWarning:`Systemgruppennamen können nicht geändert werden`,description:`Beschreibung`,descriptionPlaceholder:`Beschreibung eingeben (optional)`,permissions:`Berechtigungen ({{count}} ausgewählt)`},deleteModal:{title:`Gruppe löschen`,message:`Sind Sie sicher, dass Sie diese Gruppe löschen möchten? Benutzer in dieser Gruppe verlieren diese Berechtigungen.`,confirm:`Gruppe löschen`},editor:{title:`Gruppe bearbeiten`,createTitle:`Gruppe erstellen`,search:`Berechtigungen suchen...`,selectAll:`Alle auswählen`,clearAll:`Alle abwählen`,permissionsSelected:`{{count}} ausgewählt`,noResults:`Keine Berechtigungen entsprechen Ihrer Suche`,websocketHint:`Erforderlich für Live-Aktualisierungen. Ohne diese Berechtigung greift die Oberfläche auf regelmäßiges Abrufen zurück.`}},users:{title:`Benutzerverwaltung`,subtitle:`Benutzer und deren Zugriff auf Ihre Bambuddy-Instanz verwalten`,backToSettings:`Zurück zu Einstellungen`,createUser:`Benutzer erstellen`,noPermission:`Sie haben keine Berechtigung, auf diese Seite zuzugreifen.`,admin:`Admin`,noGroups:`Keine Gruppen`,active:`Aktiv`,inactive:`Inaktiv`,edit:`Bearbeiten`,delete:`Löschen`,system:`System`,noGroupsAvailable:`Keine Gruppen verfügbar`,table:{username:`Benutzername`,groups:`Gruppen`,status:`Status`,actions:`Aktionen`},toast:{created:`Benutzer erfolgreich erstellt`,updated:`Benutzer erfolgreich aktualisiert`,deleted:`Benutzer erfolgreich gelöscht`,fillRequired:`Bitte füllen Sie alle Pflichtfelder aus`,passwordsDoNotMatch:`Passwörter stimmen nicht überein`,passwordTooShort:`Passwort muss mindestens 6 Zeichen lang sein`,ldapProvisioned:`LDAP-Benutzer „{{username}}" bereitgestellt`},modal:{createUser:`Benutzer erstellen`,editUser:`Benutzer bearbeiten`,cancel:`Abbrechen`,creating:`Erstellen...`,saving:`Speichern...`,saveChanges:`Änderungen speichern`,advancedAuthSubtitle:`mit erweiterter Authentifizierung`,tabsAriaLabel:`Benutzerquelle`,localTab:`Lokal`,ldapTab:`LDAP`,ldapSearchLabel:`Verzeichnis durchsuchen`,ldapSearchPlaceholder:`Benutzername, Name oder E-Mail eingeben...`,ldapMinChars:`Mindestens 2 Zeichen für die Suche eingeben`,ldapTypeToSearch:`Tippen, um das LDAP-Verzeichnis zu durchsuchen`,ldapSearching:`Verzeichnis wird durchsucht...`,ldapNoResults:`Keine passenden Benutzer im Verzeichnis`,ldapSearchError:`Verzeichnissuche fehlgeschlagen. Bitte LDAP-Server-Status prüfen.`,ldapAlreadyProvisioned:`Bereits bereitgestellt`,ldapSelectedLabel:`Ausgewählt`,ldapProvision:`Benutzer bereitstellen`,ldapProvisioning:`Wird bereitgestellt...`,ldapErrorProvision:`Bereitstellung fehlgeschlagen. Bitte LDAP-Server-Status prüfen und erneut versuchen.`},form:{username:`Benutzername`,usernamePlaceholder:`Benutzernamen eingeben`,email:`E-Mail`,emailPlaceholder:`benutzer@beispiel.de`,password:`Passwort`,passwordPlaceholder:`Passwort eingeben`,confirmPassword:`Passwort bestätigen`,confirmPasswordPlaceholder:`Passwort bestätigen`,newPasswordPlaceholder:`Neues Passwort eingeben`,confirmNewPasswordPlaceholder:`Neues Passwort bestätigen`,leaveBlankToKeep:`leer lassen, um das aktuelle zu behalten`,groups:`Gruppen`,optional:`optional`,autoGeneratedPassword:`Ein sicheres Passwort wird automatisch generiert und per E-Mail an den Benutzer gesendet.`,passwordManagedByAdvancedAuth:`Das Passwort wird durch erweiterte Authentifizierung verwaltet. Verwenden Sie "Passwort zurücksetzen", um ein neues Passwort per E-Mail an den Benutzer zu senden.`,resetPassword:`Passwort zurücksetzen`,resettingPassword:`Passwort wird zurückgesetzt...`},deleteModal:{title:`Benutzer löschen`,message:`Sind Sie sicher, dass Sie diesen Benutzer löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.`,confirm:`Benutzer löschen`}},streamOverlay:{title:`Stream-Overlay`,invalidPrinterId:`Ungültige Drucker-ID`,cameraStream:`Kamera-Stream`,progress:`Fortschritt`,eta:`ETA`,printerIdle:`Drucker ist inaktiv`,printerOffline:`Drucker offline`,status:{printing:`Druckt`,paused:`Pausiert`,finished:`Fertig`,failed:`Fehlgeschlagen`,idle:`Inaktiv`,unknown:`Unbekannt`}},profiles:{title:`Profile`,subtitle:`Verwalten Sie Ihre Slicer-Voreinstellungen und Druckvorschub-Kalibrierungen`,tabs:{bambuCloud:`Bambu Cloud`,orcaCloud:`Orca Cloud`,local:`Lokale Profile`,kprofiles:`K-Profile`},orcaCloud:{connectedAs:`Verbunden als`,connectedShort:`Mit Orca Cloud verbunden`,logout:`Trennen`,noLogoutPermission:`Sie haben keine Berechtigung zum Trennen`,noConnectPermission:`Sie haben keine Berechtigung, sich mit Orca Cloud zu verbinden`,retry:`Erneut versuchen`,connectButton:`Orca Cloud verbinden`,connect:{title:`Mit Orca Cloud verbinden`,description:`Melden Sie sich bei Ihrem Orca Cloud-Konto an, um Ihre Slicer-Profile in Bambuddy zu synchronisieren.`},device:{title:`Bambuddy in Orca Cloud genehmigen`,instruction:`Öffnen Sie Orca Cloud und genehmigen Sie diesen Code. Bambuddy verbindet sich automatisch, sobald Sie genehmigt haben.`,codeLabel:`Ihr Kopplungscode`,openButton:`Orca Cloud-Genehmigungsseite öffnen`,manualHint:`Oder gehen Sie zu {{url}} und geben Sie den obigen Code ein.`,waiting:`Warte auf Ihre Genehmigung…`,cancel:`Abbrechen`},profiles:{title:`Ihre Orca Cloud-Profile ({{count}})`,refresh:`Aktualisieren`,empty:`Noch keine Profile in Ihrem Orca Cloud-Konto gefunden.`},toast:{disconnected:`Verbindung zu Orca Cloud getrennt`},errors:{startFailed:`Anmeldevorgang für Orca Cloud konnte nicht gestartet werden.`,denied:`Die Kopplung wurde in Orca Cloud abgelehnt.`,expired:`Der Kopplungscode ist abgelaufen. Klicken Sie auf Verbinden, um es erneut zu versuchen.`,pollFailed:`Die Verbindung ging beim Warten auf die Genehmigung verloren. Bitte versuchen Sie es erneut.`}},localProfiles:{title:`Lokale Profile`,subtitle:`Slicer-Voreinstellungen aus OrcaSlicer importieren und verwalten`,import:`Profile importieren`,importDesc:`.bbscfg-, .bbsflmt-, .orca_filament-, .zip- oder .json-Dateien hier ablegen`,importing:`Importiere...`,search:`Lokale Voreinstellungen durchsuchen...`,noPresets:`Noch keine lokalen Voreinstellungen`,noSearchResults:`Keine Voreinstellungen entsprechen deiner Suche`,badge:`Lokal`,edit:`Bearbeiten`,delete:`Löschen`,cancel:`Abbrechen`,deleteConfirmTitle:`Voreinstellung löschen`,deleteConfirm:`Möchten Sie diese Voreinstellung wirklich löschen? Dies kann nicht rückgängig gemacht werden.`,source:`Quelle`,inheritsFrom:`Erbt von`,filamentType:`Typ`,vendor:`Hersteller`,compatiblePrinters:`Drucker`,nozzleTemp:`Düsentemperatur`,cost:`Kosten`,density:`Dichte`,pressureAdvance:`Druckvorschub`,filament:`Filament`,process:`Prozess`,printer:`Drucker`,toast:{importSuccess:`{{count}} Voreinstellung(en) importiert`,importSkipped:`{{count}} Voreinstellung(en) übersprungen (Duplikate)`,importError:`{{count}} Fehler beim Import`,deleted:`Voreinstellung gelöscht`,updated:`Voreinstellung aktualisiert`}},connectedAs:`Verbunden als`,signInExpiredTitle:`Bambu-Cloud-Anmeldung abgelaufen`,signInExpiredBody:`Bambu Lab akzeptiert das gespeicherte Token nicht mehr. Melden Sie sich erneut an, um Cloud-Profile, MakerWorld-Importe und Firmware-Prüfungen wiederherzustellen.`,logout:`Abmelden`,noLogoutPermission:`Sie haben keine Berechtigung zum Abmelden`,failedToLoad:`Profile konnten nicht geladen werden`,retry:`Erneut versuchen`,time:{justNow:`Gerade eben`,minsAgo:`vor {{count}}m`,hoursAgo:`vor {{count}}h`,daysAgo:`vor {{count}}d`},toast:{loggedOut:`Abgemeldet`},login:{title:`Mit Bambu Cloud verbinden`,subtitle:`Synchronisieren Sie Ihre Slicer-Voreinstellungen geräteübergreifend`,email:`E-Mail`,password:`Passwort`,region:`Region`,regionGlobal:`Global`,regionChina:`China`,verificationCode:`Bestätigungscode`,totpCode:`Authenticator-Code`,checkEmail:`Prüfen Sie Ihre E-Mail ({{email}}) für einen 6-stelligen Code`,enterTotpHint:`Geben Sie den 6-stelligen Code aus Ihrer Authenticator-App ein`,accessToken:`Zugriffstoken`,accessTokenHint:`Fügen Sie Ihr Bambu-Cloud-Zugriffstoken ein. Konten der Region China müssen diesen Weg nutzen (telefonnummerngebunden — kein E-Mail-Login). Im Wiki steht, wie Sie das Token aus den MakerWorld-Cookies auslesen.`,back:`Zurück`,loginButton:`Anmelden`,verifyButton:`Bestätigen`,setTokenButton:`Token setzen`,useToken:`Stattdessen Zugriffstoken verwenden`,useEmail:`Stattdessen mit E-Mail anmelden`,toast:{loggedIn:`Erfolgreich angemeldet`,codeSent:`Bestätigungscode an Ihre E-Mail gesendet`,enterTotp:`Geben Sie den Code aus Ihrer Authenticator-App ein`,tokenSet:`Token erfolgreich gesetzt`}},presets:{myPreset:`Mein Profil (bearbeitbar)`,duplicate:`Duplizieren`,editable:`Bearbeitbar`,failedToLoadDetails:`Profil-Details konnten nicht geladen werden`,deleteConfirm:`Dieses Profil löschen?`,deleteWarning:`"{{name}}" wird dauerhaft aus Bambu Cloud gelöscht. Dies kann nicht rückgängig gemacht werden.`,noDuplicatePermission:`Sie haben keine Berechtigung zum Duplizieren von Profilen`,noEditPermission:`Sie haben keine Berechtigung zum Bearbeiten von Profilen`,noDeletePermission:`Sie haben keine Berechtigung zum Löschen von Profilen`,types:{filament:`Filament-Profil`,printer:`Drucker-Profil`,process:`Prozess-Profil`},toast:{deleted:`Profil gelöscht`,created:`Profil erstellt`,updated:`Profil aktualisiert`,duplicated:`Profil dupliziert`,fieldAdded:`Feld "{{key}}" hinzugefügt`,exported:`Profil exportiert`},baseLabel:`Basis: {{name}}`,currentLabel:`Aktuell: {{name}}`,newPreset:`Neues Profil`,editPreset:`Profil bearbeiten`,duplicatePreset:`Profil duplizieren`,createNewPreset:`Neues Profil erstellen`,customizeSettings:`Passen Sie die Einstellungen für Ihr neues Profil an`,compareWithBase:`Mit Basis-Profil vergleichen`,compare:`Vergleichen`,basePreset:`Basis-Profil`,selectBasePreset:`Basis-Profil auswählen...`,presetName:`Profilname`,myCustomPreset:`Mein eigenes Profil`,inheritsFrom:`Erbt von`,dropJsonToImport:`JSON zum Importieren ablegen`,tabs:{common:`Allgemein`,allFields:`Alle Felder`},availableFields:`Verfügbare Felder`,searchFieldsPlaceholder:`Felder suchen...`,noMatchingFields:`Keine passenden Felder`,allFieldsAdded:`Alle Felder hinzugefügt`,addCustomField:`Eigenes Feld hinzufügen`,yourOverrides:`Ihre Überschreibungen`,noOverridesYet:`Noch keine Überschreibungen`,clickFieldsToAdd:`Klicken Sie links auf Felder, um sie hinzuzufügen`,saveAsTemplate:`Als Vorlage speichern`,jsonTip:`Tipp: Ziehen Sie eine .json-Datei auf dieses Fenster, um Einstellungen zu importieren`},cloudView:{searchPlaceholder:`Profile suchen...`,templates:`Vorlagen`,refresh:`Aktualisieren`,newPreset:`Neues Profil`,clearFilters:`Filter zurücksetzen`,compareMode:`Vergleichsmodus`,selectAnotherPreset:`Wählen Sie ein weiteres {{type}}-Profil`,clickTwoPresets:`Klicken Sie auf zwei Profile des gleichen Typs zum Vergleichen`,selectFirst:`1. Erstes auswählen`,selectSecond:`2. Zweites auswählen`,compareNow:`Jetzt vergleichen`,lastSynced:`Zuletzt synchronisiert:`,showingCount:`{{showing}} von {{total}} Profilen`,noPresetsFound:`Keine Profile gefunden`,columns:{filament:`Filament`,process:`Prozess`,printer:`Drucker`},noFilamentPresets:`Keine Filament-Profile`,noProcessPresets:`Keine Prozess-Profile`,noPrinterPresets:`Keine Drucker-Profile`,filters:{type:`Typ`,owner:`Besitzer`,printer:`Drucker`,nozzle:`Düse`,filament:`Filament`,layer:`Schicht`,all:`Alle`,myPresets:`Meine Profile`,builtIn:`Voreingestellt`,process:`Prozess`},noTemplatesPermission:`Sie haben keine Berechtigung, Vorlagen zu verwalten`,noRefreshPermission:`Sie haben keine Berechtigung, Profile zu aktualisieren`,noCreatePermission:`Sie haben keine Berechtigung, Profile zu erstellen`},templates:{title:`Schnellvorlagen`,noTemplates:`Noch keine Vorlagen`,createFirst:`Erstellen Sie Vorlagen aus dem Preset-Editor`,typeFilter:`Typ:`,deleteTitle:`Vorlage löschen`,deleteWarning:`Diese Aktion kann nicht rückgängig gemacht werden`,deleteConfirm:`Möchten Sie "{{name}}" wirklich löschen?`,namePlaceholder:`Vorlagenname`,descriptionPlaceholder:`Beschreibung`,settingsJson:`Einstellungen (JSON)`,fieldsCount:`{{count}} Felder`,shownInModals:`In Dialogen angezeigt`,hiddenInModals:`In Dialogen ausgeblendet`,apply:`Anwenden`,toast:{deleted:`Vorlage gelöscht`,updated:`Vorlage aktualisiert`,created:`Vorlage erstellt`,applied:`Vorlage angewendet`}}},support:{debugLoggingActive:`Debug-Protokollierung ist aktiv`,manageLogs:`Verwalten`,collectItem7:`Drucker-Verbindungsstatus und Firmware-Versionen`,collectItem8:`Integrationsstatus (Spoolman, MQTT, HA)`,collectItem9:`Netzwerkschnittstellen (nur Subnetze)`,collectItem10:`Python-Paketversionen`,collectItem11:`Datenbankzustandsprüfungen`,collectItem12:`Docker-Umgebungsdetails`,bundleGenerating:`Bundle wird erstellt...`,bundleStepConnection:`Drucker-Verbindungsprüfungen werden ausgeführt`,bundleStepVirtualPrinters:`Setup-Prüfungen für virtuelle Drucker werden ausgeführt`,bundleStepLogScan:`Aktuelle Protokolle werden auf bekannte Probleme überprüft`,bundleStepBuild:`Support-Bundle-ZIP wird erstellt`},fileManager:{title:`Dateimanager`,subtitle:`Organisieren und verwalten Sie Ihre Druckdateien`,uploadFiles:`Dateien hochladen`,newFolder:`Neuer Ordner`,folderName:`Ordnername`,folderNamePlaceholder:`z.B. Funktionsteile`,renameFile:`Datei umbenennen`,renameFolder:`Ordner umbenennen`,invalidFilenameChar:`Das Zeichen "{{char}}" ist in Druck-Dateinamen nicht erlaubt. Die SD-Karte des Druckers lehnt folgende Zeichen ab: < > : " / \\ | ? *`,moveFiles:`{{count}} Datei(en) verschieben`,rootNoFolder:`Stammverzeichnis (Kein Ordner)`,current:`aktuell`,linkFolder:`Ordner verknüpfen`,linkFolderDescription:`"{{name}}" mit einem Projekt oder Archiv verknüpfen für schnellen Zugriff.`,project:`Projekt`,archive:`Archiv`,noProjectsFound:`Keine Projekte gefunden`,noArchivesFound:`Keine Archive gefunden`,unlink:`Verknüpfung aufheben`,link:`Verknüpfen`,dragDropFiles:`Dateien hierher ziehen`,dropFilesHere:`Dateien hier ablegen`,releaseToUpload:`Loslassen zum Hochladen`,orClickToBrowse:`oder klicken zum Durchsuchen`,allFileTypesSupported:`Alle Dateitypen werden unterstützt. ZIP-Dateien werden extrahiert.`,zipFilesDetected:`ZIP-Dateien erkannt`,zipExtractOptions:`ZIP-Dateien werden extrahiert. Wählen Sie, wie die Ordnerstruktur behandelt werden soll:`,preserveZipStructure:`Ordnerstruktur aus ZIP beibehalten`,createFolderFromZip:`Ordner aus ZIP-Dateiname erstellen`,stlThumbnailGeneration:`STL-Vorschaubildgenerierung`,zipMayContainStl:`ZIP-Dateien können STL-Dateien enthalten. Vorschaubilder können während der Extraktion generiert werden.`,thumbnailsCanBeGenerated:`Vorschaubilder können für STL-Dateien generiert werden. Große Modelle benötigen möglicherweise mehr Zeit.`,generateThumbnailsForStl:`Vorschaubilder für STL-Dateien generieren`,threemfDetected:`3MF-Dateien erkannt`,threemfExtractionInfo:`Druckermodell, Material, Farbe und Druckeinstellungen werden automatisch aus 3MF-Dateien extrahiert.`,willBeExtracted:`Wird extrahiert`,filesExtracted:`{{count}} Dateien extrahiert`,uploadComplete:`Upload abgeschlossen: {{succeeded}} erfolgreich`,uploadFailed:`Hochladen fehlgeschlagen`,zipFilesFailed:`{{count}} Dateien fehlgeschlagen`,uploading:`Hochladen...`,changeLink:`Verknüpfung ändern...`,linkTo:`Verknüpfen mit...`,linkToProjectOrArchive:`Mit Projekt oder Archiv verknüpfen`,generateThumbnail:`Vorschaubild generieren`,generateThumbnails:`Vorschaubilder generieren`,generateThumbnailsForMissing:`Vorschaubilder für STL-Dateien ohne Vorschau generieren`,gridView:`Rasteransicht`,listView:`Listenansicht`,lowDiskSpaceWarning:`Warnung: Wenig Speicherplatz`,lowDiskSpaceDetails:`Nur {{free}} frei von {{total}} gesamt. Schwellenwert ist auf {{threshold}} GB eingestellt.`,files:`Dateien`,folders:`Ordner`,size:`Größe`,free:`Frei`,allFiles:`Alle Dateien`,allExternal:`Extern`,externalIsEmpty:`Keine externen Dateien`,externalEmptyDescription:`Dateien aus deinen verknüpften externen Ordnern erscheinen hier.`,wrap:`Umbrechen`,enableTextWrapping:`Textumbruch aktivieren`,disableTextWrapping:`Textumbruch deaktivieren`,collapse:`Einklappen`,collapseFoldersByDefault:`Ordner standardmäßig einklappen`,expandFoldersByDefault:`Ordner standardmäßig ausklappen`,folderSort:`Ordner sortieren`,folderSortByName:`Nach Name`,folderSortByActivity:`Nach letzter Aktivität`,dragToResizeTooltip:`Ziehen zum Ändern der Größe, Doppelklick zum Zurücksetzen`,searchFiles:`Dateien suchen...`,searchSubfoldersHint:`Inklusive Unterordner`,readme:{truncated:`Gekürzt`,show:`README anzeigen`,hide:`README ausblenden`,label:`README`},tags:{title:`Tags`,subtitle:`Dateien mit Labels versehen — Spielzeug, kindersicher, nur PETG, was immer du willst.`,manage:`Tags`,manageTitle:`Tag-Katalog verwalten`,add:`Neuer Tag`,edit:`Tag umbenennen`,name:`Name`,fileCount:`Dateien`,empty:`Noch keine Tags. Erstelle einen, um Dateien zu kennzeichnen.`,noMatches:`Keine passenden Tags.`,createPlaceholder:`z. B. Spielzeug, kindersicher, petg`,createButton:`Erstellen`,nameRequired:`Name ist erforderlich.`,searchPlaceholder:`Tags filtern...`,created:`Tag erstellt.`,updated:`Tag umbenannt.`,deleted:`Tag entfernt.`,saveFailed:`Tag konnte nicht gespeichert werden.`,deleteFailed:`Tag konnte nicht entfernt werden.`,applyFailed:`Tags konnten nicht angewendet werden.`,applyAdd:`Tags hinzufügen`,applyRemove:`Tags entfernen`,applyAddSuccess:`{{count}} Tag(s) zu {{files}} Datei(en) hinzugefügt.`,applyRemoveSuccess:`{{count}} Tag(s) von {{files}} Datei(en) entfernt.`,actionAdd:`Zu ausgewählten Dateien hinzufügen`,actionRemove:`Von ausgewählten Dateien entfernen`,tagAction:`Tag`,bulkTitle:`{{count}} ausgewählte Datei(en) taggen`,bulkTooltip:`Tags für alle ausgewählten Dateien hinzufügen oder entfernen.`,noPermission:`Du hast keine Berechtigung, Dateien zu taggen.`,filterLabel:`Filtern nach:`,clearAll:`Alle entfernen`,confirmDelete:`Tag "{{name}}" löschen?`,confirmDeleteMessage:`Entfernt den Tag aus dem Katalog. Dateien behalten ihre übrigen Tags.`,confirmDeleteInUseMessage:`Dieser Tag ist auf {{count}} Datei(en). Beim Löschen verschwindet er von allen; die Dateien selbst bleiben unverändert.`,editAria:`{{name}} bearbeiten`,deleteAria:`{{name}} löschen`},allTypes:`Alle Typen`,prints:`Drucke`,ascending:`Aufsteigend`,descending:`Absteigend`,showModified:`Änderungsdatum anzeigen`,hideModified:`Änderungsdatum ausblenden`,lastModified:`Zuletzt geändert`,lastActivity:`Letzte Aktivität`,resultsCount:`{{showing}} von {{total}} Dateien`,selectAll:`Alle auswählen`,deselectAll:`Auswahl aufheben`,selected:`{{count}} ausgewählt`,adding:`Hinzufügen...`,loadingFiles:`Dateien werden geladen...`,folderIsEmpty:`Ordner ist leer`,noFilesYet:`Noch keine Dateien`,folderEmptyDescription:`Laden Sie Dateien hoch oder verschieben Sie Dateien in diesen Ordner.`,noFilesDescription:`Laden Sie Dateien hoch, um Ihre Druckdateien zu organisieren.`,noMatchingFiles:`Keine passenden Dateien`,noMatchingFilesDescription:`Keine Dateien entsprechen Ihren aktuellen Such- oder Filterkriterien.`,clearFilters:`Filter zurücksetzen`,printedCount:`{{count}}x gedruckt`,uploadedBy:`Hochgeladen von`,deleteFolder:`Ordner löschen`,deleteFile:`Datei löschen`,deleteFilesCount:`{{count}} Dateien löschen`,deleteFolderConfirm:`Möchten Sie diesen Ordner wirklich löschen? Alle Dateien darin werden ebenfalls gelöscht.`,deleteFileConfirm:`Möchten Sie diese Datei wirklich löschen?`,deleteFilesConfirm:`Möchten Sie {{count}} ausgewählte Dateien wirklich löschen? Diese Aktion kann nicht rückgängig gemacht werden.`,deleting:`Wird gelöscht...`,noPermissionRenameFolder:`Sie haben keine Berechtigung, Ordner umzubenennen`,noPermissionLinkFolder:`Sie haben keine Berechtigung, Ordner zu verknüpfen`,noPermissionDeleteFolder:`Sie haben keine Berechtigung, Ordner zu löschen`,onlyEmptyFoldersDeletable:`Sie können nur leere Ordner löschen`,noPermissionPrint:`Sie haben keine Berechtigung zum Drucken`,noPermissionSlice:`Sie haben keine Berechtigung, Dateien zu slicen`,noPermissionAddToQueue:`Sie haben keine Berechtigung, zur Warteschlange hinzuzufügen`,noPermissionDownload:`Sie haben keine Berechtigung, Dateien herunterzuladen`,noPermissionRenameFile:`Sie haben keine Berechtigung, diese Datei umzubenennen`,noPermissionGenerateThumbnail:`Sie haben keine Berechtigung, Vorschaubilder zu generieren`,noPermissionDeleteFile:`Sie haben keine Berechtigung, diese Datei zu löschen`,noPermissionCreateFolder:`Sie haben keine Berechtigung, Ordner zu erstellen`,noPermissionUpload:`Sie haben keine Berechtigung, Dateien hochzuladen`,noPermissionMoveFiles:`Sie haben keine Berechtigung, Dateien zu verschieben`,noPermissionDeleteFiles:`Sie haben keine Berechtigung, Dateien zu löschen`,linkExternal:`Extern verknüpfen`,linkExternalFolder:`Externen Ordner verknüpfen`,linkExternalFolderDescription:`Ein Host-Verzeichnis (NAS, USB, Netzlaufwerk) in den Dateimanager einbinden. Dateien werden nicht kopiert — sie werden direkt vom Originalpfad gelesen.`,externalFolderNamePlaceholder:`z.B. NAS-Drucke`,externalPath:`Host-Pfad`,externalPathHelp:`Absoluter Pfad zum Verzeichnis auf dem Docker-Host. Muss als Bind-Mount in den Container eingebunden sein.`,readOnly:`Nur Lesen`,readOnlyHelp:`verhindert Uploads und Löschungen`,showHiddenFiles:`Versteckte Dateien anzeigen (Punkt-Dateien)`,externalFolder:`Externer Ordner`,scanFolder:`Scannen`,toast:{folderCreated:`Ordner erstellt`,folderDeleted:`Ordner gelöscht`,fileDeleted:`Datei gelöscht`,filesDeleted:`{{count}} Dateien gelöscht`,filesMoved:`Dateien verschoben`,folderLinked:`Ordner verknüpft`,folderUnlinked:`Ordnerverknüpfung aufgehoben`,externalFolderLinked:`Externer Ordner verknüpft und gescannt`,folderScanned:`Scan abgeschlossen: {{added}} hinzugefügt, {{removed}} entfernt`,addedToQueue:`{{count}} Datei(en) zur Warteschlange hinzugefügt`,addedToQueuePartial:`{{added}} Datei(en) hinzugefügt, {{failed}} fehlgeschlagen`,failedToAddToQueue:`Fehler beim Hinzufügen: {{error}}`,fileRenamed:`Datei umbenannt`,folderRenamed:`Ordner umbenannt`,thumbnailsGenerated:`{{count}} Vorschaubild(er) generiert`,thumbnailsGeneratedPartial:`{{succeeded}} Vorschaubild(er) generiert, {{failed}} fehlgeschlagen`,noStlMissingThumbnails:`Keine STL-Dateien ohne Vorschaubild`,failedToGenerateThumbnails:`Fehler beim Generieren der Vorschaubilder: {{error}}`,thumbnailGenerated:`Vorschaubild generiert`,failedToGenerateThumbnail:`Fehler beim Generieren des Vorschaubildes: {{error}}`}},projects:{title:`Projekte`,subtitle:`Organisieren und verfolgen Sie Ihre 3D-Druckprojekte`,newProject:`Neues Projekt`,editProject:`Projekt bearbeiten`,deleteProject:`Projekt löschen`,projectName:`Projektname`,description:`Beschreibung`,noProjects:`Noch keine Projekte`,noProjectsFiltered:`Keine {{status}} Projekte`,noProjectsFilteredHelp:`Sie haben keine {{status}} Projekte. Projekte werden hier angezeigt, wenn sich ihr Status ändert.`,createFirst:`Erstellen Sie Ihr erstes Projekt, um verwandte Drucke zu organisieren, den Fortschritt zu verfolgen und Ihre Builds zu verwalten.`,createFirstButton:`Erstes Projekt erstellen`,create:`Erstellen`,files:`Dateien`,prints:`Drucke`,plates:`Platten`,parts:`Teile`,lastModified:`Zuletzt geändert`,deleteConfirm:`Möchten Sie dieses Projekt wirklich löschen? Archive und Warteschlangenelemente werden getrennt, aber nicht gelöscht.`,addFiles:`Dateien hinzufügen`,removeFile:`Datei entfernen`,viewDetails:`Details anzeigen`,namePlaceholder:`z.B. Voron 2.4 Build`,descriptionPlaceholder:`Optionale Beschreibung...`,urlLabel:`URL`,urlPlaceholder:`https://makerworld.com/...`,urlInvalid:`URL muss mit http:// oder https:// beginnen`,openExternalUrl:`Projekt-URL öffnen`,coverImageLabel:`Titelbild`,coverImageAlt:`Projekt-Titelbild`,coverImageUpload:`Hochladen`,coverImageReplace:`Ersetzen`,coverImageRemove:`Entfernen`,color:`Farbe`,targetPlates:`Ziel-Platten`,targetPlatesPlaceholder:`z.B. 25`,targetPlatesHelp:`Anzahl der Druckaufträge`,targetParts:`Ziel-Teile`,targetPartsPlaceholder:`z.B. 150`,targetPartsHelp:`Benötigte Objekte insgesamt`,targetSets:`Kopien pro Datei`,targetSetsPlaceholder:`z. B. 10`,targetSetsHelp:`Wie oft jede druckbare Datei gedruckt werden soll`,tagsLabel:`Tags (kommagetrennt)`,tagsPlaceholder:`z.B. voron, funktional, geschenk`,dueDate:`Fälligkeitsdatum`,priority:`Priorität`,priorityLow:`Niedrig`,priorityNormal:`Normal`,priorityHigh:`Hoch`,priorityUrgent:`Dringend`,statusActive:`Aktiv`,statusCompleted:`Abgeschlossen`,statusArchived:`Archiviert`,done:`Fertig`,completed:`abgeschlossen`,failed:`fehlgeschlagen`,inQueue:`in Warteschlange`,noPrintsYet:`Noch keine Drucke`,printJobs:`Druckaufträge (Platten)`,partsPrinted:`Gedruckte Teile`,failedParts:`Fehlgeschlagene Teile`,import:`Importieren`,export:`Exportieren`,importProject:`Projekt importieren`,exportAll:`Alle Projekte exportieren`,loading:`Projekte werden geladen...`,noEditPermission:`Sie haben keine Berechtigung, Projekte zu bearbeiten`,noDeletePermission:`Sie haben keine Berechtigung, Projekte zu löschen`,noCreatePermission:`Sie haben keine Berechtigung, Projekte zu erstellen`,noImportPermission:`Sie haben keine Berechtigung, Projekte zu importieren`,noExportPermission:`Sie haben keine Berechtigung, Projekte zu exportieren`,toast:{created:`Projekt erstellt`,updated:`Projekt aktualisiert`,deleted:`Projekt gelöscht`,imported:`Projekt importiert`,multipleImported:`{{count}} Projekte importiert`,importFailed:`Import fehlgeschlagen`,exported:`Projekte exportiert (nur Metadaten)`}},projectDetail:{notFound:`Projekt nicht gefunden`,backToProjects:`Zurück zu Projekten`,export:`Exportieren`,exportProject:`Projekt exportieren`,noExportPermission:`Sie haben keine Berechtigung, Projekte zu exportieren`,noEditPermission:`Sie haben keine Berechtigung, Projekte zu bearbeiten`,partOf:`Teil von:`,priorityLabel:`Priorität:`,noPrints:`Noch keine Drucke in diesem Projekt`,status:{active:`Aktiv`,completed:`Abgeschlossen`,archived:`Archiviert`},priority:{low:`Niedrig`,normal:`Normal`,high:`Hoch`,urgent:`Dringend`},dueDate:{overdue:`Überfällig`,today:`Heute fällig`,daysLeft:`{{count}} Tage übrig`},progress:{platesProgress:`Platten-Fortschritt`,partsProgress:`Teile-Fortschritt`,setsProgress:`Vollständige Sätze`,sets:`Sätze`,setsHint:`Ein Satz ist vollständig, wenn jede druckbare Datei diese Anzahl erreicht hat`,printJobs:`Druckaufträge`,parts:`Teile`,percentComplete:`{{percent}}% abgeschlossen`,remaining:`{{count}} verbleibend`},stats:{printJobs:`Druckaufträge`,total:`gesamt`,failed:`{{count}} fehlgeschlagen`,partsPrinted:`{{count}} Teile gedruckt`,printTime:`Druckzeit`,filamentUsed:`Filament verbraucht`},cost:{title:`Kostenverfolgung`,filamentCost:`Filamentkosten`,energy:`Energie`,totalCost:`Gesamtkosten`,total:`Gesamt`,includesBom:`inkl. Stückliste`,budget:`Budget`,remaining:`Verbleibend`},subProjects:{title:`Unterprojekte ({{count}})`},notes:{title:`Notizen`,noEditPermission:`Sie haben keine Berechtigung, Notizen zu bearbeiten`,placeholder:`Notizen zu diesem Projekt hinzufügen...`,empty:`Noch keine Notizen. Klicken Sie auf Bearbeiten, um Notizen hinzuzufügen.`},files:{title:`Dateien`,linkFolders:`Ordner aus dem Dateimanager verknüpfen`,forQuickAccess:`für schnellen Zugriff auf dieses Projekt.`,fileCount:`{{count}} Datei(en)`,empty:`Keine Ordner verknüpft. Gehen Sie zum Dateimanager und verknüpfen Sie einen Ordner mit diesem Projekt.`,printedCount:`{{count}}-mal gedruckt`,progressTooltip:`{{done}} von {{target}} abgeschlossenen Drucken`,noFiles:`Keine Dateien in diesem Ordner.`},bom:{title:`Stückliste`,acquired:`{{completed}}/{{total}} beschafft`,showAll:`Alle anzeigen`,hideDone:`Erledigte ausblenden`,addPart:`Teil hinzufügen`,noAddPermission:`Sie haben keine Berechtigung, Teile hinzuzufügen`,partNamePlaceholder:`Teilename (z.B. M3x8 Schrauben)`,partName:`Teilename`,qty:`Menge`,price:`Preis ({{currency}})`,sourcingUrlPlaceholder:`Bezugsquelle-URL (optional)`,remarksPlaceholder:`Bemerkungen (optional)`,deletePart:`Teil löschen`,deleteConfirm:`Möchten Sie "{{name}}" wirklich löschen?`,noUpdatePermission:`Sie haben keine Berechtigung, Teile zu aktualisieren`,noEditPermission:`Sie haben keine Berechtigung, Teile zu bearbeiten`,noDeletePermission:`Sie haben keine Berechtigung, Teile zu löschen`,totalCost:`Gesamtkosten:`,empty:`Keine Teile in der Stückliste. Fügen Sie Hardware, Elektronik oder andere Komponenten hinzu, um zu verfolgen, was beschafft werden muss.`},timeline:{title:`Aktivitätsverlauf`,empty:`Noch keine Aktivität.`},template:{saveAsTemplate:`Als Vorlage speichern`,noCreatePermission:`Sie haben keine Berechtigung, Vorlagen zu erstellen`},queue:{title:`Warteschlange`,viewAll:`Alle anzeigen`,printing:`{{count}} druckend`,queued:`{{count}} in Warteschlange`},prints:{title:`Drucke ({{count}})`},toast:{projectUpdated:`Projekt aktualisiert`,partAdded:`Teil hinzugefügt`,partRemoved:`Teil entfernt`,exportFailed:`Export fehlgeschlagen`,projectExported:`Projekt exportiert`,templateCreated:`Vorlage erstellt`}},system:{title:`Systeminformationen`,version:`Version`,uptime:`Laufzeit`,cpuUsage:`CPU-Auslastung`,memoryUsage:`Speicherauslastung`,diskUsage:`Festplattenauslastung`,networkInfo:`Netzwerkinformationen`,logs:`Protokolle`,debugMode:`Debug-Modus`,enableDebug:`Debug-Protokollierung aktivieren`,disableDebug:`Debug-Protokollierung deaktivieren`,downloadLogs:`Protokolle herunterladen`,clearLogs:`Protokolle löschen`,dockerInfo:`Docker-Info`,containerName:`Container-Name`,imageName:`Image-Name`,platform:`Plattform`,architecture:`Architektur`},sponsors:{sectionTitle:`Unabhängig & von der Community finanziert`,tagline:`Bambuddy ist kostenlos und bleibt es, weil Menschen es freiwillig unterstützen. Kein VC, kein Cloud-Zwang.`,viewSupporters:`Unterstützer ansehen`,toastPrints:`Du hast {{count}} Drucke mit Bambuddy abgeschlossen. Bambuddy bleibt kostenlos dank seiner Unterstützer.`,toastCost:`Du hast {{total}} an Filament mit Bambuddy verfolgt. Sieh dir an, wer das Projekt unabhängig hält.`,toastArchives:`{{count}} Drucke mit Bambuddy archiviert. Sieh dir an, wer es unabhängig hält.`,toastAnniversary:`Ein Jahr mit Bambuddy! Sieh dir an, wer das Projekt unabhängig hält.`,toastVersionUpdate:`Aktualisiert auf v{{version}}. Bambuddy bleibt kostenlos dank seiner Unterstützer.`,toastBusiness:`Sie betreiben Bambuddy auf {{count}} Druckern. Für Teams gibt es Support-Pakete – bevorzugte Fehlerbehebung, Rechnungsstellung und einen direkten Draht zum Maintainer.`,businessCta:`Bambuddy für Unternehmen`,businessTitle:`Bambuddy für Unternehmen`,businessTagline:`Sie betreiben {{count}} Drucker. Für Teams und Druckfarmen gibt es priorisierten Support, kommerzielle Lizenzen und Rechnungsstellung.`},library:{title:`Filament-Bibliothek`,addFilament:`Filament hinzufügen`,editFilament:`Filament bearbeiten`,deleteFilament:`Filament löschen`,vendor:`Hersteller`,material:`Material`,color:`Farbe`,kFactor:`K-Faktor`,temperature:`Temperatur`,noFilaments:`Keine Filamente in der Bibliothek`,deleteConfirm:`Möchten Sie dieses Filament wirklich löschen?`,importFromPrinter:`Vom Drucker importieren`,exportToFile:`In Datei exportieren`,runWithPipeline:{actionLabel:`Mit Pipeline ausführen`,noPermission:`Du hast keine Berechtigung, Pipelines auszuführen`,modalTitle:`Mit Pipeline ausführen`,confirmTitle:`Lauf bestätigen`,confirmIntro:`Pre-Flight hat Probleme mit diesem Lauf gefunden`,sourceHint:`Quelle`,pipelineHint:`Pipeline`,targetHint:`Ziel`,pipelineListAria:`Verfügbare Pipelines`,runAnyway:`Trotzdem ausführen`,loading:`Wird geladen…`,empty:`Noch keine Pipelines gespeichert. Öffne den Slice-Dialog und klicke „Als Pipeline speichern“, um eine zu erstellen.`,noTarget:`Kein Zieldrucker festgelegt`,noTargetMessage:`Diese Pipeline hat keinen Zieldrucker. Öffne sie in den Einstellungen, um einen festzulegen.`,copies:`Kopien`,copiesHint:`max. {{n}}`,classTarget:`Beliebiger {{model}}`,toast:{started:`Pipeline-Lauf gestartet`,failed:`Lauf konnte nicht gestartet werden`},issue:{printerNotSet:`Kein Zieldrucker für diese Pipeline festgelegt.`,printerNotFound:`Zieldrucker existiert nicht mehr.`,printerDisabled:`Zieldrucker ist deaktiviert.`,printerOffline:`Zieldrucker ist offline.`,filamentType:`Filament-Slot {{slot}}: erwartet {{expected}}, AMS hat {{actual}}`,filamentColor:`Filament-Slot {{slot}}: Farbe weicht ab (erwartet {{expected}}, AMS hat {{actual}})`,amsSlotMissing:`AMS-Slot {{slot}} ist auf diesem Drucker nicht verfügbar`,filamentUnverified:`Filament-Slot {{slot}} stammt aus einem Cloud-/Standard-Preset und konnte nicht statisch verifiziert werden.`,noClassMatches:`Keine Drucker in dieser Installation entsprechen der Zielmodellklasse der Pipeline ({{expected}}).`,classNotSet:`Pipeline-Ziel ist auf eine Druckerklasse gesetzt, aber kein Modell wurde gewählt.`}}},slice:{title:`Modell slicen`,action:`Slicen`,actionAll:`Alle {{count}} Plates slicen`,actionAllTitle:`Alle Plates in eine einzelne Multi-Plate-Ausgabe slicen (ein Archiv). Die Filamentauswahl gilt für jeden Slot des Projekts.`,allPlatesToggle:`Alle {{count}} Plates slicen`,slicing:`Slicen…`,printer:`Drucker-Profil`,process:`Prozess-Profil`,filament:`Filament-Profil`,filamentSlot:`Filament {{index}} – {{type}}`,selectPreset:`— Profil auswählen —`,loadingPresets:`Profile werden geladen…`,analyzingPlateFilaments:`Plattenfilamente werden analysiert…`,analyzingPlateFilamentsHint:`Es wird ein Probeschnitt ausgeführt, um die belegten AMS-Slots dieser Platte zu ermitteln. Wird zwischengespeichert — erneutes Öffnen ist sofort.`,previewToast:`{{name}} wird analysiert — {{elapsed}}`,previewWithProgress:`{{name}} wird analysiert — {{stage}} ({{percent}}%) — {{elapsed}}`,notUsedByPlate:`— wird von dieser Platte nicht verwendet`,noPresetsForSlot:`Keine Profile verfügbar`,otherPrinters:`Andere Drucker`,presetsLoadFailed:`Profile konnten nicht geladen werden. Importiere sie zuerst unter Einstellungen → Profile.`,refreshPresets:`Aktualisieren`,refreshPresetsTitle:`Profile neu laden — die aktuellen Cloud- und Bundle-Listen abrufen (nach dem Löschen eines Profils in Bambu Studio oder Bambu Handy verwenden)`,allPresetsRequired:`Alle Profile müssen ausgewählt sein`,useEmbedded:`Eingebettete Einstellungen der Datei verwenden`,useEmbeddedHint:`So slicen, wie der Ersteller es angelegt hat (Wände, Füllung, Filament), statt mit den obigen Profilen. Verfügbar, weil dein Drucker zur Datei passt.`,designSettings:`Einstellungen des Erstellers behalten`,designSettingsHint:`Diese Datei ändert {{count}} Druckeinstellung(en) gegenüber dem Standardprofil.`,designSettingsSelected:`{{selected}} von {{total}} ausgewählt`,designSettingsPrinterCoupled:`druckerspezifisch`,designSettingsPrinterCoupledHint:`Auf den Drucker abgestimmt, für den die Datei erstellt wurde — auf deinem kann der Wert falsch oder unzulässig sein.`,enqueuing:`Slice-Auftrag wird übermittelt…`,queued:`In Warteschlange…`,failed:`Slicen fehlgeschlagen. Logs des Slicer-Sidecars prüfen.`,startedToast:`{{name}} wird im Hintergrund gesliced…`,queuedToast:`Warteschlange: {{name}} — {{elapsed}}`,runningToast:`{{name}} wird gesliced — {{elapsed}}`,runningWithProgress:`{{name}} – {{stage}} ({{percent}} %) – {{elapsed}}`,runningWithProgressMultiPlate:`Plate {{plateIndex}} von {{plateCount}} • {{name}} – {{stage}} ({{percent}} %) – {{elapsed}}`,completedToast:`{{name}} wurde gesliced`,failedTitle:`Slicen fehlgeschlagen`,failedToast:`Slicen von {{name}} fehlgeschlagen: {{detail}}`,tier:{local:`Importiert`,cloud:`Bambu Cloud`,orcaCloud:`Orca Cloud`,standard:`Standard`},cloud:{notAuthenticated:`In Bambu Cloud anmelden (Einstellungen → Profile → Bambu Cloud), um deine Cloud-Profile zu sehen.`,expired:`Bambu-Cloud-Sitzung abgelaufen — erneut anmelden, um die Cloud-Profile zu aktualisieren.`,unreachable:`Bambu Cloud ist gerade nicht erreichbar. Lokale und Standard-Profile funktionieren weiterhin.`},orcaCloud:{notAuthenticated:`Bei Orca Cloud anmelden (Profile → Orca Cloud), um Ihre Orca-Profile zu sehen.`,expired:`Orca Cloud-Sitzung abgelaufen — erneut anmelden, um die Orca-Profile zu aktualisieren.`,unreachable:`Orca Cloud ist derzeit nicht erreichbar. Andere Profile funktionieren weiterhin.`},bedType:{label:`Druckbett`,auto:`Auto (aus Prozess-Profil)`,coolPlate:`Cool Plate`,coolPlateSuperTack:`Cool Plate SuperTack`,engineering:`Engineering Plate`,highTemp:`High Temp Plate`,texturedPEI:`Textured PEI Plate`,smoothPEI:`Smooth PEI Plate`},pipelines:{label:`Pipeline`,applyAria:`Pipeline anwenden`,applyPrompt:`Pipeline anwenden…`,empty:`Keine gespeicherten Pipelines`,saveButton:`Als Pipeline speichern`,saveTitle:`Aktuelle Auswahl aller vier Slots als wiederverwendbare Pipeline speichern`,namePlaceholder:`Pipeline-Name`,nameAria:`Neuer Pipeline-Name`,toast:{applied:`„{{name}}“ angewendet`,saved:`Pipeline gespeichert`,saveFailed:`Speichern fehlgeschlagen`}}},spoolman:{title:`Spoolman-Integration`,enabled:`Spoolman aktiviert`,url:`Spoolman URL`,connected:`Verbunden`,disconnected:`Nicht verbunden`,testConnection:`Verbindung testen`,sync:`Synchronisieren`,syncing:`Synchronisiert...`,lastSync:`Letzte Synchronisierung`,linkToSpoolman:`Mit Spoolman verknüpfen`,openInSpoolman:`In Spoolman öffnen`,unlinkSpool:`Spule trennen`,unlinkConfirmTitle:`Spule entfernen?`,unlinkConfirmMessage:`Die Spule wird vom Slot entfernt. Die Spulendaten selbst bleiben unverändert.`,selectSpool:`Spule auswählen`,noUnlinkedSpools:`Keine nicht zugewiesenen Spulen verfügbar`,linkSuccess:`Spule erfolgreich zugewiesen`,linkFailed:`Spule konnte nicht zugewiesen werden`,unlinkSuccess:`Spule erfolgreich entfernt`,unlinkFailed:`Spule konnte nicht entfernt werden`,linkedSpool:`Zugewiesene Spule`,spoolId:`Spulen-ID`,fillSourceLabel:`(Spoolman)`,weight:`Gewicht`,remaining:`Verbleibend`,disableWeightSync:`AMS-Gewichtsschätzung deaktivieren`,disableWeightSyncDesc:`Verbleibende Kapazität nicht aus AMS-Schätzungen aktualisieren. Verwenden Sie dies, wenn Sie die Verbrauchserfassung von Spoolman gegenüber den prozentualen AMS-Schätzungen bevorzugen. Neue Spulen verwenden weiterhin die AMS-Schätzung als Anfangsgewicht.`,reportPartialUsage:`Teilverbrauch bei fehlgeschlagenen Drucken melden`,reportPartialUsageDesc:`Wenn ein Druck fehlschlägt oder abgebrochen wird, den geschätzten Filamentverbrauch bis zu diesem Zeitpunkt basierend auf dem Schichtfortschritt melden.`},locations:{title:`Lagerorte`,subtitle:`Regale, Schubladen und andere physische Lagerplätze für Spulen verwalten`,add:`Lagerort hinzufügen`,addShort:`Hinzufügen`,edit:`Lagerort bearbeiten`,name:`Name`,spools:`Spulen`,empty:`Noch keine Lagerorte. Erstellen Sie Ihr erstes Regal oder Ihre erste Schublade.`,manage:`Lagerorte`,createPlaceholder:`z. B. Regal A, Schublade 1`,nameRequired:`Name des Lagerorts ist erforderlich`,created:`Lagerort erstellt`,updated:`Lagerort aktualisiert`,deleted:`Lagerort gelöscht`,saveFailed:`Lagerort konnte nicht gespeichert werden`,deleteFailed:`Lagerort konnte nicht gelöscht werden`,deleteBlocked:`Entfernen Sie zuerst alle Spulen von diesem Lagerort`,confirmDelete:`„{{name}}“ löschen?`,confirmDeleteMessage:`Dieser Lagerort wird aus dem Katalog entfernt. Spulen müssen zuerst verschoben werden.`},inventory:{title:`Spulen-Inventar`,subtitle:`Verwalten Sie Ihre Spulen`,addToInventory:`Zum Inventar hinzufügen`,addToInventoryPending:`Wird hinzugefügt...`,addToInventorySuccess:`Spule zum Inventar hinzugefügt`,addToInventoryFailed:`Spule konnte nicht zum Inventar hinzugefügt werden`,unknownSpoolTitle:`Neues Filament erkannt`,unknownSpoolMessage:`An {{location}} wurde eine Spule mit unbekanntem RFID-Tag erkannt. Jetzt zum Inventar hinzufügen?`,unknownSpoolSlot:`Slot`,bulk:{selectAllVisible:`Alle sichtbaren auswählen`,selectRow:`Zeile auswählen`,selectGroup:`Gruppe auswählen`,selectionCount:`{{count}} ausgewählt`,edit:`Bearbeiten`,printLabels:`Etiketten drucken`,resetUsage:`Verbrauch zurücksetzen`,restore:`Wiederherstellen`,archive:`Archivieren`,delete:`Löschen`,clearSelection:`Auswahl aufheben`,editTitle:`Spulen sammelbearbeiten`,editSubtitle:`Wird auf {{count}} ausgewählte Spulen angewendet. Nur angekreuzte Felder werden aktualisiert.`,editHint:`In ein Feld tippen markiert es für die Aktualisierung — nur angekreuzte Zeilen werden gesendet. Leere Felder bleiben unverändert (Felder leeren geht nur pro Spule).`,useCustom:`„{{value}}" verwenden`,toggleField:`Aktualisierung für dieses Feld umschalten`,changeCount:`{{count}} Felder werden aktualisiert.`,applyPending:`Wird angewendet...`,applyButton:`Auf {{count}} Spulen anwenden`,deleteTitle:`Ausgewählte Spulen löschen`,archiveTitle:`Ausgewählte Spulen archivieren`,restoreTitle:`Ausgewählte Spulen wiederherstellen`,resetUsageTitle:`Verbrauch ausgewählter Spulen zurücksetzen`,deleteMessage:`{{count}} Spulen dauerhaft löschen? Dies kann nicht rückgängig gemacht werden.`,archiveMessage:`{{count}} Spulen archivieren? Sie können später wiederhergestellt werden.`,restoreMessage:`{{count}} archivierte Spulen wiederherstellen?`,resetUsageMessage:`Den "Gesamtverbrauch"-Zähler auf {{count}} Spulen zurücksetzen? Die verbleibende Menge bleibt erhalten.`,updateSuccess:`{{count}} Spulen aktualisiert`,updateFailed:`Sammelaktualisierung fehlgeschlagen`,updatePartial:`{{ok}} Spulen aktualisiert, {{failed}} fehlgeschlagen`,updateAllFailed:`Alle {{count}} Aktualisierungen fehlgeschlagen — Auswahl bleibt erhalten zum erneuten Versuch`,deleteSuccess:`{{count}} Spulen gelöscht`,deleteFailed:`Sammellöschung fehlgeschlagen`,deletePartial:`{{ok}} Spulen gelöscht, {{failed}} fehlgeschlagen`,deleteAllFailed:`Alle {{count}} Löschungen fehlgeschlagen — Auswahl bleibt erhalten zum erneuten Versuch`,archiveSuccess:`{{count}} Spulen archiviert`,archiveFailed:`Sammelarchivierung fehlgeschlagen`,archivePartial:`{{ok}} Spulen archiviert, {{failed}} fehlgeschlagen`,archiveAllFailed:`Alle {{count}} Archivierungen fehlgeschlagen — Auswahl bleibt erhalten zum erneuten Versuch`,restoreSuccess:`{{count}} Spulen wiederhergestellt`,restoreFailed:`Sammelwiederherstellung fehlgeschlagen`,restorePartial:`{{ok}} Spulen wiederhergestellt, {{failed}} fehlgeschlagen`,restoreAllFailed:`Alle {{count}} Wiederherstellungen fehlgeschlagen — Auswahl bleibt erhalten zum erneuten Versuch`,invalidHex:`6 Hex-Zeichen (RRGGBB) oder 8 (RRGGBBAA) eingeben. Anderenfalls wird das Feld nicht übernommen.`},spoolmanMixedContentTitle:`Spoolman lässt sich nicht über HTTPS laden — Browser blockiert gemischte Inhalte`,spoolmanMixedContentBody:`Bambuddy wird über HTTPS ausgeliefert (über deinen Reverse-Proxy), aber deine Spoolman-URL ist nach wie vor HTTP. Browser blockieren gemischte Inhalte aus Sicherheitsgründen, daher kann die eingebettete Spoolman-Oberfläche nicht geladen werden. Spoolman muss ebenfalls über HTTPS erreichbar sein.`,spoolmanMixedContentFixReverseProxy:`Stelle Spoolman hinter denselben Reverse-Proxy wie Bambuddy (Traefik / Nginx / Caddy) mit HTTPS und aktualisiere die Spoolman-URL in den Einstellungen auf die neue HTTPS-Adresse.`,spoolmanMixedContentFixOpenNewTab:`Als Workaround kannst du Spoolman in einem neuen Tab über HTTP öffnen — gemischte Inhalte werden nur innerhalb eingebetteter Frames blockiert, ein eigener Tab funktioniert weiterhin.`,spoolmanOpenInNewTab:`Spoolman in neuem Tab öffnen`,labels:{title:`Spulen-Etiketten drucken`,selectedCount:`{{count}} ausgewählt`,pickSpools:`Wählen Sie, für welche Spulen Etiketten gedruckt werden sollen:`,monochrome:`Monochrom (Schwarz-Weiß-Drucker)`,monochromeHint:`Entfernt das Farbfeld und verbreitert den Text`,searchPlaceholder:`Name, Marke oder #ID suchen`,filterByMaterial:`Material:`,allMaterials:`Alle`,selectVisible:`Alle sichtbaren auswählen ({{count}})`,deselectVisible:`Sichtbare abwählen`,clearAll:`Alle entfernen`,noSpoolsToShow:`Keine Spulen anzuzeigen. Filter anpassen und erneut versuchen.`,noMatches:`Keine Spulen entsprechen der aktuellen Suche oder dem Filter.`,printOne:`Etikett für diese Spule drucken`,printLabels:`Etiketten drucken…`,bulkTitle:`Spulen aus den aktuell angezeigten {{count}} zum Etikettieren auswählen`,noSpoolsTitle:`Keine Spulen zum Etikettieren`,error:`Etiketten konnten nicht erstellt werden: {{msg}}`,sortBy:{label:`Sortieren:`,id:`Nach ID`,color:`Nach Farbe`},templates:{amsHolderSmall:{label:`AMS-Halter — klein (74 × 33 mm)`,hint:`Ein Etikett pro Seite; passt zum druckbaren Etikett aus dem MakerWorld-Modell 752566 (AMS-Filament-Etikettenhalter).`},amsHolderLarge:{label:`AMS-Halter — groß (75 × 55 mm)`,hint:`Ein Etikett pro Seite; passt zur Kartoneinleger-Variante des AMS-Filament-Etikettenhalters. Genug Platz für Farbprobe, Marke, Material, ID und QR-Code.`},box40x30:{label:`Boxetikett (40 × 30 mm)`,hint:`Ein Etikett pro Seite; gängige DK/Brother-Rollengröße, ideal für Filament-Beutel und Lager-Etiketten.`},box:{label:`Box label (62 × 29 mm)`,hint:`Ein Etikett pro Seite; für Brother PT/QL und Dymo-Kleinetiketten dimensioniert.`},averyL7160:{label:`Avery L7160 — A4 sheet (38.1 × 63.5 mm × 21)`,hint:`EU-Bogenformat; 21 Etiketten pro A4-Seite.`},avery5160:{label:`Avery 5160 — US Letter sheet (25.4 × 66.7 mm × 30)`,hint:`US-Bogenformat; 30 Etiketten pro Letter-Seite.`}}},csv:{importButton:`CSV importieren`,exportButton:`CSV exportieren`,modalTitle:`Spulen aus CSV importieren`,selectFile:`CSV-Datei auswählen oder hierher ziehen`,dragHint:`Kopfzeile: material (erforderlich), brand, subtype, color_name, rgba, …`,parsing:`Datei wird gelesen…`,previewError:`CSV-Datei konnte nicht gelesen werden`,validCount:`{{count}} gültig`,errorCount:`{{count}} Fehler`,skippedCount:`{{count}} übersprungen`,colRow:`Zeile`,colStatus:`Status`,colColor:`Farbe`,colorResolved:`Farbe aus Katalog übernommen`,colorCrossMaterial:`Farbe von einem anderen Material übernommen — keine exakte Übereinstimmung im Katalog`,duplicateExisting:`Eine Spule mit diesem Material, dieser Marke und Farbe existiert bereits — sie wird trotzdem als neue Spule importiert`,spoolmanHint:`Im Spoolman-Modus den integrierten CSV-Import/-Export von Spoolman verwenden.`,importValidRows:`{{count}} gültige Zeilen importieren`,noValidRows:`Keine gültigen Zeilen`,importing:`Wird importiert…`,importSuccess:`{{count}} Spulen importiert`,importError:`Import fehlgeschlagen`,exportError:`Export fehlgeschlagen`},addSpool:`Spule hinzufügen`,copySpool:`Spule kopieren`,editSpool:`Spule bearbeiten`,material:`Material`,selectMaterial:`Material auswählen...`,subtype:`Untertyp`,brand:`Marke`,searchBrand:`Marke suchen...`,useCustomBrand:`"{{brand}}" verwenden`,useCustomMaterial:`Benutzerdefiniertes Material verwenden: {{material}}`,suggestedOptions:`Vorgeschlagen`,allOptions:`Alle`,colorName:`Farbname`,colorNamePlaceholder:`Jadeweiß, Feuerrot...`,color:`Farbe`,hexColor:`Hex-Farbe`,pickColor:`Benutzerdefinierte Farbe wählen`,labelWeight:`Nenngewicht`,coreWeight:`Leergewicht der Spule`,searchSpoolWeight:`Spulengewicht suchen...`,weightUsed:`Verbraucht`,currentWeight:`Restgewicht`,measuredWeight:`Gemessenes Gewicht`,spoolName:`Spule`,costPerKg:`Kosten pro kg`,storageLocation:`Lagerstandort`,storageLocationPlaceholder:`z.B. Regal A, Schublade 1`,openInInventory:`Im Inventar öffnen`,measuredWeightError:`Das gemessene Gewicht muss zwischen {{min}}g und {{max}}g liegen.`,slicerFilament:`Slicer-Filament`,slicerFilamentName:`Slicer-Preset-Name`,slicerPreset:`Slicer-Preset`,searchPresets:`Filament-Presets suchen...`,selectedPreset:`Ausgewählt`,noPresetsFound:`Keine Presets gefunden`,tempOverrides:`Temperatur-Überschreibungen`,note:`Notiz`,notePlaceholder:`Zusätzliche Notizen zu dieser Spule...`,category:`Kategorie`,categoryPlaceholder:`z. B. Produktion, Prototyp, Kunde A`,categoryNone:`Ohne Kategorie`,storageLocationNone:`Kein Lagerort`,lowStockThresholdOverride:`Niedrigbestandsschwelle (diese Spule)`,lowStockThresholdOverrideHelp:`Leer lassen, um den globalen Schwellenwert ({{global}}%) zu verwenden.`,clearRfid:`RFID-Tag löschen`,rfidCleared:`RFID-Tag gelöscht`,archive:`Archivieren`,restore:`Wiederherstellen`,noSpools:`Noch keine Spulen. Fügen Sie Ihre erste Spule hinzu.`,noAvailableSpools:`Keine Spulen verfügbar. Fügen Sie eine Spule zum Inventar hinzu oder lösen Sie eine aus einem anderen Slot.`,kProfiles:`K-Profile`,addKProfile:`K-Profil hinzufügen`,assignSpool:`Spule zuweisen`,unassignSpool:`Zuweisung aufheben`,assignSuccess:`Spule zugewiesen und AMS-Slot konfiguriert`,assignPendingInsert:`Zugewiesen. Slot wird beim Einsetzen der Spule konfiguriert.`,assignFailed:`Spulenzuweisung fehlgeschlagen`,selectSpool:`Wählen Sie eine Spule für diesen Slot`,assigned:`Zugewiesen`,assigning:`Wird zugewiesen...`,searchSpools:`Spulen suchen...`,showAllSpools:`Alle Spulen anzeigen`,spoolmanSpools:`Spoolman-Spulen`,allMaterials:`Alle Materialien`,filterByBrand:`Nach Marke filtern...`,showArchived:`Archivierte anzeigen`,quickAdd:`Schnellerfassung (Lager)`,quantity:`Menge`,stock:`Lager`,configured:`Konfiguriert`,spoolsCreated:`{{count}} Spulen erstellt`,spoolsPartiallyCreated:`{{created}} von {{total}} Spulen erstellt (einige fehlgeschlagen)`,spoolCreated:`Spule erstellt`,spoolUpdated:`Spule aktualisiert`,spoolDeleted:`Spule gelöscht`,deepLinkSpoolNotFound:`Spule nicht gefunden`,deepLinkFetchFailed:`Spule konnte nicht geladen werden — bitte erneut versuchen`,spoolArchived:`Spule archiviert`,spoolRestored:`Spule wiederhergestellt`,kProfileSaveFailed:`K-Profil-Einstellungen konnten nicht gespeichert werden`,syncWeightSpoolNotFound:`Spule nicht gefunden — sie wurde möglicherweise gelöscht`,syncWeightSpoolmanUnreachable:`Spoolman ist nicht erreichbar — bitte später erneut versuchen`,syncWeightFailed:`Gewicht konnte nicht synchronisiert werden`,spoolmanUnreachable:`Spoolman ist nicht erreichbar — bitte später erneut versuchen`,deleteSpoolNotFound:`Spule nicht gefunden — sie wurde möglicherweise bereits gelöscht`,deleteFailed:`Spule konnte nicht gelöscht werden`,archiveSpoolNotFound:`Spule nicht gefunden — sie wurde möglicherweise bereits gelöscht`,archiveFailed:`Spule konnte nicht archiviert werden`,restoreSpoolNotFound:`Spule nicht gefunden — sie wurde möglicherweise bereits gelöscht`,restoreFailed:`Spule konnte nicht wiederhergestellt werden`,saveFailed:`Änderungen konnten nicht gespeichert werden`,tagClearFailed:`Tag konnte nicht gelöscht werden`,deleteConfirm:`Möchten Sie diese Spule wirklich löschen? Dies kann nicht rückgängig gemacht werden.`,archiveConfirm:`Möchten Sie diese Spule wirklich archivieren?`,advancedSettings:`Erweiterte Einstellungen`,filamentInfoTab:`Filament-Info`,paProfileTab:`PA-Profil`,filamentInfo:`Filament`,additional:`Zusätzlich`,loadingPresets:`Cloud-Presets werden geladen...`,cloudConnected:`Cloud verbunden`,cloudNotConnected:`Cloud nicht verbunden (Standardwerte)`,recentColors:`Zuletzt`,searchColors:`Farben suchen...`,searchResults:`Suchergebnisse`,allColors:`Alle Farben`,commonColors:`Häufige Farben`,showLess:`Weniger`,showAll:`Alle`,noColorsFound:`Keine Farben gefunden`,noResults:`Keine Ergebnisse`,extraColorsLabel:`Zusätzliche Farben`,extraColorsPlaceholder:`EC984C,#6CD4BC,A66EB9,D87694`,extraColorsHint:`2 bis 8 Hex-Stops, durch Kommas getrennt. Wird als Verlauf dargestellt.`,extraColorsInvalid:`Ungültige Hex-Werte ignoriert: {{tokens}}`,colorEffectLabel:`Effekt`,colorEffect:{none:`Keiner`,sparkle:`Glitzer`,wood:`Holz`,marble:`Marmor`,glow:`Leuchtend`,matte:`Matt`,silk:`Seide`,galaxy:`Galaxie`,rainbow:`Regenbogen`,metal:`Metallic`,translucent:`Lichtdurchlässig`,gradient:`Verlauf`,dualColor:`Zweifarbig`,triColor:`Dreifarbig`,multicolor:`Mehrfarbig`},selectMaterialFirst:`Bitte zuerst ein Material im Filament-Info Tab auswählen.`,noPrintersConfigured:`Keine Drucker konfiguriert. Fügen Sie Drucker hinzu.`,matchingFilter:`Filter`,anyBrand:`Jede Marke`,anyVariant:`Jede Variante`,autoSelect:`Auto-Auswahl`,matches:`Treffer`,match:`Treffer`,noMatches:`Keine Treffer`,connected:`Verbunden`,offline:`Offline`,printerOffline:`Drucker ist offline. Verbinden Sie ihn, um Kalibrierungsprofile anzuzeigen.`,noKProfilesMatch:`Keine K-Profile stimmen mit dem gewählten Filament überein.`,leftNozzle:`Linke Düse`,rightNozzle:`Rechte Düse`,profilesSelected:`Kalibrierungsprofil(e) ausgewählt`,totalInventory:`Gesamtbestand`,totalConsumed:`Gesamtverbrauch`,byMaterial:`Nach Material`,inPrinter:`Im Drucker`,lowStock:`Niedriger Bestand`,sinceTracking:`Seit Beginn der Erfassung`,resetConsumedCounter:`Zähler zurücksetzen`,resetConsumedCounterTooltip:`Den verbrauchten Gramm-Zähler dieser Spule auf null setzen. Das Restgewicht bleibt unverändert.`,resetConsumedCounterConfirm:`Verbrauchten Gramm-Zähler dieser Spule auf 0 zurücksetzen? Künftige Drucke zählen wieder ab null. Die Spule selbst, ihre Restgewichtsberechnung und Ihre Einstellungen bleiben unverändert.`,resetAllConsumedCounters:`Alle Zähler zurücksetzen`,resetAllConsumedCountersTooltip:`Den verbrauchten Gramm-Zähler auf jeder Spule auf null setzen. Die Restgewichte bleiben unverändert.`,resetAllConsumedCountersConfirm:`Verbrauchten Gramm-Zähler auf allen {{count}} Spulen (archivierte eingeschlossen) auf 0 zurücksetzen? Das löscht den Wert „Insgesamt verbraucht“, sodass künftige Drucke wieder ab null gezählt werden. Spulen und Restgewichte bleiben unverändert.`,consumedCounterReset:`Zähler zurückgesetzt`,allConsumedCountersReset:`Zähler für {{count}} Spule(n) zurückgesetzt`,resetConsumedCounterFailed:`Zähler konnte nicht zurückgesetzt werden`,loadedInAms:`Im AMS/Ext geladen`,remaining:`Verbleibend`,weightCheck:`Gewichtskontrolle`,lastWeighed:`Zuletzt gewogen`,neverWeighed:`Nie gewogen`,search:`Spulen suchen...`,showing:`Zeige`,to:`bis`,of:`von`,show:`Zeige`,spools:`Spulen`,spool:`Spule`,page:`Seite`,noSpoolsMatch:`Keine Ergebnisse`,noSpoolsMatchDesc:`Versuchen Sie, Ihre Suche oder Filter anzupassen.`,active:`Aktiv`,archived:`Archiviert`,all:`Alle`,used:`Verwendet`,new:`Neu`,clearFilters:`Filter löschen`,table:`Tabelle`,cards:`Karten`,net:`Netto`,groupSimilar:`Gruppieren`,groupedSpools:`{{count}} identische Spulen`,groupedRows:`Zeilen`,columns:`Spalten`,configureColumns:`Spalten konfigurieren`,configureColumnsDesc:`Ziehen zum Neuordnen oder Pfeile verwenden. Sichtbarkeit mit dem Augensymbol umschalten.`,visible:`sichtbar`,reset:`Zurücksetzen`,cancel:`Abbrechen`,applyChanges:`Änderungen anwenden`,moveUp:`Nach oben`,moveDown:`Nach unten`,hideColumn:`Spalte ausblenden`,showColumn:`Spalte einblenden`,linkToSpool:`Mit Spule verknüpfen`,tagLinked:`Tag mit Spule verknüpft`,tagLinkFailed:`Tag-Verknüpfung fehlgeschlagen`,tagAlreadyLinked:`Tag bereits mit anderer Spule verknüpft`,unknownTag:`Unbekannter RFID-Tag erkannt`,usageHistory:`Verbrauchshistorie`,noUsageHistory:`Noch kein Verbrauch erfasst`,printName:`Druckname`,weightConsumed:`Verbrauchtes Gewicht`,clearHistory:`Löschen`,historyCleared:`Verbrauchshistorie gelöscht`,fillSourceLabel:`(Inv)`,lowStockThresholdError:`Der Schwellenwert muss zwischen 0.1 und 99.9 liegen`,assignMismatchTitle:`Material stimmt nicht überein`,assignMismatchMessage:`Das ausgewählte Spulenmaterial "{{spoolMaterial}}" stimmt nicht mit dem Tray-Material "{{trayMaterial}}" für {{location}} überein. Trotzdem zuweisen?`,assignMismatchConfirm:`Trotzdem zuweisen`,assignPartialMismatchMessage:`Das Spulenmaterial "{{spoolMaterial}}" ist ähnlich, stimmt aber nicht genau mit "{{trayMaterial}}" in {{location}} überein. Möchten Sie fortfahren?`,assignProfileMismatchMessage:`Das Spulenprofil "{{spoolProfile}}" stimmt nicht mit dem Fachprofil "{{trayProfile}}" in {{location}} überein. Möchten Sie fortfahren?`,assignReconfigureNote:`Der AMS-Slot wird mit dem Profil der Spule neu konfiguriert.`,spoolmanFilamentCatalog:`Spoolman-Filamentkatalog`,pickFromSpoolmanCatalog:`Aus Spoolman-Katalog wählen…`,spoolmanFilamentSelected:`Filament aus Spoolman-Katalog ausgewählt`,spoolmanFilamentUnlinked:`Verknüpfung mit Filamentkatalog aufgehoben`,noSpoolmanFilaments:`Keine Filamente im Spoolman-Katalog gefunden`,spoolmanFilamentColorSwatch:`Filamentfarbe`,spoolWeightManagedBySpoolman:`Das Leerspulengewicht wird pro Filamenttyp in Spoolman verwaltet`,spoolmanCatalogLoadFailed:`Spoolman-Filamentkatalog konnte nicht geladen werden`},timelapse:{title:`Zeitraffer`,create:`Zeitraffer erstellen`,download:`Herunterladen`,delete:`Löschen`,preview:`Vorschau`,frameRate:`Bildrate`,quality:`Qualität`,processing:`Wird verarbeitet...`,noTimelapses:`Keine Zeitraffer verfügbar`},ams:{title:`AMS`,slot:`Slot`,empty:`Leer`,emptySlot:`Leerer Slot`,slotEmpty:`Leer`,slotUnconfigured:`?`,emptySlotReset:`Keine Spule zugewiesen`,unknown:`Unbekannt`,humidity:`Luftfeuchtigkeit`,temperature:`Temperatur`,filamentType:`Filamenttyp`,filamentColor:`Farbe`,remaining:`Verbleibend`,history:`AMS-Verlauf`,noHistory:`Kein Verlauf verfügbar`,configureSlot:`Slot konfigurieren`,externalSpool:`Externe Spule`,profile:`Profil`,kFactor:`K-Faktor`,fill:`Füllstand`,configure:`Konfigurieren`,used:`verwendet`,remainingUnit:`verbleibend`},printModal:{selectPrinter:`Drucker auswählen`,selectPlate:`Platte auswählen`,filamentMapping:`Filamentzuordnung`,useArchiveMapping:`Zuordnung`,useArchiveMappingTooltip:`Jeden Steckplatz aus der mit diesem Archiv gespeicherten AMS-Zuordnung (vom Slicer) auswählen, anstatt nach Typ/Farbe abzugleichen.`,clickToChangeSlot:`Klicken, um die Steckplatzzuweisung zu ändern`,reRead:`Neu einlesen`,plateN:`Platte {{n}}`,plateFilamentsUnreadable:`Die Filamente einer ausgewählten Platte konnten nicht gelesen werden, sie lässt sich daher nicht zuordnen. Wähle sie ab, um die anderen einzureihen.`,totalCost:`Gesamtkosten:`,slotRemainingShort:` - {{grams}}g übrig`,printSettings:`Druckeinstellungen`,bedLeveling:`Bett-Nivellierung`,flowCalibration:`Fluss-Kalibrierung`,vibrationCalibration:`Vibrations-Kalibrierung`,layerInspection:`Erste-Schicht-Prüfung`,timelapse:`Zeitraffer`,cancel:`Abbrechen`,noPrintersAvailable:`Keine Drucker verfügbar`,printerBusy:`Drucker ist beschäftigt`,printerOffline:`Drucker ist offline`,sameTypeDifferentColor:`Gleicher Typ, andere Farbe`,filamentTypeNotLoaded:`Filamenttyp nicht geladen`,whenToPrint:`Wann drucken`,asap:`Sofort`,queue:`Warteschlange`,schedule:`Planen`,dateTime:`Datum & Uhrzeit`,invalidDateTime:`Bitte ein gültiges Datum und eine gültige Uhrzeit eingeben`,openCalendar:`Kalender öffnen`,requireManualStart:`Manuellen Start erfordern`,requirePreviousSuccess:`Nur starten, wenn der vorherige Druck erfolgreich war`,autoOffAfter:`Drucker nach Abschluss ausschalten`,helpAsap:`Der Druck wird oben in die Warteschlange eingefügt und startet, sobald ein geeigneter Drucker im Leerlauf ist.`,helpSchedule:`Der Druck startet zur geplanten Zeit, wenn der Drucker im Leerlauf ist. Wenn er belegt ist, wartet er, bis der Drucker verfügbar ist.`,helpQueue:`Der Druck wird hinten in die Warteschlange eingefügt.`,leftNozzle:`L`,rightNozzle:`R`,leftNozzleTooltip:`Linke Düse`,rightNozzleTooltip:`Rechte Düse`,filamentOverride:`Filament-Überschreibung`,filamentOverrideHint:`Filamente für modellbasierte Zuweisung optional überschreiben. Der Planer wird gegen die ausgewählten Filamente statt der ursprünglichen 3MF-Werte abgleichen.`,originalFilament:`Original`,overrideWith:`Ersetzen mit`,resetToOriginal:`Auf Original zurücksetzen`,insufficientFilamentTitle:`Nicht genug Filament`,waitingForAmsStatus:`Warte auf AMS-Status von {{printer}}…`,insufficientFilamentMessage:`Einige zugewiesene Spulen haben weniger Filament als dieser Druck benötigt:`,insufficientFilamentLine:`{{printer}} - {{slot}}: benötigt {{required}}g, verbleibend {{remaining}}g`,printAnyway:`Trotzdem drucken`,forceColorMatch:`Farbe erzwingen`,staggerPrinterStarts:`Druckerstarts staffeln`,staggerGroupSize:`Gruppengröße`,staggerInterval:`Intervall (Min.)`,staggerPreview:`{{printers}} Drucker → {{groups}} Gruppen à {{size}}, Start alle {{interval}} Min.`,staggerLastGroup:`letzte Gruppe: {{count}}`,staggerTotal:`insgesamt: {{minutes}} Min.`,staggerToPrinters:`Gestaffelt an {{count}} Drucker senden`,gcodeInjection:`Auto-Print G-code einfügen`},backup:{includesEncryptionKey:`Lokale Sicherungen enthalten die MFA-Schlüsseldatei (DATA_DIR/.mfa_encryption_key), damit ein Backup-ZIP selbstkonsistent ist. Behandle das ZIP als sensibel — wer Zugriff auf die Datei hat, kann die darin enthaltenen OIDC-Client-Secrets und TOTP-Geheimnisse entschlüsseln.`,title:`Sichern & Wiederherstellen`,createBackup:`Sicherung erstellen`,restoreBackup:`Sicherung wiederherstellen`,restoreDescription:`Alle Daten aus einer Sicherungsdatei ersetzen`,downloadBackup:`Sicherung herunterladen`,uploadBackup:`Sicherung hochladen`,lastBackup:`Letzte Sicherung`,autoBackup:`Automatische Sicherung`,backupNow:`Jetzt sichern`,restoreWarning:`Warnung: Das Wiederherstellen einer Sicherung überschreibt alle aktuellen Daten.`,includeArchives:`Archive einschließen`,includeSettings:`Einstellungen einschließen`,includeProfiles:`Profile einschließen`,backupSuccess:`Sicherung erfolgreich erstellt`,restoreSuccess:`Sicherung erfolgreich wiederhergestellt`,backupFailed:`Sicherung fehlgeschlagen`,restoreFailed:`Wiederherstellung fehlgeschlagen`,restoreNote:`Virtueller Drucker wird während der Wiederherstellung gestoppt`,githubBackup:`Git-Backup`,enabled:`Aktiviert`,cloudLoginRequired:`Bambu Cloud Login erforderlich. Melden Sie sich unter Profile → Cloud-Profile an, um GitHub-Backup zu aktivieren.`,cloudLoginRequiredShort:`Cloud-Login erforderlich`,githubDescription:`Synchronisieren Sie Ihre Profile automatisch mit einem privaten GitHub-Repository für Backup und Versionsverlauf.`,repoIsPrivate:`Repository ist privat — Sicherung möglich.`,repoIsPublicWarning:`Das Repository ist ÖFFENTLICH. Bambuddy-Backups enthalten MQTT-Zugangsdaten, Home-Assistant-Tokens, Prometheus-Tokens, Ihre Bambu-Cloud-E-Mail-Adresse und über K-Profile auch Drucker-Zugangscodes. Speichern ist blockiert, bis Sie das Repository in den Einstellungen Ihres Anbieters auf privat stellen.`,repoVisibilityUnknown:`Die Sichtbarkeit des Repositories konnte nicht bestimmt werden. Bambuddy sichert nur in Repositories, die nachweislich privat sind; Speichern wird blockiert.`,repositoryUrl:`Repository-URL`,repoUrlPlaceholderGitHub:`https://github.com/username/repo-name`,repoUrlPlaceholderGitea:`https://gitea.example.com/username/repo-name`,repoUrlPlaceholderForgejo:`https://forgejo.example.com/username/repo-name`,repoUrlPlaceholderGitLab:`https://gitlab.com/username/repo-name`,allowInsecureHttp:`Unsicheres HTTP erlauben`,allowInsecureHttpHint:`Für selbst gehostete Instanzen in privaten Netzwerken ohne TLS aktivieren`,personalAccessToken:`Persönlicher Zugriffstoken`,tokenSaved:`(gespeichert)`,enterNewToken:`Neuen Token eingeben zum Aktualisieren`,tokenHint:`Feingranularer Token mit Lese-/Schreibberechtigung für Inhalte`,branch:`Branch`,provider:`Git-Anbieter`,providerGitHub:`GitHub`,providerGitLab:`GitLab`,providerGitea:`Gitea`,providerForgejo:`Forgejo`,manualOnly:`Nur manuell`,hourly:`Stündlich`,daily:`Täglich`,weekly:`Wöchentlich`,includeInBackup:`In Sicherung einschließen`,kProfiles:`K-Profile`,kProfilesDescription:`Druckvorschub-Kalibrierung von verbundenen Druckern`,noPrintersConnected:`Keine Drucker verbunden`,printersConnected:`{{connected}}/{{total}} verbunden`,cloudProfiles:`Cloud-Profile`,cloudProfilesDescription:`Filament-, Drucker- und Prozessprofile aus Bambu Cloud und Orca Cloud`,cloudProfilesAccounts:`Verbundene Konten — Bambu Cloud: {{bambu}}, Orca Cloud: {{orca}}`,appSettings:`App-Einstellungen`,appSettingsDescription:`Bambuddy-Konfiguration (komplette Datenbank)`,spoolInventory:`Spulenbestand`,spoolInventoryDescription:`Filamentspulen, Nutzungsverlauf und Kostenverfolgung`,printArchives:`Druckarchive`,printArchivesDescription:`Druckverlauf-Metadaten (keine GCode/3MF-Dateien)`,lastBackupAt:`Letzte Sicherung:`,noBackupsYet:`Noch keine Sicherungen`,next:`Nächste:`,startingBackup:`Sicherung wird gestartet...`,test:`Test`,enableBackup:`Sicherung aktivieren`,testConnection:`Verbindung testen`,enterRepoUrl:`Repository-URL eingeben`,enterRepoAndToken:`Repository-URL und Zugriffstoken eingeben`,repoRequired:`Repository-URL ist erforderlich`,tokenRequired:`Zugriffstoken ist erforderlich`,githubBackupEnabled:`GitHub-Backup aktiviert`,tokenUpdated:`Token aktualisiert`,settingsSaved:`Einstellungen gespeichert`,failedToSave:`Speichern fehlgeschlagen: {{message}}`,backupCompleteFiles:`Sicherung abgeschlossen - {{count}} Dateien aktualisiert`,backupSkippedNoChanges:`Sicherung übersprungen - keine Änderungen`,backupFailed2:`Sicherung fehlgeschlagen: {{message}}`,clearedLogs:`{{count}} Protokolle gelöscht`,failedToClearLogs:`Protokolle löschen fehlgeschlagen: {{message}}`,history:`Verlauf`,clear:`Löschen`,date:`Datum`,status:`Status`,commit:`Commit`,localBackup:`Lokale Sicherung`,localBackupDescription:`Erstellen Sie eine vollständige Sicherung Ihrer Bambuddy-Daten einschließlich Datenbank, Archive, Uploads und aller Dateien.`,downloadBackupLabel:`Sicherung herunterladen`,completeBackupZip:`Vollständige Sicherung: Datenbank + alle Dateien (ZIP)`,download:`Herunterladen`,preparingBackup:`Sicherung wird vorbereitet...`,creatingArchive:`Sicherungsarchiv wird erstellt... Dies kann bei großen Archiven eine Weile dauern.`,downloadingFile:`Sicherungsdatei wird heruntergeladen...`,backupDownloaded:`Sicherung erfolgreich heruntergeladen`,failedToCreateBackup:`Sicherung erstellen fehlgeschlagen: {{message}}`,restore:`Wiederherstellen`,restoreReplacesAll:`Wiederherstellung ersetzt alle Daten.`,restoreReplacesAllDetail:`Ihre aktuelle Datenbank und Dateien werden vollständig ersetzt. Nach der Wiederherstellung ist ein Neustart erforderlich.`,restoreConfirmTitle:`Sicherung wiederherstellen`,restoreConfirmMessage:`Sind Sie sicher, dass Sie von "{{filename}}" wiederherstellen möchten? Dies ersetzt Ihre aktuelle Datenbank und alle Dateien vollständig. Die Anwendung muss nach der Wiederherstellung neu gestartet werden.`,restoreConfirmButton:`Sicherung wiederherstellen`,uploadingFile:`Sicherungsdatei wird hochgeladen...`,backupRestoredRestart:`Sicherung wiederhergestellt. Bitte starten Sie Bambuddy neu.`,failedToRestore:`Sicherung wiederherstellen fehlgeschlagen. Bitte überprüfen Sie das Dateiformat.`,reloadNow:`Jetzt neu laden`,creatingBackup:`Sicherung erstellen`,restoringBackup:`Sicherung wiederherstellen`,preparing:`Vorbereiten...`,processing:`Verarbeiten...`,doNotClosePage:`Bitte schließen Sie diese Seite nicht und navigieren Sie nicht weg. Dieser Vorgang kann bei großen Sicherungen mehrere Minuten dauern.`,restoring:`Wiederherstellen...`,restoreComplete:`Wiederherstellung abgeschlossen`,restoreFailed2:`Wiederherstellung fehlgeschlagen`,importSettings:`Einstellungen aus einer Sicherungsdatei importieren`,pleaseWaitRestoring:`Bitte warten Sie, während Ihre Daten wiederhergestellt werden`,selectBackupFile:`Klicken Sie, um eine Sicherungsdatei auszuwählen (.json oder .zip)`,duplicateHandling:`So funktioniert die Duplikatbehandlung:`,matchPrinters:`Drucker`,matchPrintersBy:`abgeglichen nach Seriennummer`,matchSmartPlugs:`Smart Plugs`,matchSmartPlugsBy:`abgeglichen nach IP-Adresse`,matchNotificationProviders:`Benachrichtigungsanbieter`,matchNotificationProvidersBy:`abgeglichen nach Name`,matchFilaments:`Filamente`,matchFilamentsBy:`abgeglichen nach Name + Typ + Marke`,matchArchives:`Archive`,matchArchivesBy:`abgeglichen nach Inhaltshash (immer übersprungen)`,matchPendingUploads:`Ausstehende Uploads`,matchPendingUploadsBy:`abgeglichen nach Dateiname`,matchSettingsTemplates:`Einstellungen & Vorlagen`,matchSettingsTemplatesBy:`immer überschrieben`,replaceExisting:`Vorhandene Daten ersetzen`,keepExisting:`Vorhandene Daten behalten`,overwriteDescription:`Bereits vorhandene Elemente mit Sicherungsdaten überschreiben`,keepDescription:`Nur Elemente wiederherstellen, die noch nicht vorhanden sind`,overwriteCaution:`Achtung:`,overwriteWarning:`Das Überschreiben ersetzt Ihre aktuellen Konfigurationen durch Daten aus der Sicherung. Drucker-Zugangscodes werden aus Sicherheitsgründen nie überschrieben.`,cancel:`Abbrechen`,processingBackup:`Sicherungsdatei wird verarbeitet...`,itemsRestored:`Wiederhergestellt`,itemsSkipped:`Übersprungen`,restored:`Wiederhergestellt`,skippedAlreadyExist:`Übersprungen (bereits vorhanden)`,filesCategory:`Dateien (3MF, Thumbnails, etc.)`,andMore:`...und {{count}} weitere`,newApiKeysGenerated:`Neue API-Schlüssel generiert`,keysShownOnce:`Diese Schlüssel werden nur einmal angezeigt. Kopieren Sie sie jetzt!`,copy:`Kopieren`,noDataFound:`In der Sicherungsdatei wurden keine Daten zur Wiederherstellung gefunden.`,close:`Schließen`,scheduledBackup:`Geplante Backups`,scheduledBackupDescription:`Backup-Snapshots automatisch nach Zeitplan erstellen. Ausgabeverzeichnis kann auf einen NAS oder externen Speicher gemountet werden.`,frequency:`Frequenz`,backupTime:`Zeit`,retention:`Aufbewahrung`,retentionDescription:`Anzahl der zu behaltenden Backups`,outputPath:`Ausgabepfad`,outputPathPlaceholder:`Standard: {{path}}`,outputPathDescription:`Leer lassen für den Standardort`,runNow:`Jetzt ausführen`,backupFiles:`Backup-Dateien`,noScheduledBackups:`Noch keine Backups`,deleteBackup:`Löschen`,deleteBackupConfirm:`Diese Backup-Datei löschen?`,backupRunning:`Backup läuft...`,scheduledBackupComplete:`Backup erfolgreich abgeschlossen`,scheduledBackupFailed:`Backup fehlgeschlagen`,nextBackup:`Nächstes Backup`,backupSize:`Größe`,localTimeHint:`Ortszeit ({{tz}})`,defaultPathLabel:`Standard:`,pathCheck:{title:`Bambuddy kann nicht in dieses Verzeichnis schreiben`,howToFix:`So beheben Sie das:`,sandboxed:`Der Bambuddy-Dienst kann nicht nach {{path}} schreiben. Seine systemd-Unit läuft mit ProtectSystem=strict, wodurch jedes Verzeichnis außerhalb der Installations-, Daten- und Log-Verzeichnisse für den Dienst schreibgeschützt ist - auch eines, in das Sie aus Ihrer eigenen Shell schreiben können.`,read_only:`{{path}} liegt auf einem schreibgeschützten Dateisystem.`,permission_denied:`Bambuddy darf nicht nach {{path}} schreiben. Prüfen Sie Eigentümer und Rechte des Verzeichnisses.`,no_space:`Das Dateisystem, auf dem {{path}} liegt, ist voll.`,not_a_directory:`{{path}} existiert, ist aber kein Verzeichnis.`,missing:`{{path}} existiert nicht und konnte nicht angelegt werden.`,error:`Bambuddy kann nicht nach {{path}} schreiben.`,ephemeralTitle:`Diese Backups überleben einen Container-Neustart nicht`,container_ephemeral:`{{path}} liegt im Bambuddy-Container, nicht auf dem Host. Dort geschriebene Backups gehen verloren, sobald der Container neu erstellt wird. Binden Sie das Verzeichnis vom Host ein:`},categories:{settings:`Einstellungen`,notification_providers:`Benachrichtigungsanbieter`,notification_templates:`Benachrichtigungsvorlagen`,smart_plugs:`Smart Plugs`,printers:`Drucker`,filaments:`Filamente`,maintenance_types:`Wartungstypen`,archives:`Archive`,projects:`Projekte`,pending_uploads:`Ausstehende Uploads`,external_links:`Externe Links`,api_keys:`API-Schlüssel`}},tags:{title:`Tags`,addTag:`Tag hinzufügen`,editTag:`Tag bearbeiten`,deleteTag:`Tag löschen`,tagName:`Tag-Name`,tagColor:`Tag-Farbe`,noTags:`Keine Tags`,deleteConfirm:`Möchten Sie diesen Tag wirklich löschen?`,manageTags:`Tags verwalten`},uploadModal:{title:`3MF-Dateien hochladen`,dragDrop:`3MF-Dateien hierher ziehen`,or:`oder`,browseFiles:`Dateien durchsuchen`,extractionInfo:`Das Druckermodell wird automatisch aus den 3MF-Datei-Metadaten extrahiert.`,uploaded:`hochgeladen`,failed:`fehlgeschlagen`,uploading:`Wird hochgeladen...`,upload:`Hochladen`,uploadFailed:`Hochladen fehlgeschlagen`},editArchive:{title:`Archiv bearbeiten`,name:`Name`,namePlaceholder:`Druckname`,printer:`Drucker`,noPrinter:`Kein Drucker`,project:`Projekt`,noProject:`Kein Projekt`,itemsPrinted:`Gedruckte Teile`,itemsPrintedHelp:`Anzahl der in diesem Druckauftrag produzierten Teile`,notes:`Notizen`,notesPlaceholder:`Notizen zu diesem Druck hinzufügen...`,externalLink:`Externer Link`,externalLinkPlaceholder:`https://printables.com/model/...`,externalLinkHelp:`Link zu Printables, Thingiverse oder anderer Quelle`,tags:`Tags`,tagsPlaceholder:`Tags hinzufügen...`,addMoreTags:`Weitere Tags hinzufügen...`,matchingTags:`Übereinstimmend mit "{{query}}"`,existingTags:`Vorhandene Tags`,clickToAdd:`(zum Hinzufügen klicken)`,status:`Status`,failureReason:`Fehlergrund`,selectReason:`Grund auswählen...`,photos:`Fotos des Druckergebnisses`,photosHelp:`Klicken Sie auf + um Fotos Ihres Druckergebnisses hinzuzufügen`,printResult:`Druckergebnis`,saving:`Wird gespeichert...`,failureReasons:{adhesionFailure:`Haftungsfehler`,spaghettiDetached:`Spaghetti / Abgelöst`,layerShift:`Schichtversatz`,cloggedNozzle:`Verstopfte Düse`,filamentRunout:`Filament aufgebraucht`,warping:`Verformung`,stringing:`Fadenziehen`,underExtrusion:`Unterextrusion`,powerFailure:`Stromausfall`,userCancelled:`Vom Benutzer abgebrochen`,other:`Sonstiges`},statuses:{completed:`Abgeschlossen`,failed:`Fehlgeschlagen`,aborted:`Abgebrochen`,printing:`Druckt`}},kProfiles:{title:`K-Profile`,noPrintersConfigured:`Keine Drucker konfiguriert`,addPrinterInSettings:`Fügen Sie einen Drucker in den Einstellungen hinzu, um K-Profile zu verwalten`,noActivePrinters:`Keine aktiven Drucker`,enablePrinterConnection:`Aktivieren Sie eine Druckerverbindung, um K-Profile anzuzeigen`,loadingProfiles:`Lade K-Profile...`,printerOffline:`Drucker offline`,printerOfflineDesc:`Der ausgewählte Drucker ist nicht verbunden. Schalten Sie ihn ein, um K-Profile anzuzeigen.`,noMatchingProfiles:`Keine passenden Profile`,noMatchingProfilesDesc:`Keine Profile entsprechen Ihren Suchkriterien`,noKProfiles:`Keine K-Profile`,noKProfilesDesc:`Keine Druckvorschub-Profile für {{diameter}}mm Düse gefunden`,createFirstProfile:`Erstes Profil erstellen`,printer:`Drucker`,nozzle:`Düse`,refresh:`Aktualisieren`,addProfile:`Profil hinzufügen`,export:`Exportieren`,import:`Importieren`,select:`Auswählen`,selectAll:`Alle auswählen`,delete:`Löschen`,searchPlaceholder:`Nach Name oder Filament suchen...`,allExtruders:`Alle Extruder`,leftOnly:`Nur links`,rightOnly:`Nur rechts`,allFlow:`Alle Flusstypen`,hfOnly:`Nur HF`,sOnly:`Nur S`,sortName:`Sortieren: Name`,sortKValue:`Sortieren: K-Wert`,sortFilament:`Sortieren: Filament`,leftExtruder:`Linker Extruder`,rightExtruder:`Rechter Extruder`,modal:{addTitle:`K-Profil hinzufügen`,editTitle:`K-Profil bearbeiten`,profileName:`Profilname`,profileNamePlaceholder:`Mein PLA-Profil`,kValue:`K-Wert`,kValuePlaceholder:`0,020`,kValueHelp:`Typischer Bereich: 0,01 - 0,06 für PLA, 0,02 - 0,10 für PETG`,filament:`Filament`,selectFilament:`Filament auswählen...`,source:{local:`Importiert`,orcaCloud:`Orca Cloud`,bambuCloud:`Bambu Cloud`,builtin:`Integriert`},noFilamentsHelp:`Keine Filamente verfügbar. Melde dich bei Bambu Cloud an oder importiere Presets unter Profile → Lokale Profile.`,searchFilaments:`Filamente durchsuchen...`,noFilamentMatches:`Kein Filament passt zu dieser Suche`,flowType:`Flusstyp`,highFlow:`Hoher Durchfluss`,standard:`Standard`,nozzleSize:`Düsengröße`,extruder:`Extruder`,extruders:`Extruder`,left:`Links`,right:`Rechts`,notes:`Notizen (lokal gespeichert)`,notesPlaceholder:`Notizen zu diesem Profil hinzufügen...`,notesHelp:`Notizen werden in Bambuddy gespeichert, nicht auf dem Drucker`,syncing:`Synchronisiert mit Drucker...`,savingExtruder:`Speichern auf Extruder {{current}}/{{total}}...`,pleaseWait:`Bitte warten`},deleteConfirm:{title:`Profil löschen`,cannotUndo:`Dies kann nicht rückgängig gemacht werden`,message:`Möchten Sie "{{name}}" wirklich vom Drucker löschen?`},bulkDelete:{title:`Profile löschen`,cannotUndo:`Dies kann nicht rückgängig gemacht werden`,message:`Möchten Sie wirklich {{count}} ausgewählte Profile vom Drucker löschen?`},toast:{profileSaved:`K-Profil gespeichert`,profilesSaved:`K-Profil auf {{count}} Extrudern gespeichert`,selectAtLeastOneExtruder:`Bitte wählen Sie mindestens einen Extruder aus`,selectFilament:`Bitte zuerst ein Filament auswählen`,filamentNotResolvable:`Keine Bambu-Filament-ID für {{name}} — der Drucker kann dafür kein Profil speichern`,profileDeleted:`K-Profil gelöscht`,profilesDeleted:`{{count}} Profile gelöscht`,exportedProfiles:`{{count}} Profile exportiert`,importedProfiles:`{{count}} von {{total}} Profilen importiert`,noProfilesToExport:`Keine Profile zum Exportieren`,invalidFileFormat:`Ungültiges Dateiformat`,failedToParseImport:`Import-Datei konnte nicht gelesen werden`,failedToSaveBatch:`K-Profile konnten nicht gespeichert werden`,noteSaved:`Notiz gespeichert`,failedToSaveNote:`Notiz konnte nicht gespeichert werden`},permission:{noRead:`Sie haben keine Berechtigung, Profile zu aktualisieren`,noCreate:`Sie haben keine Berechtigung, Profile hinzuzufügen`,noUpdate:`Sie haben keine Berechtigung, K-Profile zu aktualisieren`,noDelete:`Sie haben keine Berechtigung, K-Profile zu löschen`,noExport:`Sie haben keine Berechtigung, Profile zu exportieren`,noImport:`Sie haben keine Berechtigung, Profile zu importieren`}},virtualPrinter:{title:`Virtueller Drucker`,running:`Läuft`,stopped:`Gestoppt`,description:{default:`Aktiviere einen virtuellen Drucker, der in Bambu Studio und OrcaSlicer erscheint. Dateien, die an diesen Drucker gesendet werden, werden direkt archiviert ohne zu drucken.`,proxy:`Aktiviere einen Proxy, der Slicer-Datenverkehr an einen echten Drucker weiterleitet, um Ferndruck über jedes Netzwerk zu ermöglichen.`},enable:{title:`Virtuellen Drucker aktivieren`,visibleInSlicer:`Sichtbar als "Bambuddy" in der Slicer-Erkennung`,proxyingTo:`Proxy zu {{name}}`,notActive:`Nicht aktiv`},model:{title:`Druckermodell`,description:`Wähle welches Druckermodell emuliert werden soll.`,restartWarning:`Das Ändern des Modells startet den virtuellen Drucker neu`},accessCode:{title:`Zugangscode`,isSet:`Zugangscode ist gesetzt`,notSet:`Kein Zugangscode gesetzt - erforderlich zum Aktivieren`,placeholder:`8-Zeichen-Code eingeben`,placeholderChange:`Neuen Code eingeben zum Ändern`,hint:`Muss genau 8 Zeichen lang sein. Wird von Slicern zur Authentifizierung verwendet.`,charCount:`({{count}}/8)`,inheritedFromTarget:`Vom Zieldrucker übernommen`,derivedFromTargetHint:`Verwendet den Zugangscode des Zieldruckers. Die Brücke leitet die Slicer-Authentifizierung an den echten Drucker weiter, daher müssen die Codes übereinstimmen — den Druckercode in dessen Einstellungen ändern.`,reveal:`Zugangscode anzeigen`,hide:`Zugangscode verbergen`},targetPrinter:{title:`Zieldrucker`,configured:`Proxy-Ziel konfiguriert`,notConfigured:`Kein Zieldrucker ausgewählt - erforderlich für Proxy-Modus`,placeholder:`Drucker auswählen...`,hint:`Wähle den Drucker aus, an den der Slicer-Datenverkehr weitergeleitet werden soll. Der Drucker muss im LAN-Modus sein.`,noPrinters:`Keine Drucker konfiguriert. Füge zuerst einen Drucker hinzu, um den Proxy-Modus zu verwenden.`},remoteInterface:{title:`Netzwerkschnittstelle überschreiben`,configured:`Schnittstellenüberschreibung aktiv`,optional:`Optional - verwenden wenn die automatisch erkannte IP falsch ist (z.B. mehrere NICs, Docker, VPN)`,placeholder:`Automatisch erkennen (Standard)...`,hint:`Überschreibt die per SSDP beworbene und im TLS-Zertifikat verwendete IP-Adresse. Nützlich wenn Bambuddy mehrere Netzwerkschnittstellen hat.`},mode:{title:`Modus`,archive:`Archivieren`,archiveDesc:`Dateien sofort archivieren`,review:`Überprüfen`,reviewDesc:`Vor dem Archivieren überprüfen`,queue:`Warteschlange`,queueDesc:`Archivieren und zur Warteschlange hinzufügen`,proxy:`Proxy`,proxyDesc:`An echten Drucker weiterleiten`},autoDispatch:{title:`Automatisch starten`,description:`Drucke automatisch starten, wenn sie zur Warteschlange hinzugefügt werden. Wenn deaktiviert, warten Drucke auf manuellen Start.`},queueForceColorMatch:{title:`Farbabgleich erzwingen`,description:`Druckaufträge nur an Drucker senden, bei denen der genaue Filament-Typ und die genaue Farbe geladen sind. Standardmäßig deaktiviert — ohne diese Option verwendet die Warteschlange nur den Drucker-Modell-Abgleich und wählt möglicherweise einen Drucker mit der falschen Farbe.`},saveAmsMapping:{title:`AMS-Zuordnung speichern`,description:`Speichert die vom Slicer selbst gewählte AMS-Steckplatz-Zuordnung (aus dem MQTT-Befehl project_file) im Archiv, sodass ein späterer erneuter Druck dieselbe physische Spule verwendet, anstatt sie erneut aus Typ/Farbe der Datei abzuleiten. Standardmäßig deaktiviert.`},gcodeInjection:{title:`G-code-Injektion`,description:`Wendet die in den Einstellungen pro Modell konfigurierten G-code-Snippets auf Jobs dieses VP an. Standardmäßig aus.`},tailscaleDisabled:{title:`Tailscale-Integration`,description:`Aktivieren, um diesen VP als per Tailscale erreichbar zu markieren. Zeigt die Tailscale-Adresse des Hosts an, damit du weißt, welche IP du im Slicer eintragen musst. Der CA-Import bleibt unverändert — diese Option hat keinen Einfluss auf Zertifikate.`},setupRequired:{title:`Einrichtung erforderlich`,description:`Die virtuelle Druckerfunktion erfordert zusätzliche Systemkonfiguration, bevor sie funktioniert. Dies beinhaltet Portweiterleitung, Firewall-Regeln und plattformspezifische Einstellungen.`,readGuide:`Lese die Einrichtungsanleitung vor dem Aktivieren`},archiveNameSource:{title:`Quelle des Archivnamens`,description:`Lege fest, wie neue Archive benannt werden, wenn Dateien über den virtuellen Drucker eintreffen. "Metadaten" verwendet den im 3MF eingebetteten Titel des Slicers (Standard). "Dateiname" nutzt den Dateinamen, den Bambu Studio per FTP gesendet hat. Hinweis: Bambu Studio überschreibt den im Dialog "Zum Drucker senden" eingegebenen Namen mit dem Titelfeld der 3MF, sofern eines vorhanden ist — beide Modi liefern daher oft denselben Wert.`,metadata:`Metadaten`,filename:`Dateiname`},caCert:{title:`Slicer-Zertifikat`,description:`Virtuelle Drucker verwenden ein TLS-Zertifikat, das von der Bambuddy-CA signiert ist. Importieren Sie dieses CA-Zertifikat einmalig in den Vertrauensspeicher Ihres Slicers, damit er die Verbindung akzeptiert — kein Abrufen über die Kommandozeile mehr nötig.`,copy:`Kopieren`,copied:`Kopiert`,download:`Herunterladen`,fingerprint:`SHA-256`},howItWorks:{title:`So funktioniert es`,step1:`Im selben LAN erscheinen virtuelle Drucker automatisch in deinem Slicer (Bambu Studio / OrcaSlicer). Aus anderen Netzwerken füge sie manuell per IP-Adresse und Zugangscode hinzu.`,step2:`Im Archiv-, Überprüfungs- und Warteschlangen-Modus verwende die "Senden"-Funktion im Slicer, um 3MF-Dateien an Bambuddy zu senden. Der Slicer zeigt "Druck erfolgreich" — die Datei wird gespeichert, nicht gedruckt.`,step3:`Im Proxy-Modus leitet der virtuelle Drucker den gesamten Datenverkehr an einen echten Drucker weiter — Drucke starten sofort wie bei einer direkten Verbindung.`},status:{title:`Status-Details`,printerName:`Druckername`,model:`Modell`,serialNumber:`Seriennummer`,mode:`Modus`,pendingFiles:`Ausstehende Dateien`,targetPrinter:`Zieldrucker`,ftpPort:`FTP-Port`,mqttPort:`MQTT-Port`,ftpConnections:`FTP-Verbindungen`,mqttConnections:`MQTT-Verbindungen`},toast:{updated:`Virtuelle Druckereinstellungen aktualisiert`,failedToUpdate:`Einstellungen konnten nicht aktualisiert werden`,copyFailed:`Kopieren fehlgeschlagen — bitte Text manuell markieren`,accessCodeRequired:`Bitte zuerst einen Zugangscode setzen`,targetPrinterRequired:`Bitte zuerst einen Zieldrucker auswählen`,bindIpRequired:`Bitte zuerst eine Bind-IP setzen`,accessCodeEmpty:`Zugangscode darf nicht leer sein`,accessCodeLength:`Zugangscode muss genau 8 Zeichen lang sein`,targetCodeChangedRebind:`Zugangscode wurde an den neuen Zieldrucker angepasst. Bitte dieses Gerät im Slicer neu hinzufügen, damit der neue Code übernommen wird.`,created:`Virtueller Drucker erstellt`,failedToCreate:`Virtueller Drucker konnte nicht erstellt werden`,deleted:`Virtueller Drucker gelöscht`,failedToDelete:`Virtueller Drucker konnte nicht gelöscht werden`},list:{title:`Virtuelle Drucker`,add:`Hinzufügen`,addFirst:`Virtuellen Drucker hinzufügen`,empty:`Keine virtuellen Drucker konfiguriert. Fügen Sie einen hinzu, um zu beginnen.`},bindIp:{title:`Bind-Interface`,placeholder:`Interface auswählen...`,hint:`Netzwerkinterface, an das dieser virtuelle Drucker gebunden wird. Muss pro Drucker eindeutig sein.`},proxy:{accessCodeHint:`Im Proxy-Modus den Zugangscode des Zieldruckers im Slicer verwenden. Die Verbindung wird transparent zum echten Drucker weitergeleitet.`},addDialog:{title:`Virtuellen Drucker hinzufügen`,name:`Name`,hint:`Sie können Zugangscode, Zieldrucker und andere Einstellungen nach dem Erstellen konfigurieren.`,create:`Erstellen`},deleteConfirm:{title:`Virtuellen Drucker löschen`,message:`Möchten Sie "{{name}}" wirklich löschen? Dies stoppt alle Dienste für diesen Drucker.`}},modelViewer:{openInSlicer:`Im Slicer öffnen`,tabs:{model:`3D-Modell`,gcode:`G-Code Vorschau`},notAvailable:`nicht verfügbar`,notSliced:`nicht geslicet`,plates:`Platten`,allPlates:`Alle Platten`,plateNumber:`Platte {{number}}`,plateCount:`{{count}} Platte`,plateCount_other:`{{count}} Platten`,objectCount:`{{count}} Objekt`,objectCount_other:`{{count}} Objekte`,filamentCount:`{{count}} Filament`,filamentCount_other:`{{count}} Filamente`,eta:`ETA {{minutes}} Min`,noPreview:`Keine Vorschau für diese Datei verfügbar`,pagination:{pageOf:`Seite {{current}} von {{total}}`,prev:`Zurück`,next:`Weiter`},errors:{failedToLoad:`Datei konnte nicht geladen werden`,noMeshes:`Keine Meshes in 3MF-Datei gefunden`,unsupportedFormat:`Nicht unterstütztes Dateiformat`}},maintenanceDescriptions:{lubricateCarbonRods:`Schmiermittel auf Karbonstäbe für sanfte Bewegung auftragen`,lubricateRails:`Schmiermittel auf Linearschienen für sanfte Bewegung auftragen`,cleanNozzle:`Hotend und Düse reinigen, um Verstopfungen zu verhindern`,checkBelts:`Riemenspannung für präzise Drucke überprüfen`,cleanBuildPlate:`Druckplatte für bessere Haftung reinigen`,checkExtruder:`Extruderzahnräder auf Verschleiß prüfen`,checkCooling:`Sicherstellen, dass Lüfter ordnungsgemäß funktionieren`,generalInspection:`Allgemeine Druckerinspektion`,cleanCarbonRods:`Karbonstäbe reinigen, um Reibung zu reduzieren`,lubricateSteelRods:`Schmiermittel auf Stahlstangen für sanfte Bewegung auftragen`,cleanSteelRods:`Stahlstangen reinigen, um Reibung zu reduzieren`,cleanLinearRails:`Linearschienen abwischen, um Staub und Schmutz zu entfernen`,checkPtfeTube:`PTFE-Schlauch auf Verschleiß oder Beschädigung prüfen`,replaceHepaFilter:`HEPA-Filter für Luftqualität ersetzen`,replaceCarbonFilter:`Aktivkohlefilter ersetzen`,lubricateLeftNozzleRail:`Linke Düsenschiene schmieren (H2-Serie)`},smartPlugs:{offline:`Offline`,admin:`Admin`,openPlugAdminPage:`Plug-Admin-Seite öffnen`,deleteSmartPlug:`Smart Plug löschen`,turnOnSmartPlug:`Smart Plug einschalten`,turnOffSmartPlug:`Smart Plug ausschalten`,turnOn:`Einschalten`,turnOff:`Ausschalten`,addSmartPlug:{scanningNetwork:`Netzwerk wird durchsucht...`,chooseEntity:`Entität auswählen...`,connectionFailed:`Verbindung fehlgeschlagen`,searchEntities:`Entitäten suchen...`,searchPowerSensors:`Leistungssensoren suchen...`,searchEnergySensors:`Energiesensoren suchen...`,placeholders:{plugName:`Wohnzimmer Steckdose`,mqttStateOnValue:`ON, true, 1`,mqttSameAsPower:`Gleich wie Leistungs-Topic oder anders`}},linkedTo:`Verbunden mit:`,monitorOnly:`Nur Überwachung`,alerts:`Alarme`,scheduleOn:`Ein {{time}}`,scheduleOff:`Aus {{time}}`,on:`Ein`,off:`Aus`,power:`Leistung`,kwhToday:`kWh Heute`,settings:`Einstellungen`,automationSettings:`Automatisierungseinstellungen`,showInSwitchbar:`In Schaltleiste anzeigen`,quickAccessSidebar:`Schnellzugriff über Seitenleiste`,enabled:`Aktiviert`,enableAutomation:`Automatisierung für diesen Stecker aktivieren`,autoOn:`Auto Ein`,autoOnDescription:`Einschalten wenn Druck startet`,autoOff:`Auto Aus`,autoOffDescription:`Ausschalten wenn Druck abgeschlossen (einmalig)`,autoOffPersistent:`Aktiviert lassen`,autoOffPersistentDescription:`Zwischen Drucken aktiviert bleiben statt einmalig`,controlsPrinterPower:`Versorgt den Drucker`,controlsPrinterPowerDescription:`Deaktivieren, wenn diese Steckdose nur Zubehör versorgt (Filterlüfter, Licht). Sonst wird der Drucker beim Ausschalten als offline markiert.`,autoOffAfterDrying:`Automatisch aus nach Trocknung`,autoOffAfterDryingDescription:`Ausschalten, wenn AMS-Trocknung abgeschlossen ist`,delayAfterDryingMinutes:`Verzögerung nach Trocknung (Minuten)`,turnOffDelayMode:`Ausschaltverzögerungsmodus`,time:`Zeit`,temp:`Temp.`,delayMinutes:`Verzögerung (Minuten)`,tempThreshold:`Temperaturschwelle (°C)`,tempThresholdDescription:`Schaltet aus wenn die Düse unter diese Temperatur abkühlt`,edit:`Bearbeiten`,deleteConfirm:`Möchten Sie "{{name}}" wirklich löschen? Dies kann nicht rückgängig gemacht werden.`,turnOnConfirm:`Möchten Sie "{{name}}" wirklich einschalten?`,turnOffConfirm:`Möchten Sie "{{name}}" wirklich ausschalten? Dies unterbricht die Stromversorgung des angeschlossenen Geräts.`,failedToTurn:`{{name}}" konnte nicht {{action}} werden`,unknown:`Unbekannt`,addTitle:`Smart Plug hinzufügen`,editTitle:`Smart Plug bearbeiten`,stopScanning:`Suche beenden`,discoverTasmota:`Tasmota Geräte suchen`,foundDevices:`{{count}} Gerät(e) gefunden - zum Auswählen klicken:`,noDevicesFound:`Keine Tasmota Geräte in Ihrem Netzwerk gefunden`,haNotConfigured:`Home Assistant ist nicht konfiguriert. Einrichtung unter`,haSettingsPath:`Einstellungen → Netzwerk → Home Assistant`,selectEntity:`Entität auswählen *`,ipAddress:`IP-Adresse *`,nameLabel:`Name *`,username:`Benutzername`,password:`Passwort`,authHint:`Leer lassen, wenn Ihr Tasmota-Gerät keine Authentifizierung benötigt`,linkToPrinter:`Mit Drucker verbinden`,noPrinter:`Kein Drucker (nur manuelle Steuerung)`,linkingDescription:`Verknüpfung ermöglicht automatisches Ein-/Ausschalten bei Druckstart/-ende`,powerAlerts:`Leistungsalarme`,alertAbove:`Alarm wenn über (W)`,alertBelow:`Alarm wenn unter (W)`,alertDescription:`Benachrichtigung wenn der Stromverbrauch diese Schwellenwerte überschreitet. Leer lassen um diese Richtung zu deaktivieren.`,dailySchedule:`Tagesplan`,turnOnAt:`Einschalten um`,turnOffAt:`Ausschalten um`,scheduleDescription:`Den Stecker automatisch täglich zu diesen Zeiten ein-/ausschalten. Leer lassen um diese Aktion zu überspringen.`,showOnPrinterCard:`Auf Druckerkarte anzeigen`,displayOnPrinterCard:`Schaltfläche auf Druckerkarte anzeigen`,connectedResult:`Verbunden!`,deviceLabel:`Gerät: {{name}} - `,stateLabel:`Status: {{state}}`,test:`Test`,delete:`Löschen`,save:`Speichern`,add:`Hinzufügen`,cancel:`Abbrechen`,failedToStartScan:`Suche konnte nicht gestartet werden`,nameRequired:`Name ist erforderlich`,entityRequired:`Entität ist für Home Assistant Stecker erforderlich`,mqttTopicRequired:`Mindestens ein MQTT-Topic muss für Leistung, Energie oder Statusüberwachung konfiguriert sein`,loadingEntities:`Entitäten werden geladen...`,loading:`Laden...`,failedToLoadEntities:`Entitäten konnten nicht geladen werden: {{error}}`,noEntitiesMatching:`Keine Entitäten gefunden die "{{search}}" entsprechen`,noEntitiesAvailable:`Keine Entitäten verfügbar`,searchingEntities:`Alle Entitäten durchsuchen ({{count}} gefunden)`,showingEntities:`Zeige switch, light, input_boolean ({{count}} verfügbar)`,energyMonitoringOptional:`Energieüberwachung (Optional)`,energyMonitoringHint:`Sensoren suchen und auswählen, die Leistungs-/Energiedaten liefern.`,powerSensorW:`Leistungssensor (W)`,energyTodayKwh:`Energie Heute (kWh)`,totalEnergyKwh:`Gesamtenergie (kWh)`,noMatchingSensors:`Keine passenden Sensoren`,none:`Keine`,mqttNotConfigured:`MQTT-Broker nicht konfiguriert. Broker-Adresse einstellen unter`,mqttSettingsPath:`Einstellungen → Netzwerk → MQTT-Veröffentlichung`,mqttNotConfiguredSuffix:`(Sie müssen die Veröffentlichung nicht aktivieren, nur die Broker-Details ausfüllen).`,mqttMonitorOnlyDescription:`MQTT-Stecker empfangen Leistungs-/Energiedaten über MQTT-Abonnement. Ein-/Ausschalten ist nicht verfügbar - verwenden Sie Ihren MQTT-Broker oder Ihr Home-Automation-System.`,powerMonitoring:`Leistungsüberwachung`,energyMonitoring:`Energieüberwachung`,stateMonitoring:`Statusüberwachung`,optional:`optional`,topic:`Thema`,jsonPath:`JSON-Pfad`,multiplier:`Multiplikator`,onValue:`EIN-Wert`,mqttPowerHint:`JSON-Pfad extrahiert Wert aus JSON-Payload (z.B. "power_l1"). Leer lassen wenn Topic rohe numerische Werte sendet. @@ -45,9 +45,9 @@ ON değeri: "ON" anlamına gelen tam string. Otomatik algılama için boş bıra Значение «включено» — точная строка, означающая включённое состояние. Оставьте пустым для автоматического распознавания ON, true и 1.`,restControl:`Управление`,restOnUrl:`URL включения`,restOffUrl:`URL выключения`,restOnBody:`Тело запроса включения`,restOffBody:`Тело запроса выключения`,restMethod:`Метод HTTP`,restHeaders:`Пользовательские заголовки (JSON)`,restStatusUrl:`URL состояния`,restStatusPath:`Путь JSON состояния`,restStatusOnValue:`Значение «включено»`,restPowerUrl:`URL мощности`,restPowerPath:`Путь JSON мощности`,restPowerMultiplier:`Множитель мощности`,restEnergyUrl:`URL энергии`,restEnergyPath:`Путь JSON энергии`,restEnergyTotalPath:`Путь JSON полной энергии`,restEnergyTotalMultiplier:`Множитель полной энергии`,restEnergyTotalPathHint:`например, aenergy.total`,restEnergyTotalHint:`Многие розетки, включая все устройства Shelly, передают только накопительный счётчик энергии, который никогда не сбрасывается. Его следует указывать здесь, а не в поле выше: если считать его суточным расходом, значение не сбросится в полночь, а данные за вчера и общий расход останутся пустыми. Bambuddy вычисляет расход за сегодня и вчера по этому счётчику; для накопления данных потребуется один-два дня. Shelly передаёт ватт-часы, поэтому используйте множитель 0.001.`,restEnergyMultiplier:`Множитель энергии`,restUrlRequired:`Для REST-розетки необходимо указать хотя бы один URL: включения или выключения`,restHeadersHint:`например, {"Authorization": "Bearer your-token"}`,restBodyHint:`например, ON или {"state": "on"}`,restStatusHint:`URL для опроса текущего состояния`,restPathHint:`например, state или data.power.status`,restPowerUrlHint:`Отдельный URL данных мощности; если пусто, используется URL состояния`,restEnergyUrlHint:`Отдельный URL данных энергии; если пусто, используется URL состояния`,restEnergyHint:`Для каждого значения можно использовать отдельный URL либо URL состояния. Множители используются для преобразования единиц, например 0.001 для Вт·ч→кВт·ч.`,testConnection:`Проверить подключение`,connectionSuccess:`Подключение успешно`,noSwitchesInSwitchbar:`На панели переключателей нет устройств`,enableSwitchbarHint:`Включите «Показывать на панели переключателей» в разделе «Настройки → Умные розетки»`},notifications:{providerTypes:{callmebot:`CallMeBot/WhatsApp`,ntfy:`ntfy`,pushover:`Pushover`,telegram:`Telegram`,email:`Электронная почта`,discord:`Discord`,webhook:`Вебхук`,homeassistant:`Home Assistant`,bark:`Bark`},providerDescriptions:{email:`Уведомления по электронной почте через SMTP`,telegram:`Уведомления через Telegram-бота`,discord:`Отправка в канал Discord через вебхук`,ntfy:`Бесплатные push-уведомления с возможностью самостоятельного размещения сервера`,pushover:`Простые и надёжные push-уведомления`,callmebot:`Бесплатные уведомления WhatsApp через CallMeBot`,webhook:`Универсальный HTTP POST-запрос на любой URL`,homeassistant:`Постоянные уведомления на панели Home Assistant`,bark:`iOS push-уведомления через Bark (можно разместить у себя)`},lastSuccess:`Последняя отправка: {{date}}`,error:`Ошибка`,printer:`Принтер:`,allPrinters:`Все принтеры`,sendTestNotification:`Отправить тестовое уведомление`,eventSettings:`Настройки событий`,enabled:`Включено`,sendFromProvider:`Отправлять уведомления через этого провайдера`,printEvents:`События печати`,printerStatus:`Состояние принтера`,amsAlarms:`Предупреждения AMS`,amsHtAlarms:`Предупреждения AMS-HT`,printQueue:`Очередь печати`,start:`Запуск`,plateCheck:`Проверка пластины`,complete:`Завершено`,failed:`Ошибка`,stopped:`Остановлено`,progress:`Ход печати`,offline:`Не в сети`,lowFilament:`Мало филамента`,maintenance:`Обслуживание`,amsHumidity:`Влажность AMS`,amsTemp:`Температура AMS`,amsHtHumidity:`Влажность AMS-HT`,amsHtTemp:`Температура AMS-HT`,bedCooled:`Стол остыл`,firstLayer:`Первый слой`,quiet:`Тихий режим`,digest:`Сводка в {{time}}`,printStarted:`Печать началась`,plateNotEmpty:`Пластина не пуста`,plateNotEmptyDescription:`Перед печатью на пластине обнаружены объекты`,plateClearRequired:`Требуется подтверждение стола`,plateClearRequiredDescription:`Печать завершена, очередь ждет подтверждения`,plateClear:`Стол свободен`,printCompleted:`Печать завершена`,bedCooledLabel:`Стол остыл`,bedCooledDescription:`После печати температура стола опустилась ниже заданного порога`,firstLayerCompleteLabel:`Первый слой завершён`,firstLayerCompleteDescription:`Уведомить со снимком после завершения первого слоя`,missingSpoolAssignmentLabel:`Катушка не назначена`,missingSpoolAssignmentDescription:`Уведомить при запуске печати, если для необходимых слотов не назначены катушки`,printFailed:`Ошибка печати`,printStopped:`Печать остановлена`,progressMilestones:`Этапы выполнения`,progressMilestonesDescription:`Уведомлять при 25%, 50% и 75%`,printerOffline:`Принтер не в сети`,printerError:`Ошибка принтера`,aiFailureDetection:`Обнаружение сбоев с помощью ИИ`,aiFailureDetectionDescription:`Уведомить, если Obico AI обнаружит возможный сбой печати`,lowFilamentLabel:`Заканчивается филамент`,maintenanceDue:`Требуется обслуживание`,maintenanceDueDescription:`Уведомить, когда принтеру потребуется обслуживание`,amsHumidityHigh:`Высокая влажность в AMS`,amsHumidityHighDescription:`Влажность в обычной AMS превысила заданный порог`,amsTemperatureHigh:`Высокая температура в AMS`,amsTemperatureHighDescription:`Температура в обычной AMS превысила заданный порог`,amsHtHumidityHigh:`Высокая влажность в AMS-HT`,amsHtHumidityHighDescription:`Влажность в AMS-HT превысила заданный порог`,amsHtTemperatureHigh:`Высокая температура в AMS-HT`,amsHtTemperatureHighDescription:`Температура в AMS-HT превысила заданный порог`,inventoryAlerts:`Уведомления о запасах`,stockReorderAlert:`Пора заказывать`,stockReorderAlertDescription:`Запас по SKU достиг точки повторного заказа`,stockBreakAlert:`Риск исчерпания запаса`,stockBreakAlertDescription:`Запас закончится раньше, чем поступит пополнение`,jobAdded:`Задание добавлено`,jobAddedDescription:`Задание добавлено в очередь`,jobAssigned:`Задание назначено`,jobAssignedDescription:`Задание по модели назначено принтеру`,jobStarted:`Задание запущено`,jobStartedDescription:`Задание из очереди отправлено на печать`,jobWaiting:`Задание ожидает`,jobWaitingDescription:`Задание ожидает филамент или свободный принтер`,jobSkipped:`Задание пропущено`,jobSkippedDescription:`Задание пропущено из-за ошибки предыдущего`,jobFailed:`Не удалось запустить задание`,jobFailedDescription:`Задание не удалось отправить на печать`,queueComplete:`Очередь завершена`,queueCompleteDescription:`Все задания в очереди завершены`,quietHours:`Тихие часы`,noNotificationsDuring:`Не отправлять уведомления в это время`,editProviderToChangeQuietHours:`Измените провайдера, чтобы настроить тихие часы`,dailyDigest:`Ежедневная сводка`,batchNotifications:`Объединять уведомления в одну ежедневную сводку`,sendAt:`Отправлять в {{time}}`,editProviderToChangeDigestTime:`Измените провайдера, чтобы настроить время сводки`,edit:`Изменить`,deleteProvider:`Удалить провайдера уведомлений`,deleteConfirm:`Удалить «{{name}}»? Это действие нельзя отменить.`,delete:`Удалить`,addTitle:`Добавить провайдера уведомлений`,editTitle:`Изменить провайдера уведомлений`,nameLabel:`Название *`,namePlaceholder:`Мои уведомления`,providerTypeLabel:`Тип провайдера *`,configuration:`Настройка`,testConfiguration:`Проверить настройку`,printerFilter:`Фильтр принтеров`,onlyFromPrinter:`Отправлять уведомления только о событиях этого принтера`,quietHoursDnd:`Тихие часы (не беспокоить)`,quietStart:`Начало`,quietEnd:`Окончание`,dailyDigestLabel:`Ежедневная сводка`,sendDigestAt:`Отправлять сводку в`,digestCollected:`События будут собраны и отправлены одной сводкой в указанное время`,notificationEvents:`События для уведомлений`,progressPercent:`(25%, 50%, 75%)`,bedCooledAfterPrint:`(после завершения печати)`,eventPriority:{sectionTitle:`Приоритет ntfy`,helpNtfy:`Выберите приоритет для каждого включённого события. ntfy использует его для усиления оповещений: звука, видимости и поведения push-уведомлений. Для неуказанных событий используется приоритет по умолчанию сервера ntfy.`,min:`Минимальный`,low:`Низкий`,default:`Обычный`,high:`Высокий`,urgent:`Срочный`},cancel:`Отмена`,save:`Сохранить`,add:`Добавить`,nameRequired:`Укажите название`,fieldRequired:`Поле «{{field}}» обязательно`,haDataInvalid:`Поле Data должно быть корректным JSON-объектом, напр. {"priority": "high", "ttl": 0}`,phoneNumber:`Номер телефона`,apiKey:`Ключ API`,serverUrl:`URL сервера`,topic:`Тема`,authToken:`Токен авторизации`,userKey:`Ключ пользователя`,appToken:`Токен приложения`,priority:`Приоритет`,pushoverRetry:`Повтор экстренного уведомления (с)`,pushoverExpire:`Срок действия экстренного уведомления (с)`,botToken:`Токен бота`,chatId:`ID чата`,telegramThreadId:`ID темы форума`,telegramThreadIdHelp:`Необязательно. Отправляет в конкретную тему форум-группы — последнее число в ссылке на тему (t.me/c/.../25). Оставьте пустым для темы General.`,telegramThreadIdInvalid:`ID темы форума должен быть числом.`,smtpServer:`SMTP-сервер`,smtpPort:`Порт SMTP`,security:`Защита соединения`,authentication:`Аутентификация`,username:`Имя пользователя`,password:`Пароль`,fromEmail:`Адрес отправителя`,toEmail:`Адрес получателя`,webhookUrl:`URL вебхука`,payloadFormat:`Формат данных`,authorization:`Авторизация`,titleFieldName:`Имя поля заголовка`,messageFieldName:`Имя поля сообщения`,editTemplate:`Изменить шаблон: {{name}}`,titleLabel:`Заголовок`,bodyLabel:`Текст`,titlePlaceholder:`Заголовок уведомления...`,bodyPlaceholder:`Текст уведомления...`,availableVariables:`Доступные переменные`,clickToInsert:`Нажмите, чтобы вставить в позицию курсора в тексте`,livePreview:`Предварительный просмотр`,hide:`Скрыть`,show:`Показать`,loadingPreview:`Загрузка предварительного просмотра...`,enterTemplateContent:`Введите содержимое шаблона для предварительного просмотра`,titlePreview:`Заголовок:`,bodyPreview:`Текст:`,resetToDefault:`Восстановить стандартный шаблон`,titleRequired:`Укажите заголовок`,bodyRequired:`Введите текст уведомления`,notificationLog:`Журнал уведомлений`,showFailedOnly:`Только неудачные`,last24Hours:`Последние 24 часа`,last7Days:`Последние 7 дней`,last30Days:`Последние 30 дней`,last90Days:`Последние 90 дней`,justNow:`Только что`,noFailedNotifications:`Неудачных уведомлений нет`,noNotificationsLogged:`В журнале пока нет уведомлений`,unknownProvider:`Неизвестный провайдер`,logTitle:`Заголовок`,logMessage:`Сообщение`,logError:`Ошибка`,logProvider:`Провайдер: {{type}}`,logTime:`Время: {{time}}`,refresh:`Обновить`,clearOld:`Удалить старые`,statsSummary:`За последние {{days}} дней:`,statsNotifications:`уведомлений`,statsSent:`отправлено: {{count}}`,statsFailed:`ошибок: {{count}}`,eventTypes:{print_start:`Печать началась`,print_complete:`Печать завершена`,print_failed:`Ошибка печати`,print_stopped:`Печать остановлена`,print_progress:`Ход печати`,printer_offline:`Принтер не в сети`,printer_error:`Ошибка принтера`,filament_low:`Заканчивается филамент`,maintenance_due:`Требуется обслуживание`,test:`Тест`},userEmail:{title:`Уведомления`,emailNotifications:`Уведомления по электронной почте`,emailNotificationsDesc:`Получать письма о собственных заданиях печати. Для отправки используются системные параметры SMTP из раздела расширенной аутентификации.`,sendingTo:`Уведомления будут отправляться на адрес`,noEmailWarning:`Для вашей учётной записи не указан адрес электронной почты. Обратитесь к администратору.`,printJobNotifications:`Уведомления о заданиях печати`,printJobNotificationsDesc:`Выберите события, при которых будут отправляться письма о запущенных вами заданиях.`,printJobStarts:`Запуск задания печати`,printJobStartsDesc:`Уведомлять о начале вашего задания печати.`,printJobFinishes:`Завершение задания печати`,printJobFinishesDesc:`Уведомлять об успешном завершении вашего задания печати.`,printErrors:`Ошибки печати`,printErrorsDesc:`Уведомлять, если задание завершилось ошибкой или при печати возникла проблема.`,printJobStops:`Остановка задания печати`,printJobStopsDesc:`Уведомлять об отмене или остановке вашего задания печати.`,saveSuccess:`Настройки уведомлений сохранены.`,saveError:`Не удалось сохранить настройки уведомлений.`}},richTextEditor:{bold:`Полужирный`,italic:`Курсив`,underline:`Подчёркивание`,bulletList:`Маркированный список`,numberedList:`Нумерованный список`,alignLeft:`По левому краю`,alignCenter:`По центру`,alignRight:`По правому краю`,addLink:`Добавить ссылку`,removeLink:`Удалить ссылку`},externalLinks:{title:`Ссылки на боковой панели`,sidebarLayout:`Боковая панель`,sidebarLayoutDescription:`Показывайте или скрывайте встроенные страницы, добавляйте внешние ссылки и перетаскивайте пункты, меняя порядок навигации.`,systemPages:`Страницы Bambuddy`,externalLinks:`Внешние ссылки`,visibleInSidebar:`Показывается на боковой панели`,hiddenFromSidebar:`Скрыто с боковой панели`,requiredInSidebar:`Обязательный пункт боковой панели`,hidePage:`Скрыть страницу`,showPage:`Показать страницу`,settingsCannotBeHidden:`Настройки нельзя скрыть`,noLinksConfigured:`Внешние ссылки не настроены`,deleteLink:`Удалить ссылку`,removeCustomIcon:`Удалить пользовательский значок`,openInNewTab:`Открывать в новой вкладке`,placeholders:{linkName:`Моя ссылка`}},keyboardShortcuts:{title:`Горячие клавиши`,navigation:`Навигация`,archivesSection:`Архив`,kProfilesSection:`K-профили`,generalSection:`Общие`,shortcuts:{goToPrinters:`Перейти к принтерам`,goToArchives:`Перейти в архив`,goToQueue:`Перейти к очереди`,goToStats:`Перейти к статистике`,goToProfiles:`Перейти к облачным профилям`,goToSettings:`Перейти к настройкам`,focusSearch:`Перейти в строку поиска`,openUploadModal:`Открыть окно загрузки`,clearSelection:`Снять выделение / убрать фокус с поля`,contextMenu:`Контекстное меню карточки`,refreshProfiles:`Обновить профили`,newProfile:`Новый профиль`,exitSelectionMode:`Выйти из режима выделения`,showHelp:`Показать эту справку`},footer:`Нажмите Esc или щёлкните снаружи, чтобы закрыть`},notificationLog:{title:`Журнал уведомлений`,events:{printStarted:`Печать началась`,printComplete:`Печать завершена`,printFailed:`Ошибка печати`,printStopped:`Печать остановлена`,progress:`Ход выполнения`,printerOffline:`Принтер не в сети`,printerError:`Ошибка принтера`,lowFilament:`Заканчивается филамент`,maintenanceDue:`Требуется обслуживание`,test:`Тест`},timeAgo:{justNow:`Только что`,minutesAgo:`{{minutes}} мин назад`,hoursAgo:`{{hours}} ч назад`}},restoreBackup:{title:`Восстановление резервной копии`,restoring:`Восстановление...`,restoreComplete:`Восстановление завершено`,restoreFailed:`Ошибка восстановления`,importSettings:`Импортировать настройки из файла резервной копии`,pleaseWait:`Подождите, пока данные восстанавливаются`,clickToSelect:`Нажмите, чтобы выбрать файл резервной копии (.json или .zip)`,howDuplicateHandling:`Как обрабатываются совпадения:`,categories:{printers:`Принтеры`,smartPlugs:`Умные розетки`,notificationProviders:`Провайдеры уведомлений`,filaments:`Филаменты`,archives:`Архив`,pendingUploads:`Ожидающие загрузки`,settingsTemplates:`Настройки и шаблоны`},matchingInfo:{printers:`сопоставляются по серийному номеру`,smartPlugs:`сопоставляются по IP-адресу`,notificationProviders:`сопоставляются по названию`,filaments:`сопоставляются по названию, типу и бренду`,archives:`сопоставляются по хешу содержимого`,pendingUploads:`сопоставляются по имени файла`,settingsTemplates:`всегда перезаписываются`},replaceExisting:`Заменить существующие данные`,keepExisting:`Сохранить существующие данные`,replaceDescription:`Перезаписать уже существующие элементы данными из резервной копии`,keepDescription:`Восстановить только отсутствующие элементы`,caution:`Внимание:`,cautionText:`При перезаписи текущая конфигурация будет заменена данными из резервной копии. В целях безопасности коды доступа к принтерам никогда не перезаписываются.`,itemsRestored:`Восстановлено элементов`,itemsSkipped:`Пропущено элементов`,restored:`Восстановлено`,skipped:`Пропущено (уже существует)`,filesLabel:`Файлы (3MF, миниатюры и т. п.)`,newApiKeysGenerated:`Созданы новые ключи API`,newApiKeysWarning:`Эти ключи показываются только один раз. Скопируйте их сейчас!`,processingBackup:`Обработка резервной копии...`,noDataFound:`В резервной копии не найдено данных для восстановления.`,failedToRestore:`Не удалось восстановить резервную копию. Проверьте формат файла.`},backupExport:{title:`Экспорт резервной копии`,selectData:`Выберите данные для включения`,selectAll:`Выбрать всё`,selectNone:`Снять выделение`,categoryDescriptions:{settings:`Язык, тема и настройки обновлений`,notifications:`ntfy, Pushover, Discord и другие`,templates:`Пользовательские шаблоны сообщений`,smartPlugs:`Конфигурация розеток Tasmota`,externalLinks:`Ссылки на внешние сервисы в боковой панели`,printers:`Сведения о принтерах (без кодов доступа)`,plateDetection:`Эталонные изображения пустых пластин`,filaments:`Типы и стоимость филамента`,maintenance:`Пользовательские графики обслуживания`,archives:`Все данные печати и файлы (3MF, миниатюры, фотографии)`,projects:`Проекты, позиции спецификаций и вложения`,pendingUploads:`Загрузки виртуальных принтеров, ожидающие проверки`,apiKeys:`Ключи API вебхуков (при импорте создаются новые)`},requiresPrinters:`Необходимо выбрать раздел «Принтеры»`,zipFileWarning:`Будет создан ZIP-файл.`,zipFileDescription:`В него войдут все файлы 3MF, миниатюры, таймлапсы и фотографии. Операция может занять некоторое время, а файл — получиться большим.`,includeAccessCodes:`Включить коды доступа`,includeAccessCodesDescription:`Для переноса на другой компьютер`,includeAccessCodesWarning:`Коды доступа попадут в файл открытым текстом. Храните резервную копию в безопасном месте!`,categoriesSelected:`Выбрано категорий: {{selectedCount}}`},pendingUploads:{placeholders:{notes:`Добавьте примечания об этой печати...`},discardUpload:`Отклонить загрузку`,archiveAllUploads:`Добавить все загрузки в архив`,discardAllUploads:`Отклонить все загрузки`,archive:`В архив`,timeAgo:{justNow:`Только что`,minutesAgo:`{{minutes}} мин назад`,hoursAgo:`{{hours}} ч назад`,daysAgo:`{{days}} дн. назад`}},apiBrowser:{placeholders:{requestBody:`Тело запроса JSON...`,searchEndpoints:`Поиск конечных точек...`}},configureAmsSlot:{title:`Настройка слота AMS`,slotConfigured:`Слот настроен!`,configuringSlot:`Настраивается слот:`,slotLabel:`{{ams}}, слот {{slot}}`,searchPresets:`Поиск профилей...`,colorPlaceholder:`Название или HEX-код цвета (например: brown, FF8800)`,clearCustomColor:`Очистить пользовательский цвет`,noCloudPresets:`Облачных профилей нет. Войдите в Bambu Cloud для синхронизации.`,noPresetsAvailable:`Нет доступных профилей. Войдите в Bambu Cloud или импортируйте локальные профили.`,noMatchingPresets:`Подходящие профили не найдены.`,custom:`Пользовательский`,builtin:`Встроенный`,orcaCloud:`Orca Cloud`,bambuCloud:`Bambu Cloud`,settingsSentToPrinter:`Настройки отправлены на принтер`,filamentProfile:`Профиль филамента`,kProfileLabel:`K-профиль (Pressure Advance)`,filteringFor:`Фильтр по материалу: {{material}}`,noKProfile:`Без K-профиля (стандартное значение 0,020)`,noMatchingKProfiles:`Подходящие K-профили не найдены. Будет использовано стандартное значение K=0,020.`,otherKProfiles:`Другие K-профили на этом принтере`,selectFilamentFirst:`Сначала выберите профиль филамента`,kFromCalibration:`K={{value}} из калибровки принтера`,customColorLabel:`Пользовательский цвет (необязательно)`,presetColors:`Цвета {{name}}:`,showLessColors:`Показать меньше цветов`,showMoreColors:`Показать больше цветов`,clear:`Очистить`,hexLabel:`HEX: #{{hex}}`,resetting:`Сброс...`,resetSlot:`Сбросить слот`,cancel:`Отмена`,configuring:`Настройка...`,configureSlot:`Настроить слот`},githubBackup:{title:`Резервное копирование в Git`,history:`История`,downloadBackup:`Скачать резервную копию`,restoreBackup:`Восстановить резервную копию`,noBackupsYet:`Резервных копий пока нет`},emailSettings:{placeholders:{fromName:`BamBuddy`}},tagManagement:{searchTags:`Поиск меток...`,renameTag:`Переименовать метку`,deleteTag:`Удалить метку`},notificationTemplates:{placeholders:{title:`Заголовок уведомления...`,body:`Текст уведомления...`}},batchTag:{placeholders:{newTag:`Введите новую метку...`}},photoGallery:{deletePhoto:`Удалить фотографию`},filamentHoverCard:{copySpoolUuid:`Скопировать UUID катушки`},kProfilesView:{hasNote:`Есть примечание`,copyProfile:`Копировать профиль`},layout:{openMenu:`Открыть меню`,noPermissionSystemInfo:`У вас нет разрешения на просмотр системной информации`},dashboard:{dragToReorder:`Перетащите, чтобы изменить порядок`,hideWidget:`Скрыть виджет`},notificationProviderCard:{deleteNotificationProvider:`Удалить провайдера уведомлений`},fileManagerModal:{closeFileManager:`Закрыть файловый менеджер`,sortFiles:`Сортировать файлы`,goToParentFolder:`Перейти в родительскую папку`,threeView:`Просмотр 3D`},embeddedCameraViewer:{refreshStream:`Обновить поток`,close:`Закрыть`,zoomOut:`Уменьшить`,resetZoom:`Сбросить масштаб`,zoomIn:`Увеличить`,dragToResize:`Перетащите, чтобы изменить размер`},timelapseViewer:{skipBack5s:`Назад на 5 с`,skipForward5s:`Вперёд на 5 с`},notificationProviders:{descriptions:{email:`Уведомления по электронной почте через SMTP`,telegram:`Уведомления через Telegram-бота`,discord:`Отправка в канал Discord через вебхук`,ntfy:`Бесплатные push-уведомления с возможностью самостоятельного размещения сервера`,pushover:`Простые и надёжные push-уведомления`,callmebot:`Бесплатные уведомления WhatsApp через CallMeBot`,webhook:`Обычный HTTP POST на любой URL`}},logViewer:{searchPlaceholder:`Поиск по сообщению или имени логгера...`,noLogEntries:`Записи журнала не найдены`},switchbarPopover:{noSwitchesInSwitchbar:`На панели переключателей нет устройств`},projectPageModal:{placeholders:{title:`Название`,designer:`Автор`,license:`Лицензия`,description:`Введите описание...`,profileTitle:`Название профиля`,profileDescription:`Описание профиля...`}},spoolmanSettings:{},time:{unknown:`—`,waiting:`Ожидание`,justNow:`Только что`,now:`Сейчас`,minsAgo:`{{count}} мин назад`,inMins:`через {{count}} мин`,hoursAgo:`{{count}} ч назад`,inHours:`через {{count}} ч`,daysAgo:`{{count}} дн. назад`,inDays:`через {{count}} дн.`},spoolbuddy:{nav:{dashboard:`Панель`,ams:`AMS`,inventory:`Катушки`,writeTag:`Запись метки`,settings:`Настройки`},status:{nfcReady:`NFC готов`,nfcOff:`NFC выключен`,offline:`Не в сети`,online:`В сети`,noPrinters:`Нет принтеров`,deviceOffline:`Устройство не в сети`,waitingConnection:`Ожидание подключения устройства...`,systemReady:`Система готова`,status:`Состояние`},dashboard:{readyToScan:`Готово к сканированию`,idleMessage:`Поставьте катушку на весы для идентификации`,nfcHint:`Метка NFC будет считана автоматически`,device:`Устройство`,syncWeight:`Синхронизировать массу`,weightSynced:`Синхронизировано!`,unknownTag:`Неизвестная метка`,newTag:`Обнаружена новая метка`,onScale:`на весах`,linkSpool:`Связать с катушкой`,linkTagTitle:`Связать метку с катушкой`,linkTag:`Связать метку`,selectSpool:`Выберите катушку, с которой нужно связать эту метку:`,noUntagged:`Катушки без меток не найдены`,tagDetected:`Метка обнаружена`,noTag:`Метка отсутствует`,tagId:`Метка`,grossWeight:`Масса брутто`,spoolSize:`Размер катушки`,close:`Закрыть`,currentSpool:`Текущая катушка`,plateReady:`Пластина готова: {{name}}`,plateReadyLabel:`Пластины, готовые к очистке`,plateClearAction:`Очищено`,plateClearedToast:`Пластина отмечена как очищенная`,plateClearFailed:`Не удалось отметить пластину как очищенную`},modal:{spoolDetected:`Катушка обнаружена`,assignToAms:`Назначить в AMS`,syncWeight:`Синхронизировать массу`,weightSynced:`Синхронизировано!`,syncing:`Синхронизация...`,newTagDetected:`Обнаружена новая метка`,addToInventory:`Добавить в учёт`,assignToAmsTitle:`Назначить в AMS`,selectSlot:`Выберите слот`,assign:`Назначить`,assigning:`Назначение...`,assignSuccess:`Назначено!`,assignPendingInsert:`Назначено. Слот будет настроен после установки катушки.`,assignError:`Не удалось назначить катушку. Повторите попытку.`,noPrinterSelected:`Выберите принтер...`,noAmsDetected:`На этом принтере AMS не обнаружена`,slot:`Слот`},weight:{noReading:`Нет показаний`,stable:`Стабильно`,measuring:`Измерение...`,tare:`Тарировать`,calibrate:`Калибровать`},spool:{remaining:`Остаток`,material:`Материал`,brand:`Бренд`,color:`Цвет`,coreWeight:`Сердечник`,labelWeight:`По этикетке`,scaleWeight:`По весам`,netWeight:`Нетто`,lastUsed:`Последнее использование`},ams:{noData:`AMS не обнаружена`,connectAms:`Подключите AMS, чтобы увидеть слоты филамента`,noPrinter:`Принтер не выбран`,selectPrinter:`Выберите принтер на верхней панели`,printerDisconnected:`Принтер отключён`,humidity:`Влажность`,level:`Уровень`,active:`Активен`,slot:`Слот`,empty:`Пусто`},inventory:{search:`Поиск катушек...`,empty:`В учёте нет катушек`,noResults:`Подходящие катушки не найдены`,spools:`катушек`,addSpool:`Добавить катушку`},settings:{tabDevice:`Устройство`,tabDisplay:`Экран`,tabScale:`Весы`,tabUpdates:`Обновления`,nfcReader:`Считыватель NFC`,type:`Тип`,connection:`Подключение`,notConnected:`Н/Д`,deviceInfo:`Сведения об устройстве`,hostname:`Хост`,uptime:`Время работы`,systemConfig:`Бэкенд и авторизация`,backendUrl:`URL бэкенда Bambuddy`,apiToken:`Токен API`,apiTokenPlaceholder:`Введите токен API`,saveConfig:`Сохранить конфигурацию`,systemQueued:`Конфигурация поставлена в очередь.`,nfcDiagnostic:`Диагностика NFC`,scaleDiagnostic:`Диагностика весов`,readTagDiagnostic:`Диагностика чтения метки`,testNfc:`Проверить считыватель`,testScale:`Проверить точность`,testReadTag:`Считать метку`,systemFieldsRequired:`Необходимо указать URL бэкенда.`,brightness:`Яркость`,saved:`Сохранено`,noBacklight:`Подсветка DSI не обнаружена. Для управления яркостью требуется дисплей DSI.`,screenBlank:`Тайм-аут отключения экрана`,screenBlankDesc:`Экран выключается при бездействии. Коснитесь его для пробуждения.`,displayNote:`Яркость регулируется программным фильтром.`,scaleCalibration:`Калибровка весов`,currentWeight:`Текущая масса`,tareOffset:`Тара`,calFactor:`Коэффициент`,knownWeight:`Эталонная масса`,calStep1:`Уберите всё с весов и нажмите «Установить ноль».`,calStep2:`Положите на весы груз известной массы.`,setZero:`Установить ноль`,calibrateNow:`Калибровать`,calibrated:`Откалибровано`,tareSet:`Команда тарирования отправлена. Ожидание устройства...`,tareComplete:`Тарирование завершено!`,tareTimedOut:`Истекло время ожидания тарирования — демон SpoolBuddy запущен?`,tareFailed:`Не удалось отправить команду тарирования`,zeroSet:`Нулевая точка установлена. Положите на весы груз известной массы.`,calibrationDone:`Калибровка завершена!`,calibrationFailed:`Ошибка калибровки`,lastCalibrated:`Последняя калибровка`,stable:`Стабильно`,settling:`Стабилизация...`,firmware:`Прошивка`,scale:`Весы`,noDevice:`Устройство SpoolBuddy не найдено`,daemonVersion:`Версия демона`,currentVersion:`Текущая`,versionPending:`Ожидание демона...`,checking:`Проверка...`,checkUpdates:`Проверить обновления`,updateAvailable:`Доступно обновление`,updateInstructions:`Обновление по SSH: запустите установочный скрипт SpoolBuddy.`,upToDate:`Установлена актуальная версия`,includeBeta:`Включать бета-версии`},writeTag:{tabExisting:`Существующая катушка`,tabNew:`Новая катушка`,tabReplace:`Заменить метку`,searchPlaceholder:`Поиск по материалу, цвету или бренду...`,noUntaggedSpools:`Нет катушек без меток`,noTaggedSpools:`Нет катушек с метками`,selectSpool:`Выберите катушку, затем положите чистую метку NTAG на считыватель`,placeTag:`Положите метку NTAG на считыватель`,tagReady:`Метка обнаружена — можно записывать`,writeTag:`Записать метку`,replaceTag:`Заменить метку`,writing:`Запись метки...`,waiting:`Ожидание SpoolBuddy...`,writeSuccess:`Метка успешно записана!`,writeFailed:`Ошибка записи`,queueFailed:`Не удалось поставить команду записи в очередь`,tryAgain:`Повторить`,cancel:`Отмена`,replaceWarning:`Старая метка будет отвязана и заменена новой.`,deviceOffline:`SpoolBuddy не в сети`,material:`Материал`,colorName:`Название цвета`,color:`Цвет`,brand:`Бренд`,weight:`Масса (г)`,createSpool:`Создать катушку`,creating:`Создание...`,spoolCreated:`Катушка создана! Можно записывать метку.`,createFailed:`Не удалось создать катушку`,incompleteDataWarning:`Метка записана с неполными данными Spoolman`},quickMenu:{printerPower:`Питание принтера`,systemControls:`Система`,restartDaemon:`Перезапустить демон`,restartBrowser:`Перезапустить браузер`,reboot:`Перезагрузить`,shutdown:`Выключить`,swipeToClose:`Проведите вниз, чтобы закрыть`,confirmTitle:`Подтверждение`,confirmShutdown:`Выключить SpoolBuddy? Для повторного включения потребуется физический доступ.`,confirmReboot:`Перезагрузить SpoolBuddy?`,confirmRestartDaemon:`Перезапустить демон SpoolBuddy? NFC и весы временно будут недоступны.`,confirmRestartBrowser:`Перезапустить браузер киоска? Экран ненадолго погаснет.`,confirm:`Подтвердить`,confirmPlugOn:`Включить {{name}}?`,confirmPlugOff:`Выключить {{name}}?`,turnOn:`Включить`,turnOff:`Выключить`}},diagnostic:{modalTitle:`Диагностика подключения — {{name}}`,running:`Выполняется диагностика...`,runningElapsed:`Выполняется диагностика... ({{elapsed}} с)`,waitingForReportHint:`Ожидание публикации отчёта о состоянии принтера — это может занять до {{max}} секунд.`,runFailed:`Не удалось выполнить диагностику: {{error}}`,retry:`Запустить снова`,runButton:`Запустить диагностику`,sectionTitle:`Диагностика подключения`,sectionDescription:`Проверьте, почему принтер не подключается или не печатает: доступность портов, режим разработчика LAN, сетевой режим Docker и учётные данные.`,noPrinters:`Принтеры не настроены.`,overall:{ok:`Проблем не обнаружено — подключение к принтеру исправно.`,warnings:`Принтер должен работать, но некоторые пункты требуют внимания.`,problems:`Обнаружены проблемы, объясняющие, почему принтер не подключается или не печатает.`},check:{port_mqtt:{title:`Порт управления (MQTT 8883)`,pass:`Доступен — принтер принимает управляющие подключения.`,fail:`Порт 8883 недоступен. Принтер выключен, имеет другой IP-адрес либо подключение блокирует межсетевой экран. Проверьте IP-адрес принтера и доступность порта 8883.`},port_ftps:{title:`Порт передачи файлов (FTPS 990)`,pass:`Доступен — отправка файлов печати будет работать.`,warn:`Порт 990 недоступен. Мониторинг может работать, но отправка заданий на принтер завершится ошибкой. Убедитесь, что порт 990 не заблокирован.`},external_storage:{title:`Сохранять отправленные файлы во внешнем хранилище (шаг 4 установки)`,pass:`Принтер сообщает, что параметр включён: отправленные файлы будут сохраняться на SD-карте, а в архиве появятся миниатюры и метаданные слайсера.`,fail:`Принтер сообщает, что параметр выключен. Включите «Сохранять отправленные файлы во внешнем хранилище»: в новых прошивках (P2S 01.02 / Bambu Studio 2.6+) переключатель находится в настройках печати принтера, в старых — на вкладке «Устройство» Bambu Studio / OrcaSlicer. Без этого у всех архивных заданий не будет миниатюр и метаданных слайсера.`,skip:`Не проверено — требуется активное подключение MQTT. В старых версиях слайсеров этот параметр существует только в слайсере и принтер его не сообщает, поэтому проверка может пройти даже при выключенном параметре. Проверьте шаг 4 установки вручную.`,skip_unsupported_model:`В этой модели есть слот SD-карты, но включить соответствующую функцию невозможно: текущая прошивка серии P1 не предоставляет переключатель в Bambu Studio, а у принтера нет экрана. Исправлять здесь нечего. Пока Bambu Lab не добавит поддержку в прошивку, архивные задания могут сохраняться без миниатюр и метаданных слайсера.`},port_rtsps:{title:`Порт камеры ({{protocol}} {{port}})`,pass:`Доступен — видеопоток камеры будет работать.`,warn:`Порт {{port}} недоступен. Просмотр камеры в реальном времени работать не будет. На печать это не влияет.`},network_mode:{title:`Сетевой режим Docker`,pass:`Используется сетевой режим host.`,warn:`Bambuddy запущен в Docker с сетью bridge. Для обнаружения принтеров и виртуального принтера требуется режим host — пересоздайте контейнер с параметром «network_mode: host».`,skip:`Bambuddy запущен не в Docker — проверка неприменима.`},subnet:{title:`Подсеть`,pass:`Принтер и Bambuddy находятся в одной подсети.`,warn:`Принтер ({{printer_ip}}) и Bambuddy ({{host_ip}}) находятся в разных подсетях. Без настроенной маршрутизации между подсетями они могут быть недоступны друг для друга.`,skip:`Не удалось определить подсеть — проверка пропущена.`},mqtt_auth:{title:`Учётные данные принтера`,pass:`Принтер принял подключение.`,fail:`Принтер доступен, но Bambuddy к нему не подключён. Скорее всего, неверны код доступа или серийный номер — код доступа изменяется при каждом переключении режима «Только LAN» или режима разработчика, поэтому снова скопируйте его с экрана принтера. Так же выглядит принтер, который перезагружается или уже исчерпал лимит одновременных подключений.`,fail_auth_rejected:`Принтер отклонил учётные данные Bambuddy. Код доступа или серийный номер неверны — код доступа изменяется при каждом переключении режима «Только LAN» или режима разработчика. Снова скопируйте его с экрана принтера и сохраните в настройках принтера.`,skip:`Не проверено — принтер недоступен.`},developer_mode:{title:`Режим разработчика LAN`,pass:`Режим разработчика включён.`,fail:`Режим разработчика на принтере ВЫКЛЮЧЕН. Включите его в настройках LAN принтера и подтвердите кнопкой OK. Без него задания печати не запускаются.`,skip:`Не удалось проверить — требуется активное подключение к принтеру.`},printer_publishing:{title:`Принтер публикует состояние`,pass:`Принтер публикует обновления состояния — AMS, филаменты и K-профили будут корректно передаваться в слайсер.`,fail:`MQTT-брокер принял подключение, но принтер не опубликовал ни одного отчёта о состоянии. Почти всегда причина в неверном регистре или ошибке в серийном номере: тема device//report чувствительна к регистру. Сверьте серийный номер в настройках принтера с номером на его экране.`,skip:`Не удалось проверить — требуется активное подключение к принтеру.`}}},systemHealth:{sectionTitle:`Состояние системы`,sectionDescription:`Проверяет последние журналы на известные проблемы, которые обычно можно исправить самостоятельно до обращения в поддержку.`,rescan:`Проверить снова`,clean:`В последних {{times}} записях журнала известные проблемы не найдены.`,logUnavailable:`Запись журналов в файл отключена, поэтому выполнить проверку невозможно. Включите файловое журналирование.`,learnMore:`Как исправить`,fixLabel:`Исправление:`,occurrences:`Обнаружено {{times}} раз; последний раз — {{lastSeen}}`,category:{layer8:`Можно исправить самостоятельно`,environment:`Окружение`,bug:`Сообщите об ошибке`},signature:{"ftp-auth-rejected":{name:`Принтер отклонил код доступа`,cause:`Принтер отклонил вход в службу передачи файлов. Код доступа неверен либо изменился после переключения режима разработчика.`,fix:`Снова скопируйте код доступа с экрана принтера в настройках LAN и обновите его в настройках принтера Bambuddy.`},"ftp-connection-timeout":{name:`Истекло время подключения к службе передачи файлов`,cause:`Bambuddy не смог подключиться к порту передачи файлов принтера (FTPS 990). Порт заблокирован, принтер выключен либо находится в другой подсети.`,fix:`Убедитесь, что порт 990 между Bambuddy и принтером не блокируется и оба устройства находятся в доступных друг другу сетях.`},"ftp-ssl-error":{name:`Ошибка защищённого соединения с файловой службой`,cause:`Не удалось выполнить TLS-рукопожатие с сервером передачи файлов принтера. Частые причины — межсетевой экран или устаревшая прошивка принтера.`,fix:`Обновите прошивку принтера и убедитесь, что межсетевой экран или прокси не перехватывает соединение на порту 990.`},"mqtt-connection-flapping":{name:`Подключение к принтеру постоянно обрывается`,cause:`Управляющее соединение MQTT 8883 постоянно разрывается и восстанавливается. Обычно причина в нестабильной сети или частично заблокированном порте.`,fix:`Проверьте уровень Wi‑Fi у принтера, по возможности используйте проводное подключение и убедитесь в стабильной доступности порта 8883.`},"camera-connection-refused":{name:`Видеопоток камеры недоступен`,cause:`Камера недоступна по порту RTSPS 322. Порт заблокирован либо на принтере выключены камера или просмотр по LAN.`,fix:`Включите камеру и просмотр по LAN на принтере и убедитесь, что порт 322 не заблокирован. На печать это не влияет.`},"database-locked":{name:`Конфликт записи в базу данных`,cause:`Под нагрузкой SQLite выдаёт ошибки «database is locked». Это часто происходит при одновременной работе с несколькими принтерами.`,fix:`Переведите Bambuddy на внешнюю базу PostgreSQL. См. руководство по PostgreSQL в документации.`}}},vpDiagnostic:{title:`Проверка настройки — {{name}}`,runButton:`Запустить проверку`,running:`Выполняется проверка настройки...`,runFailed:`Не удалось выполнить проверку: {{error}}`,retry:`Запустить снова`,overall:{ok:`Все проверки пройдены — виртуальный принтер настроен правильно.`,warnings:`Виртуальный принтер должен работать, но некоторые пункты требуют внимания.`,problems:`Обнаружены проблемы, из-за которых слайсер не видит или не может использовать виртуальный принтер.`},check:{enabled:{title:`Виртуальный принтер включён`,fail:`Виртуальный принтер выключен. Включите его, чтобы он обнаруживался в сети.`},running:{title:`Службы запущены`,fail:`Виртуальный принтер включён, но его службы не работают. Проверьте журнал Bambuddy: обычно запуску мешает конфликт IP-адреса привязки или ошибка прав доступа.`},bind_interface:{title:`Сетевой интерфейс привязки`,fail:`Интерфейс привязки не задан или больше не существует на этом хосте. Выберите актуальный интерфейс в списке «Интерфейс привязки».`},access_code:{title:`Код доступа задан`,fail:`Код доступа не задан. В слайсере необходимо указать тот же восьмизначный код, который задан здесь.`},target_printer:{title:`Целевой принтер`,fail:`Целевой принтер не выбран. Для режима прокси необходимо указать реальный принтер.`,warn:`Целевой принтер сейчас не в сети. Перенаправление возобновится после его подключения.`},port_ftps:{title:`Служба загрузки файлов (порт {{port}})`,fail:`На порту {{port}} выбранного IP-адреса никто не слушает, поэтому слайсер не сможет загружать файлы. Обычно причина в конфликте порта на этом интерфейсе.`},port_mqtt:{title:`Служба управления (порт {{port}})`,fail:`На порту {{port}} выбранного IP-адреса никто не слушает, поэтому слайсер не сможет подключиться и отображать состояние.`},port_bind:{title:`Служба обнаружения (порт {{port}})`,fail:`На порту {{port}} выбранного IP-адреса никто не слушает, поэтому сетевое обнаружение слайсером не работает.`},certificate:{title:`Сертификат TLS`,pass:`Сертификат готов. Убедитесь, что сертификат центра сертификации Bambuddy, указанный выше, импортирован в доверенное хранилище слайсера.`,fail:`Сертификат TLS для этого виртуального принтера отсутствует. Проверьте права записи в каталог данных Bambuddy.`}}},bugReport:{title:`Сообщить об ошибке`,description:`Описание`,descriptionPlaceholder:`Что пошло не так? Опишите проблему...`,email:`Электронная почта (необязательно)`,emailPlaceholder:`your@email.com`,emailPrivacy:`Указанный адрес будет добавлен в сворачиваемый раздел задачи GitHub, чтобы сопровождающий мог с вами связаться.`,screenshot:`Снимок экрана`,uploadOrPaste:`Загрузите, вставьте или перетащите изображение`,dataCollectedSummary:`Какие данные включаются в отчёт?`,dataIncluded:`Включаются:`,dataIncludedList:`Версия приложения, ОС, архитектура, версия Python, статистика базы данных (только количества), модели принтеров, количество сопел, версии прошивок, состояние подключений, состояние интеграций (Spoolman, MQTT, HA), неконфиденциальные настройки, количество сетевых интерфейсов, сведения о Docker и версии зависимостей.`,dataNeverIncluded:`Никогда не включаются:`,dataNeverIncludedList:`Имена принтеров, серийные номера, коды доступа, пароли, IP-адреса, адреса электронной почты, ключи API, токены, URL вебхуков, имена хостов и пользователей.`,submit:`Отправить`,startLogging:`Начать отладочную запись`,stepEnableLogging:`Отладочная запись включена`,stepReproduce:`Теперь воспроизведите проблему`,stepStopLogging:`Остановить и отправить отчёт`,stopAndSubmit:`Остановить и отправить`,maxDuration:`Автоматическая остановка через {{minutes}} мин`,stoppingLogs:`Сбор журналов и отправка...`,submitting:`Отправка отчёта об ошибке...`,submittingStepConnection:`Проверка подключений к принтерам`,submittingStepVirtualPrinters:`Проверка настройки виртуальных принтеров`,submittingStepLogScan:`Поиск известных проблем в последних журналах`,submittingStepSubmit:`Отправка отчёта в GitHub`,submitSuccess:`Отчёт об ошибке успешно отправлен!`,submitFailed:`Не удалось отправить отчёт об ошибке`,diagnosticChecking:`Проверка подключений к принтерам...`,diagnosticHealthy:`Проверка подключения пройдена — проблем с принтерами не обнаружено.`,diagnosticSummary:`Проблемы с подключением обнаружены у {{problems}} из {{total}} принтеров`,diagnosticIntro:`У одного или нескольких принтеров есть проблема подключения, которая может быть причиной сбоя. Разверните сведения о принтере ниже и посмотрите способ исправления — возможно, отчёт об ошибке не потребуется. При необходимости его всё равно можно отправить ниже.`,logHealthSummary:`В журналах найдены известные проблемы`,logHealthIntro:`Последние записи журнала совпадают с известными проблемами. Посмотрите способы исправления ниже — возможно, отчёт об ошибке не потребуется. При необходимости его всё равно можно отправить.`,thankYou:`Спасибо!`,submitted:`Отчёт об ошибке отправлен.`,viewIssue:`Открыть задачу`,unexpectedError:`Произошла непредвиденная ошибка`},failureDetection:{title:`Обнаружение сбоев с помощью ИИ`,description:`Контролируйте печать через собственный сервер Obico ML API и автоматически реагируйте на обнаруженные сбои.`,mlUrl:`URL Obico ML API`,mlUrlHint:`Базовый URL собственного контейнера Obico ml_api, например http://192.168.1.10:3333.`,mlToken:`Токен ML API (необязательно)`,mlTokenPlaceholder:`Оставьте пустым, если сервер работает без ML_API_TOKEN`,mlTokenHint:`Должен совпадать с переменной окружения ML_API_TOKEN вашего контейнера Obico ml_api. Оставьте пустым, если контейнер работает без токена.`,test:`Проверить`,testSuccess:`ML API доступен и работает.`,testSuccessTokenUnknown:`ML API доступен и работает. Проверить токен не удалось.`,testFailed:`Не удалось подключиться к ML API.`,sensitivity:`Чувствительность`,sensitivityLow:`Низкая (меньше ложных срабатываний)`,sensitivityMedium:`Средняя (сбалансированная)`,sensitivityHigh:`Высокая (раннее обнаружение, больше ложных срабатываний)`,sensitivityHint:`Определяет пороги уверенности, при которых создаются предупреждения и фиксируются сбои.`,action:`Действие при обнаружении сбоя`,actionNotify:`Только уведомить`,actionPause:`Приостановить печать`,actionPauseOff:`Приостановить печать и отключить питание`,pollInterval:`Интервал проверки (секунды)`,pollIntervalHint:`Как часто проверять каждый принтер во время печати. Минимум 5 с, максимум 120 с.`,externalUrlMissing:`Внешний URL не задан.`,externalUrlHint:`ML API получает снимок камеры по URL. Укажите внешний URL в общих настройках, чтобы контейнер ML API мог обращаться к Bambuddy.`,perPrinterTitle:`Контролируемые принтеры`,perPrinterHint:`Выберите принтеры, за которыми будет следить служба обнаружения.`,monitorAll:`Контролировать все подключённые принтеры`,statusTitle:`Состояние`,serviceRunning:`Служба работает`,thresholds:`Низкий / высокий порог`,activePrinters:`Активные задания`,noActivePrints:`Сейчас ничего не печатается.`,historyTitle:`Последние обнаружения`,noHistory:`Обнаружений пока нет.`},makerworld:{title:`MakerWorld`,description:`Вставьте URL модели MakerWorld, чтобы импортировать и напечатать её прямо из Bambuddy — без перехода в приложение Bambu Handy.`,pasteUrlHeader:`Импорт из MakerWorld`,pasteUrlPlaceholder:`https://makerworld.com/en/models/… или любая ссылка MakerWorld`,resolveButton:`Получить данные`,signInRequiredTitle:`Для загрузки требуется вход в Bambu Cloud`,signInRequiredBody:`Просматривать сведения о модели можно анонимно, но для загрузки файлов 3MF MakerWorld требует учётную запись Bambu Cloud.`,signInExpiredTitle:`Срок авторизации в Bambu Cloud истёк`,signInExpiredBody:`Вы по-прежнему авторизованы в Bambuddy, но Bambu Lab перестал принимать сохранённый токен, поэтому загрузки завершатся ошибкой. Выполните вход в Bambu Cloud снова.`,openCloudSettings:`Открыть настройки облака`,untitledModel:`Модель без названия`,byCreator:`Автор: {{name}}`,downloadsCount:`Загрузок: {{count}}`,licensePrefix:`Лицензия`,alreadyImported:`Уже в библиотеке`,openOnMakerworld:`Открыть на MakerWorld`,alreadyInLibrary:`Эта модель уже есть в библиотеке — найдите её в разделе «Файлы → MakerWorld».`,importSuccess:`Импортирован файл {{filename}} — сохранён в «Файлы → MakerWorld».`,platesHeader:`Пластины ({{count}})`,plateDefaultName:`Пластина {{n}}`,materialCount:`Филаментов: {{count}}`,amsRequired:`Требуется AMS`,slicedFor:`Нарезано для {{printer}}`,alsoCompatible:`Также отмечено как совместимое: {{printers}}`,importToLibrary:`Сохранить`,sliceIn:`Сохранить и нарезать в {{slicer}}`,disclaimer:`Интеграция с MakerWorld использует документированные сообществом конечные точки API. Bambuddy не связан с MakerWorld или Bambu Lab и не одобрен ими.`,lastImportSuccess:`Импортировано в библиотеку`,lastImportAlreadyInLibrary:`Уже в библиотеке`,viewInLibrary:`Открыть в файловом менеджере`,openInBambuStudio:`Открыть в Bambu Studio`,openInOrcaSlicer:`Открыть в OrcaSlicer`,importTo:`Импортировать в файловый менеджер`,recentImportsHeader:`Недавние импорты`,phaseResolving:`Получение данных`,phaseDownloading:`Загрузка`,folderAuto:`MakerWorld (по умолчанию)`,importAll:`Импортировать всё`,importAllProgress:`Импорт {{current}} из {{total}}`,openGallery:`Открыть галерею изображений`,galleryPrev:`Предыдущее изображение`,galleryNext:`Следующее изображение`,deleteImport:`Удалить из библиотеки`,importDeleting:`Удаление…`,importDeleted:`Удалено из библиотеки`,confirmDelete:`Удалить {{filename}} из библиотеки? Локальный файл будет удалён, но пластину можно снова импортировать из MakerWorld.`,errors:{resolveFailed:`Не удалось обработать эту ссылку MakerWorld.`,downloadFailed:`Ошибка загрузки. Повторите попытку.`,deleteFailed:`Не удалось удалить файл из библиотеки.`}},gcodeViewer:{back:`Назад`,backToArchives:`Вернуться в архив печати`,backToFiles:`Вернуться в файловый менеджер`},libraryTrash:{title:`Корзина`,headerButton:`Корзина`,headerTooltip:`Просмотреть файлы, перемещённые в корзину`,backToFiles:`Вернуться к файлам`,subtitleAdmin:`Удалённые файлы хранятся здесь {{days}} дней, затем удаляются автоматически. Показаны файлы всех пользователей.`,subtitleUser:`Удалённые файлы хранятся здесь {{days}} дней, затем удаляются автоматически.`,loading:`Загрузка корзины…`,loadError:`Не удалось загрузить корзину.`,empty:`Корзина пуста.`,summary:`{{count}} файлов · {{size}}`,emptyTrash:`Очистить корзину`,restore:`Восстановить`,purgeNow:`Удалить сейчас`,autoPurgeIn:`Автоудаление через {{when}}`,days:`дней`,retentionLabel:`Автоудаление через`,selectAll:`Выбрать всё`,selectOne:`Выбрать {{filename}}`,selectionCount:`Выбрано: {{count}}`,bulkRestore:`Восстановить выбранные`,bulkPurge:`Удалить выбранные`,col:{filename:`Файл`,folder:`Папка`,size:`Размер`,deleted:`Перемещён в корзину`,autoPurge:`Автоудаление`,owner:`Владелец`,actions:`Действия`},confirm:{purgeTitle:`Удалить навсегда?`,purgeBody:`Файл {{filename}} будет удалён с диска без возможности восстановления.`,emptyTitle:`Очистить корзину?`,emptyBody:`Все файлы ({{count}}) будут удалены с диска. Отменить это действие нельзя.`,bulkPurgeTitle:`Удалить выбранные файлы навсегда?`,bulkPurgeBody:`Выбранные файлы ({{count}}) будут удалены с диска без возможности восстановления.`,cta:`Удалить навсегда`},toast:{restored:`Файл восстановлен.`,restoreFailed:`Не удалось восстановить файл.`,purged:`Файл удалён навсегда.`,purgeFailed:`Не удалось удалить файл.`,emptied:`Из корзины удалено файлов: {{count}}.`,emptyFailed:`Не удалось очистить корзину.`,retentionSaved:`Срок автоудаления: {{days}} дней.`,retentionFailed:`Не удалось сохранить срок хранения.`,bulkRestored:`Восстановлено файлов: {{count}}.`,bulkPurged:`Удалено файлов: {{count}}.`}},libraryPurge:{title:`Очистить старые файлы`,headerButton:`Очистить старые`,headerTooltip:`Массово переместить старые файлы в корзину`,description:`За один проход убирает старые файлы из библиотеки. Для печатавшихся файлов возраст считается от даты последней печати, для ни разу не печатавшихся — от даты загрузки.`,ageLabel:`Переместить файлы старше`,days:`дней`,includeNeverPrinted:`Включить файлы, которые ни разу не печатались`,effectsTitle:`Что произойдёт после нажатия «Очистить»`,effect1:`Подходящие файлы будут перемещены в корзину, но пока не удалены с диска.`,effect2:`Их можно восстановить из корзины до окончания срока хранения.`,effect3:`После окончания срока хранения очистка корзины окончательно удалит их с диска.`,effect4:`Файлы во внешних подключённых папках пропускаются: Bambuddy не удаляет чужие данные.`,previewLoading:`Подсчёт подходящих файлов…`,previewFailed:`Не удалось выполнить предварительный расчёт.`,previewSummary:`В корзину будет перемещено: {{count}} файлов · {{size}}`,andMore:`…и ещё {{count}}`,warning:`Файлы в корзине продолжают занимать место до окончания срока хранения. Чтобы освободить диск сразу, после операции очистите корзину.`,confirmCta:`Переместить в корзину: {{count}}`,purging:`Перемещение в корзину…`,toast:{success:`Перемещено в корзину файлов: {{count}}.`,failed:`Не удалось очистить файлы.`}},libraryAutoPurge:{enableLabel:`Автоматически очищать старые файлы`,enableDescription:`Раз в сутки запускает административную очистку. Сначала файлы попадают в корзину и не удаляются немедленно.`,ageLabel:`Автоматически очищать файлы старше`,ageDescription:`Минимум 7 дней, максимум 10 лет. Используется тот же способ расчёта возраста, что и при ручной очистке.`,days:`дней`,includeNeverPrinted:`Включить файлы, которые ни разу не печатались`,saveFailed:`Не удалось сохранить настройки автоочистки.`},archivePurge:{headerButton:`Очистить старые`,headerTooltip:`Массово удалить старые записи архива`,title:`Очистить старые записи архива`,description:`Удаляет старую историю печати. Возраст записи считается от последнего завершения печати; повторная печать обновляет дату, поэтому используемые записи не удаляются.`,ageLabel:`Удалить записи, которые не печатались последние`,days:`дней`,effectsTitle:`Что произойдёт после нажатия «Очистить»`,effect1:`Каждая подходящая запись будет скрыта из списков, а связанные файлы удалены с диска: 3MF, миниатюра, таймлапс, исходный 3MF, проект F3D и фотографии.`,effect2:`Строка архива останется в базе, поэтому быстрая статистика сохранит вклад по филаменту, времени, стоимости и энергии — как при обычном удалении отдельной записи.`,effect3:`Установите флажок «Также удалить из статистики», чтобы исключить вклад из быстрой статистики. Это действие необратимо.`,effect4:`Повторная печать обновляет дату записи, поэтому используемые архивы не удаляются.`,purgeStatsLabel:`Также удалить из статистики`,purgeStatsHint:`Исключает соответствующие записи из быстрой статистики по филаменту, времени, стоимости и энергии. Без этого удаляются только файлы, а статистика сохраняется.`,previewLoading:`Подсчёт подходящих записей…`,previewFailed:`Не удалось выполнить предварительный расчёт.`,previewSummary:`Будет удалено: {{count}} записей · {{size}}`,andMore:`…и ещё {{count}}`,warning:`Файлы будут удалены с диска без возможности восстановления. Перед продолжением скачайте или добавьте в избранное всё, что нужно сохранить.`,confirmCta:`Удалить записей: {{count}}`,purging:`Удаление…`,toast:{success:`Удалено записей архива: {{count}}.`,failed:`Не удалось очистить архив.`}},archiveAutoPurge:{enableLabel:`Автоматически очищать старые записи архива`,enableDescription:`Раз в сутки скрывает записи из списков и удаляет их файлы с диска, если они не печатались в течение заданного срока. Повторная печать сбрасывает отсчёт.`,ageLabel:`Автоматически удалять записи, которые не печатались последние`,ageDescription:`Минимум 7 дней, максимум 10 лет. Срок считается от последнего завершения печати; повторная печать обновляет дату. Удаляются 3MF, миниатюра, таймлапс, исходный 3MF, F3D и фотографии.`,days:`дней`,purgeStatsLabel:`Также удалить из статистики`,purgeStatsDescription:`Если включено, ежедневная очистка исключает удалённые записи из быстрой статистики по филаменту, времени, стоимости и энергии. По умолчанию выключено: статистика сохраняется, удаляются только файлы.`,runNow:`Очистить архив сейчас`,saveFailed:`Не удалось сохранить настройки автоочистки.`},cameraTokens:{scope:{camera_stream:`Поток камеры`,camwall:`Стена камер`,overlay:`Оверлей для стрима`},title:`Токены API камеры`,navTitle:`Токены API камеры`,description:`Долгоживущие токены для встраивания видеопотока в Home Assistant, Frigate, киоски и другие системы, которым нужен постоянный URL. Каждый токен даёт доступ только к потоку камеры и может быть отозван в любой момент.`,loading:`Загрузка...`,confirmRevoke:{title:`Отозвать этот токен?`,body:`Все устройства, использующие «{{name}}», немедленно потеряют доступ. Отменить это действие нельзя.`,cancel:`Отмена`,confirm:`Отозвать`},create:{scopeLabel:`Область действия`,hintCameraStream:`Токен потока камеры позволяет получать только видеопотоки и снимки. Используйте его для Home Assistant, Frigate и других систем, встраивающих изображение с одной камеры.`,hintCamWall:`Токен стены камер открывает страницу /camwall на экране без авторизации. Он позволяет видеть названия и состояния всех принтеров, а также видеопотоки с их камер. Имена файлов, адреса и коды доступа недоступны.`,hintOverlay:`Токен оверлея для стрима открывает страницу /overlay/{printerId} на экране без авторизации — для OBS или любой прямой трансляции. Он даёт доступ к видеопотоку одного принтера и его текущему статусу печати, включая имя файла, отображаемое на экране. Адреса и коды доступа недоступны.`,title:`Создать токен`,nameLabel:`Название токена`,namePlaceholder:`Например, Home Assistant`,daysLabel:`Срок действия, дней`,submit:`Создать`,hint:`Максимальный срок действия — 365 дней. Значение токена показывается только один раз при создании — скопируйте его сейчас.`},created:{camWallUrlTitle:`URL стены камер для этого экрана`,camWallUrlHint:`Откройте этот адрес на экране. Любой, кто получит URL, сможет наблюдать за стеной камер, поэтому обращайтесь с ним как с ключом. Отзовите токен, чтобы отключить экран.`,overlayUrlTitle:`URL оверлея для OBS`,overlayUrlHint:`Добавьте этот адрес как источник браузера (Browser Source) в OBS. Замените число в /overlay/1 на номер вашего принтера (его можно узнать из URL на странице «Принтеры»). Любой, кто получит URL, сможет смотреть трансляцию, поэтому обращайтесь с ним как с ключом — отзовите токен, чтобы прекратить доступ.`,title:`Токен создан — скопируйте его сейчас`,warning:`Это единственный раз, когда токен отображается. После закрытия окна посмотреть его снова будет невозможно.`,copy:`Копировать`,dismiss:`Я сохранил токен`},list:{scope:`Область действия`,myTitle:`Мои токены`,allTitle:`Все пользователи (режим администратора)`,empty:`Токенов пока нет.`,name:`Название`,owner:`Владелец`,prefix:`Префикс`,created:`Создан`,expires:`Истекает`,lastUsed:`Последнее использование`,revoke:`Отозвать`,expired:`Истёк`},toast:{created:`Токен создан`,createFailed:`Не удалось создать токен`,revoked:`Токен отозван`,revokeFailed:`Не удалось отозвать токен`,loadFailed:`Не удалось загрузить токены`,copied:`Скопировано в буфер обмена`,copyFailed:`Не удалось скопировать — выделите и скопируйте вручную`}},forecast:{title:`Прогноз`,noSpools:`Активные катушки не найдены. Добавьте катушки в учёт, чтобы увидеть прогноз.`,noUsageData:`Нет данных о расходе — невозможно спрогнозировать остатки.`,sku:`Артикул`,material:`Материал`,stock:`Запас`,dailyRate:`Расход`,daysLeft:`Осталось дней`,emptyBy:`Закончится к`,reorderBy:`Заказать до`,actions:`Действия`,trend:`Тренд`,estimated:`Оценка`,noData:`Нет данных`,timeframe:`Период`,chartTitle:`Прогноз запаса — 5 основных материалов`,dashedLinesROP:`Пунктирные линии — точки заказа`,stockLevel:`Уровень запаса`,reorderPoint:`Точка заказа`,safetyMargin:`Страховой запас`,trendLegend:`Тренд (по истории, уровень обслуживания 95%)`,estimatedLegend:`Оценка (по изменению массы)`,noDataLegend:`Нет данных`,ropLabel:`ТЗ`,ssLabel:`СЗ`,safetyStockLegend:`Страховой запас`,stockArrivalLegend:`Поступление`,stockoutLegend:`Исчерпание запаса`,alertCount_one:`{{count}} предупреждение`,alertCount_other:`{{count}} предупреждений`,order:`Заказать`,save:`Сохранить`,cancel:`Отмена`,settingsSaved:`Настройки сохранены`,failedSaveSettings:`Не удалось сохранить настройки`,globalLeadTimeSaved:`Общий срок поставки сохранён`,globalLeadTime:`Общий срок поставки`,globalLeadTimeHint:`Минимальный общий срок поставки, используемый при расчёте точки заказа для всех артикулов`,skuLeadTimeOverride:`Переопределение срока поставки`,skuLeadTimeHint:`0 — использовать общий срок поставки. Значение больше 0 переопределяет его для этого артикула.`,safetyMarginLabel:`Страховой запас`,effectiveLeadTime:`Фактический срок поставки`,effectiveLeadTimeHint:`макс. (общий {{global}} дн., для артикула {{sku}} дн.)`,reorderPointHint:`средний расход × срок поставки + страховой запас — заказывайте, когда остаток достигнет этого уровня`,safetyMarginHint:`Статистический страховой запас (z=1,65 × σ × √LT) плюс заданный пользователем резерв`,safetyMarginHintDays:`Резерв поверх статистического страхового запаса.{{approx}}`,safetyMarginHintDaysApprox:` ≈ {{g}} г при текущем расходе.`,safetyMarginHintG:`Фиксированный весовой резерв поверх статистического страхового запаса.{{approx}}`,safetyMarginHintGApprox:` ≈ {{days}} дн. при текущем расходе.`,individualSpools:`Отдельные катушки`,labelWeight:`Метка`,spoolCount_one:`{{count}} катушка`,spoolCount_other:`{{count}} катушек`,stockBreakRisk:`Риск исчерпания запаса`,stockBreakDetail:`Осталось {{days}} дн., срок поставки {{lt}} дн.`,stockBreakBefore:`Запас закончится до пополнения`,reorderNow:`Заказать сейчас`,reorderTriggerPassed:`Дата заказа {{date}} уже прошла.`,shoppingList:`Список покупок`,shoppingListItems_one:`({{count}} позиция)`,shoppingListItems_other:`({{count}} позиций)`,shoppingListEmpty:`Список покупок пуст. Нажмите значок корзины в нужной строке, чтобы добавить позицию.`,addToCart:`Добавить в список покупок`,alertsSnoozed:`Отключить предупреждения для артикула`,alertsEnabled:`Включить предупреждения для артикула`,addedToCart:`Добавлено в список покупок`,failedAddItem:`Не удалось добавить позицию`,listView:`Список`,logisticsView:`Логистика`,qty:`Кол-во`,weight:`Масса`,leadTime:`Срок поставки`,expectedRestock:`Ожидаемое пополнение`,status:`Состояние`,note:`Примечание`,pending:`Ожидается`,purchased:`Куплено`,received:`Получено`,markPurchased:`Отметить как купленное`,markReceived:`Отметить как полученное — катушки будут добавлены в запас`,resetToPending:`Вернуть в ожидание`,remove:`Удалить`,clearAll:`Очистить всё`,downloadCsv:`CSV`,addToCartTitle:`Добавить в список покупок`,byQuantity:`По количеству`,byDuration:`По сроку`,numberOfSpools:`Количество катушек`,lastHowManyDays:`На сколько дней должно хватить?`,noUsageQty:`Нет данных о расходе — количество установлено равным 1.`,noteOptional:`Примечание (необязательно)`,notePlaceholder:`например, для проекта X, срочно…`,addNSpools_one:`Добавить {{count}} катушку`,addNSpools_other:`Добавить {{count}} катушек`,onArrival:`После поступления`,stockBreakIn:`Запас закончится через {{days}} дн.`,stockRunsOutBefore:`Запас закончится раньше, чем истекут {{lt}} дн. срока поставки.`,atRate:`При расходе {{rate}} г/день требуется`,moreSpools_one:`ещё {{count}} катушка`,moreSpools_other:`ещё {{count}} катушек`,bridgeGap:`чтобы перекрыть дефицит.`,noReadAccess:`У вас нет прав на просмотр прогноза запасов.`,noWriteAccess:`У вас нет прав на изменение настроек прогноза.`}}},uk:{translation:{nav:{printers:`Принтери`,archives:`Архіви`,queue:`Черга друку`,stats:`Статистика`,profiles:`Профілі`,maintenance:`Технічне обслуговування`,projects:`Проєкти`,inventory:`Філамент`,files:`Менеджер файлів`,makerworld:`MakerWorld`,notifications:`Сповіщення`,settings:`Налаштування`,system:`Система`,collapseSidebar:`Згорнути бічну панель`,expandSidebar:`Розгорнути бічну панель`,update:`Оновити`,updateAvailable:`Доступне оновлення: v{{version}}`,updateAvailableBanner:`Доступна версія {{version}}!`,viewUpdate:`Переглянути оновлення`,viewOnGithub:`Переглянути на GitHub`,keyboardShortcuts:`Комбінації клавіш (?)`,switchToLight:`Перейти у світлий режим`,switchToDark:`Перейти у темний режим`,switchToSystem:`Перейти в системний режим`,smartSwitches:`Розумні перемикачі`,logout:`Вийти`,installApp:`Встановити додаток`,installAppSuccess:`Bambuddy встановлено`},common:{save:`Зберегти`,saving:`Збереження...`,cancel:`Скасувати`,delete:`Видалити`,edit:`Редагувати`,add:`Додати`,close:`Закрити`,confirm:`Підтвердити`,loading:`Завантаження...`,error:`Помилка`,errorLoading:`Помилка завантаження даних`,retry:`Повторити`,success:`Успіх`,warning:`Попередження`,enabled:`Увімкнено`,disabled:`Вимкнено`,yes:`Так`,no:`Ні`,on:`Увімкнено`,off:`Вимкнено`,all:`Усі`,none:`Жодного`,search:`Пошук`,filter:`Фільтр`,sort:`Сортувати`,refresh:`Оновити`,download:`Завантажити`,upload:`Вивантажити`,uploading:`Вивантаження...`,uploadFailed:`Не вдалося вивантажити`,actions:`Дії`,status:`Статус`,name:`Назва`,description:`Опис`,date:`Дата`,time:`Час`,hours:`год`,minutes:`хв`,seconds:`с`,days:`дн.`,enable:`Увімкнути`,disable:`Вимкнути`,permissions:`Дозволи`,noPrinters:`Принтери не налаштовані`,noData:`Немає даних`,linkNotFound:`Посилання не знайдено`,required:`Обов’язковий`,optional:`Необов’язково`,dismiss:`Закрити`,apply:`Застосувати`,reset:`Скинути`,export:`Експортувати`,import:`Імпортувати`,clear:`Очистити`,selectAll:`Вибрати всі`,deselectAll:`Зняти вибір із усіх`,noChange:`— Без змін —`,unchanged:`Без змін`,unassigned:`Не призначено`,unknown:`Невідомо`,unknownError:`Невідома помилка`,today:`Сьогодні`,tomorrow:`Завтра`,asap:`Якнайшвидше`,overdue:`Протерміновано`,now:`Зараз`,collapse:`Згорнути`,expand:`Розгорнути`,previous:`Попередній`,next:`Далі`,viewArchive:`Переглянути архів`,viewInFileManager:`Переглянути в менеджері файлів`,addedBy:`Додав {{username}}`,prints:`друків`,more:`+ ще {{count}}`,ascending:`За зростанням`,descending:`За спаданням`,back:`Назад`,copy:`Копіювати`,copied:`Скопійовано!`,printer:`Принтер`,remove:`Видалити`,type:`Тип`,print:`Друкувати`,rename:`Перейменувати`,move:`Перемістити`,create:`Створити`,duplicate:`Дублювати`,left:`Ліворуч`,right:`Праворуч`},printers:{title:`Принтери`,addPrinter:`Додати принтер`,addPreflight:{checking:`Перевірка підключення...`,warning:`Деякі перевірки підключення завершилися невдало. Принтер може відображатися як офлайн. Перегляньте результати нижче, усуньте можливі проблеми або все одно збережіть принтер.`,back:`Назад`,saveAnyway:`Усе одно зберегти`},editPrinter:`Редагувати принтер`,deletePrinter:`Видалити принтер`,printerName:`Назва принтера`,serialNumber:`Серійний номер`,ipAddress:`IP-адреса / ім’я хоста`,accessCode:`Код доступу`,model:`Модель`,nozzleCount:`Кількість сопел`,autoArchive:`Автоархів`,status:{available:`Доступний`,idle:`Неактивний`,printing:`Друк`,paused:`Призупинено`,offline:`Не в мережі`,problem:`Проблема`,error:`Помилка`,finished:`Готово`,unknown:`Невідомий`},temperatures:{nozzle:`Сопло`,bed:`Стіл`,chamber:`Камера`},heaterHistory:{title:`Історія нагрівання`,openLabel:`Переглянути історію нагрівання`,nozzle:`Сопло`,nozzle2:`Сопло 2`,bed:`Стіл`,chamber:`Камера`,error:`Не вдалося завантажити історію`,empty:`Дані ще не записані`},progress:`{{percent}}% виконано`,timeRemaining:`Залишилося {{time}}`,deleteConfirm:`Ви впевнені, що хочете видалити "{{name}}"?`,maintenanceOk:`Технічне обслуговування в порядку`,maintenanceWarning:`{{count}} попередження`,maintenanceWarning_plural:`{{count}} попередження`,maintenanceDue:`Потрібне обслуговування: {{count}}`,maintenanceDue_plural:`Потрібне обслуговування: {{count}}`,sort:{name:`Назва`,status:`Статус`,model:`Модель`,location:`Розташування`,eta:`Орієнтовне завершення`,ascending:`Сортувати за зростанням`,descending:`Сортувати за спаданням`},cardSize:{small:`Маленькі картки`,medium:`Середні картки`,large:`Великі картки`,extraLarge:`Дуже великі картки`},pageView:{openCamWallPage:`Відкрити панель камер як окрему сторінку`,cards:`Картки`,camWall:`Панель камер`},camWall:{page:{tokenRejected:`Це посилання на панель камер більше не дійсне. Можливо, термін дії токена минув або токен було відкликано.`,loadFailed:`Не вдалося завантажити список принтерів.`},noPrinters:`Немає принтерів для показу`,noSignal:`Немає сигналу`,live:`Наживо`,snap:`Знімок`,off:`Вимкнено`,summary:`{{live}} наживо, {{snap}} знімки, {{total}} всього`,layer:`Шар {{cur}}/{{total}}`,timeLeft:`Залишилося {{time}}`,statusMode:{off:`Вимкнено`,compact:`Компактний`,full:`Повний`},settings:{title:`Налаштування Cam Wall`,maxLive:`Максимальна кількість прямих трансляцій`,maxLiveHint:`Кількість плиток, що одночасно показують пряму трансляцію. Решта оновлюються як знімки.`,snapshotInterval:`Інтервал знімка (секунди)`,snapshotIntervalHint:`Як часто плитки без прямої трансляції отримують новий знімок.`,statusOverlay:`Накладення стану`,statusOverlayHint:`Компактний: лише значок стану. Повний: значок, прогрес, шар і час, що залишився.`}},hideOffline:`Приховати офлайн-принтери`,nextAvailable:`Наступний доступний`,powerOn:`Увімкнути`,offlinePrintersWithPlugs:`Офлайн-принтери з розумними розетками`,noPrintersConfigured:`Принтерів ще не налаштовано`,search:`Пошук принтерів...`,noSearchResults:`Немає принтерів, які відповідають вашому пошуку або фільтрам`,filter:{allStatuses:`Усі статуси`,allLocations:`Усі розташування`},toolbar:{filters:`Фільтри`,view:`Вигляд`,actions:`Дії`},readyToPrint:`Готовий до друку`,external:`Зовнішній`,extL:`Ext-L`,extR:`Ext-R`,deleteArchives:`Видалити архіви друку`,noLabel:`Без етикетки`,printPreview:`Попередній перегляд`,width:`Ширина`,height:`Висота`,noObjectsFound:`Об’єктів не знайдено`,objectsLoadedOnPrintStart:`Об’єкти завантажуються після початку друку`,willBeSkipped:`Буде пропущено`,name:`Назва`,serialCannotBeChanged:`Серійний номер не можна змінити`,locationHelp:`Використовується для групування принтерів і фільтрації завдань у черзі`,wifiSignal:{veryWeak:`Дуже слабкий`,weak:`Слабкий`,fair:`Задовільний`,good:`Добрий`,excellent:`Чудово`},maintenanceUpToDate:`Усі роботи з технічного обслуговування виконано — натисніть, щоб переглянути`,maintenance:{title:`На технічному обслуговуванні`,subtitle:`Роботу цього принтера призупинено: він не підключається, не отримує завдань із черги й не надсилає сповіщень.`,pillLabel:`Технічне обслуговування`,exitButton:`Вийти з технічного обслуговування`,menuEnter:`Увійти в режим обслуговування`,menuExit:`Вийти з режиму обслуговування`,toastEntered:`{{name}} зараз у режимі обслуговування`,toastExited:`{{name}} знову в мережі`,confirmMidPrintTitle:`Перевести принтер у режим обслуговування під час друку?`,confirmMidPrintMessage:`{{name}} зараз друкує. Перехід у режим обслуговування відключить MQTT і припинить відстеження перебігу друку та сповіщення про завершення цього завдання. Продовжити?`,editFieldLabel:`Режим обслуговування`,editFieldHelp:`Коли режим увімкнено, принтер відключається від MQTT, не отримує завдань із черги й не надсилає сповіщень. Використовуйте цей режим під час ремонту, паралельного розгортання Bambuddy або тимчасового виведення принтера з роботи.`},chamberLightOn:`Увімкнути світло в камері`,chamberLightOff:`Вимкнути світло в камері`,files:`Файли`,browseFiles:`Переглянути файли принтера`,autoOffAfterPrint:`Автоматичне вимкнення після друку`,autoOffExecuted:`Автоматичне вимкнення виконано — увімкніть принтер, щоб скинути стан`,hmsErrors:`Помилки HMS`,viewHmsErrors:`Переглянути помилки HMS ({{count}})`,resume:`Відновити`,pause:`Призупинити`,stop:`Зупинити`,camera:`Камера`,skipObject:`Пропустити об’єкт`,reconnect:`Підключитися знову`,forceRefresh:`Примусово оновити`,forceRefreshSuccess:`Оновлення запитано`,mqttDebug:`Налагодження MQTT`,printerInformation:`Інформація про принтер`,copyToClipboard:`Копіювати`,copied:`Скопійовано!`,state:`Стан`,wifiSignalLabel:`Сигнал Wi‑Fi`,developerMode:`Режим розробника`,enabled:`Увімкнено`,disabled:`Вимкнено`,addedOn:`Додано`,sdCard:`SD-картка`,inserted:`Вставлено`,notInserted:`Не вставлено`,totalPrintHours:`Загальний час друку`,activeNozzle:`Активне сопло: {{nozzle}}`,nozzleRack:`Стійка сопел`,nozzleDocked:`У док-станції`,nozzleMounted:`Установлено`,nozzleActive:`Активний`,nozzleIdle:`Неактивний`,nozzleDiameter:`Діаметр`,nozzleType:`Тип`,nozzleStatus:`Статус`,nozzleFilament:`Філамент`,nozzleWear:`Знос`,nozzleMaxTemp:`Макс. температура`,nozzleSerial:`Серійний номер`,nozzleHardenedSteel:`Загартована сталь`,nozzleStainlessSteel:`Нержавіюча сталь`,nozzleTungstenCarbide:`Карбід вольфраму`,nozzleFlow:`Потік`,nozzleHighFlow:`Високий потік`,nozzleStandardFlow:`Стандартний`,firmwareUpdate:`Оновлення прошивки`,firmwareInstructions:`На сенсорному екрані принтера перейдіть до`,firmwareNav:`Перейдіть до`,settings:`Налаштування`,firmware:`Прошивка`,discoverPrinters:`Знайти принтери`,searching:`Пошук...`,manualEntry:`Ввести вручну`,addFromCloud:`Додати з хмари`,toast:{printerDeleted:`Принтер видалено`,missingSpoolAssignment:`Друк на {{printer}} розпочато. Для слотів {{slots}} не призначено котушки.`,assignmentVerified:`Філамент завантажено в слот AMS {{slot}} принтера {{printer}}`,assignmentVerifiedNoKprofile:`Слот AMS {{slot}} на {{printer}} завантажено, але калібрування потоку (K-профіль) не застосовано`,assignmentNotConfirmed:`Не вдалося підтвердити призначення для слота {{slot}} на {{printer}} — перевірте слот AMS`,printerAdded:`Додано принтер`,printerUpdated:`Принтер оновлено`,failedToDelete:`Не вдалося видалити принтер`,failedToAdd:`Не вдалося додати принтер`,connectionFailedNotAdded:`Не вдалося підключитися до принтера. Перевірте IP, серійний номер і код доступу, а також підтвердьте, що режим лише для LAN увімкнено. Принтер не додано.`,failedToUpdate:`Не вдалося оновити принтер`,commandSent:`Команда надіслана`,failedToSendCommand:`Не вдалося надіслати команду`,turnedOn:`{{name}} увімкнено`,failedToPowerOn:`Не вдалося ввімкнути {{name}}`,scriptTriggered:`Сценарій запущено`,printStopped:`Друк зупинено`,printPaused:`Друк призупинено`,printResumed:`Друк відновлено`,referenceDeleted:`Еталонне зображення видалено`,detectionAreaSaved:`Область виявлення збережено`,failedToRunScript:`Не вдалося запустити сценарій`,failedToStopPrint:`Не вдалося зупинити друк`,failedToPausePrint:`Не вдалося призупинити друк`,failedToResumePrint:`Не вдалося відновити друк`,failedToControlChamberLight:`Не вдалося керувати світлом камери`,failedToSetSpeed:`Не вдалося встановити швидкість друку`,failedToUpdateSetting:`Не вдалося оновити налаштування`,failedToSkipObjects:`Не вдалося пропустити об’єкти`,failedToRereadRfid:`Не вдалося перечитати RFID`,failedToCheckPlate:`Не вдалося перевірити друкарську пластину`,failedToUpdateLabel:`Не вдалося оновити мітку`,failedToDeleteReference:`Не вдалося видалити еталонне зображення`,failedToSaveDetectionArea:`Не вдалося зберегти область виявлення`,plateCheckEnabled:`Перевірку друкарської пластини ввімкнено`,plateCheckDisabled:`Перевірку друкарської пластини вимкнено`,calibrationSaved:`Калібрування збережено!`,calibrationFailed:`Не вдалося виконати калібрування`,rfidRereadInitiated:`Розпочато повторне зчитування RFID`,loadInitiated:`Завантаження філаменту...`,unloadInitiated:`Вивантаження філаменту...`,failedToLoad:`Не вдалося завантажити філамент`,failedToUnload:`Не вдалося вивантажити філамент`},connection:{connected:`Підключено`,offline:`Не в мережі`},plateStatus:{markCleared:`Позначити друкарську пластину як очищену`,cleared:`Друкарську пластину очищено`,notCleared:`Друкарську пластину не очищено`,inUse:`Друкарська пластина використовується`},queue:{inQueue:`У черзі: {{count}}`,inQueue_plural:`У черзі: {{count}}`},controls:`Елементи керування`,rfid:{reread:`Перечитати RFID`},ams:{load:`Завантажити`,unload:`Вивантажити`},bedJog:{limitWarning:`Під час ручного переміщення межі ходу не контролюються: через помилку прошивки Bambu віддалені команди ігнорують програмні кінцеві обмежувачі. Переміщуйте стіл обережно, щоб уникнути зіткнення.`,title:`Керування переміщенням`,bed:`Стіл`,step:`Крок (мм)`,up:`Перемістити стіл угору`,down:`Перемістити стіл униз`,disabledWhilePrinting:`Вимкнено під час друку`,notHomedTitle:`Принтер не відкалібровано за початковою позицією`,notHomedMessage:`Після останнього друку принтер не виконував пошук початкової позиції. Для безпечного позиціювання спочатку запустіть автопозиціювання: принтер припаркує друкувальну головку та визначить початкові координати X, Y і Z. Або продовжте переміщення без нього — програмні кінцеві обмежувачі буде обійдено.`,homeZ:`Запустити автопозиціювання`,moveAnyway:`Усе одно перемістити`,homingStarted:`Виконується автопозиціювання принтера…`},permission:{noAdd:`Ви не маєте дозволу додавати принтери`,noEdit:`Ви не маєте дозволу редагувати принтери`,noDelete:`Ви не маєте дозволу на видалення принтерів`,noControl:`Ви не маєте дозволу керувати принтерами`,noFiles:`Ви не маєте дозволу на доступ до файлів принтера`,noAmsRfid:`Ви не маєте дозволу на повторне читання AMS RFID`,noSmartPlugControl:`Ви не маєте дозволу керувати розумними розетками`,noCamera:`У вас немає дозволу на перегляд камер`},modal:{addTitle:`Додати принтер`,editTitle:`Редагувати принтер`,myPrinter:`Мій принтер`,selectModel:`Вибрати модель…`,locationGroup:`Розташування/група (необов’язково)`,locationPlaceholder:`наприклад, майстерня, офіс, підвал`,autoArchiveLabel:`Автоматичне архівування завершених роздруківок`,fromPrinterSettings:`З налаштувань принтера`,modelOptional:`Модель (необов’язково)`,saveChanges:`Зберегти зміни`},skipObjects:{tooltip:`Пропустити об’єкти`,onlyWhilePrinting:`Пропустити об’єкти (лише під час друку)`,requiresMultiple:`Пропустити об’єкти (потрібно щонайменше 2 об’єкти)`,title:`Пропустити об’єкти`,matchIdsInfo:`Зіставте ідентифікатори з дисплеєм принтера`,printerShowsIds:`На екрані принтера показано ідентифікатори об’єктів на друкарській пластині`,skipSelected:`Пропустити вибране`,skipping:`Пропускання…`,noObjectsSelected:`Об’єкти не вибрано`,selectObjectsToSkip:`Виберіть об’єкти, які потрібно пропустити під час поточного друку`,skipped:`пропущено`,objectsSkipped:`Об’єкти пропущено`,activeCount:`Активних: {{count}}`,waitForLayer:`Щоб пропускати об’єкти, дочекайтеся другого шару або пізніше (зараз шар {{layer}})`,skip:`Пропустити`,confirmTitle:`Пропустити об’єкт?`,confirmMessage:`Ви впевнені, що бажаєте пропустити "{{name}}"? Це неможливо скасувати.`,confirmAllMessage:`Вибрано всі об’єкти, що залишилися. Це зупинить завдання друку. Продовжити?`,confirmMultipleMessage:`Пропустити вибрані об’єкти ({{count}})? Цю дію неможливо скасувати.`},confirm:{deleteTitle:`Видалити принтер`,deleteMessage:`Ви впевнені, що хочете видалити "{{name}}"? Це призведе до видалення всіх налаштувань підключення.`,deleteArchivesNote:`Усю історію друку для цього принтера буде остаточно видалено.`,keepArchivesNote:`Історія друку буде збережена, але більше не пов’язана з цим принтером.`,stopTitle:`Зупинити друк`,stopMessage:`Ви впевнені, що хочете зупинити поточний друк на "{{name}}"? Це призведе до скасування завдання друку.`,stopButton:`Зупинити друк`,pauseTitle:`Призупинити друк`,pauseMessage:`Ви впевнені, що хочете призупинити поточний друк на "{{name}}"?`,pauseButton:`Призупинити друк`,resumeTitle:`Відновити друк`,resumeMessage:`Ви впевнені, що бажаєте відновити друк на "{{name}}"?`,resumeButton:`Відновити друк`,powerOnTitle:`Увімкнути принтер`,powerOnMessage:`Увімкнути живлення принтера «{{name}}»?`,powerOnButton:`Увімкнути`,powerOffTitle:`Вимкнути принтер`,powerOffMessage:`Вимкнути живлення принтера «{{name}}»?`,powerOffWarning:`УВАГА: «{{name}}» зараз друкує. Вимкнення живлення перерве друк і може пошкодити принтер. Продовжити?`,powerOffButton:`Вимкнути`,haToggleTitle:`Перемкнути "{{name}}"`,haToggleMessage:`Перемкнути об’єкт Home Assistant {{entity}}? Це може вимкнути живлення, якщо воно зараз увімкнено.`,haToggleWarning:`УВАГА: "{{name}}" зараз друкується! Перемикання {{entity}} може вимкнути живлення та перервати друк. Продовжити?`,haToggleButton:`Перемкнути`},bulk:{select:`Вибрати`,selectAll:`Вибрати усі`,selectByLocation:`Вибрати за розташуванням`,selected:`Вибрано: {{count}}`,actions:{stop:`Зупинити`,pause:`Призупинити`,resume:`Відновити`,clearPlate:`Очистити стіл`,clearHMS:`Очистити сповіщення`},confirm:{stopTitle:`Зупинити завдання друку: {{count}}`,stopMessage:`Активний друк буде скасовано на вибраних принтерах ({{count}}). Цю дію неможливо скасувати.`,stopButton:`Зупинити все`,pauseTitle:`Призупинити завдання друку: {{count}}`,pauseMessage:`Активний друк буде призупинено на вибраних принтерах ({{count}}).`,pauseButton:`Призупинити все`,clearPlateTitle:`Очистити столи ({{count}})`,clearPlateMessage:`Столи вибраних принтерів ({{count}}) буде позначено очищеними, що може запустити завдання з черги.`,clearPlateButton:`Очистити все`},success:`Дію «{{action}}» виконано на принтерах: {{count}}`,partial:`{{succeeded}} вдалося, {{failed}} не вдалося`,noneApplicable:`Немає вибраних принтерів у належному стані для цієї дії`,selectByState:`Вибрати за станом`},discovery:{title:`Знайти принтери`,searching:`Пошук...`,scanning:`Сканування...`,scanProgress:`Сканування... {{scanned}}/{{total}}`,foundPrinters:`Знайдено принтерів: {{count}}`,noPrintersFound:`Принтерів не знайдено`,noPrintersFoundSubnet:`Немає принтерів у вказаній підмережі.`,noPrintersFoundNetwork:`У мережі не знайдено принтерів.`,allConfigured:`Усі знайдені принтери вже налаштовані.`,alreadyAdded:`Вже додано`,select:`Вибрати`,manualEntry:`Ввести вручну`,addFromCloud:`Додати з хмари`,subnetToScan:`Підмережа для сканування`,dockerNote:`Виявлено Docker. Введіть підмережу принтера в нотації CIDR. У docker-compose.yml потрібен параметр network_mode: host.`,scanSubnet:`Сканувати підмережу для принтерів`,discoverNetwork:`Знайти принтери в мережі`,scanningSubnet:`Сканування підмережі для принтерів Bambu...`,scanningNetwork:`Сканування мережі...`,serialRequired:`Потрібен серійний номер`,unknown:`Невідомий`,failedToStart:`Не вдалося запустити пошук`,customSubnetOption:`Спеціальна підмережа...`,customSubnetLabel:`Спеціальна підмережа (CIDR)`,customSubnetNote:`Укажіть власну підмережу, якщо принтер перебуває в іншій мережі, ніж сервер. Порти FTP (990) і MQTT (8883) мають бути доступні через маршрутизатор.`},drying:{start:`Почати сушіння`,stop:`Зупинити сушіння`,temperature:`Температура`,duration:`Тривалість`,hours:`години`,timeRemaining:`Залишилося {{time}}`,active:`Сушіння`,targetSummary:`{{filament}} при {{temp}}°C`,notSupported:`Сушіння не підтримується`,powerRequired:`Підключіть адаптер живлення AMS, щоб увімкнути сушіння`,startingDrying:`Запуск сушіння…`,toastCommandSent:`Надіслано команду сушіння`,toastStopped:`Сушіння зупинено`,toastNotStarted:`Принтер прийняв команду, але AMS так і не почав сушити. Перевірте, чи підключено адаптер живлення AMS і чи принтер неактивний.`,screenOnly:`Сушінням AMS на цьому принтері можна керувати лише з екрана принтера (обмеження Bambu)`,stoppingDrying:`Припинення сушіння...`,rotateTray:`Обертати котушку під час сушіння`,rotateUnavailableReason:`Недоступно: філамент із цього слота AMS завантажено в інструментальну головку. Котушка заблокована подавальною трубкою й не може обертатися. Спочатку вивантажте філамент.`},amsBackup:{titleOn:`Резервне перемикання філаменту AMS увімкнено. Натисніть, щоб вимкнути.`,titleOff:`Резервне перемикання філаменту AMS вимкнено. Натисніть, щоб увімкнути.`,titleUnknown:`Стан резервної котушки AMS недоступний на цьому принтері.`,toastEnabled:`Резервну котушку AMS ввімкнено`,toastDisabled:`Резервну котушку AMS вимкнено`,modalTitle:`Резервне перемикання філаменту AMS`,modalHelp:`Коли філамент в активному слоті закінчується, принтер по черзі перемикається на слоти з таким самим профілем і кольором у вказаному порядку.`,modalNoSlots:`Філамент не завантажено.`,modalNoPairs:`Немає резервних пар — немає двох слотів з однаковим профілем і кольором філаменту.`,extruderRightShort:`Р`,extruderLeftShort:`Л`,stateOn:`Увімкнено`,stateOff:`Вимкнено`,stateUnknown:`Не підтримується на цьому принтері`},activeJobSlot:{title:`Цей слот відповідає філаменту {{n}} в поточному завданні друку`,ariaLabel:`Слот {{n}} поточного завдання друку`},expectedSlot:{title:`Принтер очікує філамент у цьому слоті`,ariaLabel:`Очікуваний слот для філаменту {{n}}`,label:`{{ams}} · Слот {{slot}}`,external:`Зовнішня котушка`},filaments:`Філаменти`,openCameraOverlay:`Відкрити накладання камери`,openCameraWindow:`Відкрити камеру в новому вікні`,firmwareUpdateAvailable:`Доступне оновлення прошивки: {{current}} → {{latest}}`,firmwareUpToDate:`Прошивка {{version}} актуальна`,firmwareUpdateButton:`Оновити`,plateDetection:{noPermission:`Ви не маєте дозволу на оновлення принтерів`,enabledClick:`Перевірку друкарської пластини ввімкнено — натисніть, щоб вимкнути`,disabledClick:`Перевірку друкарської пластини вимкнено — натисніть, щоб увімкнути`,manageCalibration:`Керувати калібруванням перевірки пластини`,calibrationRequired:`Потрібне калібрування`,calibrationInstructions:`Переконайтеся, що робоча пластина повністю порожня, а потім натисніть «Калібрувати».`,calibrationDescription:`Під час калібрування створюється еталонне зображення порожньої пластини. Наступні перевірки порівнюватимуть з ним зображення, щоб виявляти об’єкти.`,calibrationTip:`Порада: Ви можете зберегти до 5 калібрувань для різних пластин. Під час перевірки система автоматично використовує найкращий збіг.`,plateEmpty:`Друкарська пластина виглядає порожньою`,objectsDetected:`На пластині виявлено об’єкти`,confidence:`Впевненість`,difference:`Різниця`,analysisPreview:`Попередній перегляд аналізу:`,analysisLegend:`Зелена рамка = зона виявлення, червона накладка = відмінності від калібрування`,savedReferences:`Збережені еталонні зображення ({{count}}/{{max}})`,deleteReference:`Видалити еталонне зображення`,labelPlaceholder:`Мітка...`,clickToEdit:`{{label}} - Натисніть, щоб редагувати`,clickToAddLabel:`Натисніть, щоб додати мітку`},speed:{title:`Швидкість друку`,silent:`Тихий (50%)`,standard:`Стандарт (100%)`,sport:`Sport (124%)`,ludicrous:`Ludicrous (166%)`},airduct:{title:`Режим повітропроводу`,cooling:`Охолодження`,heating:`Опалення`},noSdCard:`Немає SD-картки`,door:{open:`Відчинено`,closed:`Закрито`},fans:{partCooling:`Вентилятор охолодження моделі`,auxiliary:`Допоміжний вентилятор`,leftAuxiliary:`Лівий допоміжний вентилятор`,exhaust:`Витяжка`,chamber:`Камерний вентилятор`},clickToViewHmsErrors:`Натисніть, щоб переглянути помилки HMS`,aiDetection:{safe:`Безпечно`,warning:`Попередження`,failure:`Помилка`,idle:`Очікування`,tooltip:`Виявлення помилок за допомогою ШІ: {{status}} (оцінка {{score}}) — натисніть, щоб переглянути деталі`,tooltipIdle:`Виявлення помилок за допомогою ШІ ввімкнено — моніторинг почнеться з наступним друком — натисніть, щоб переглянути деталі`,modalTitle:`Виявлення помилок за допомогою ШІ — {{name}}`,currentStatus:`Стан`,score:`Оцінка`,framesAnalyzed:`Проаналізовано кадрів`,idleHint:`Зараз жоден друк не відстежується. Моніторинг автоматично почнеться з наступним друком.`,lastError:`Остання помилка`,openSettings:`Відкрити налаштування`},estimatedCompletion:`Орієнтовний час виконання`,plateNumber:`Пластина {{number}}`,slotOptions:`Опції слота`,amsPopup:{friendlyName:`Назва AMS`,friendlyNamePlaceholder:`наприклад, Основна AMS`,serialNumber:`Серійний номер`,firmwareVersion:`Прошивка`,save:`Зберегти`,clear:`Очистити`,noEditPermission:`Ви не маєте дозволу на перейменування одиниць AMS.`},firmwareModal:{title:`Оновлення прошивки`,titleUpToDate:`Інформація про прошивку`,currentVersion:`Поточна:`,latestVersion:`Найновіша:`,releaseNotes:`Примітки до випуску`,checkingPrereqs:`Перевірка передумов...`,sdCardReady:`SD-картка готова. Натисніть нижче, щоб вивантажити на неї прошивку.`,uploadedSuccess:`Прошивку вивантажено на картку SD!`,applyInstructions:`Щоб застосувати оновлення до свого принтера:`,step1:`На сенсорному екрані принтера перейдіть до Налаштування`,step2:`Перейдіть до розділу Прошивка`,step3:`Виберіть Оновити з SD-картки`,step4:`Оновлення займе 10-20 хвилин`,done:`Готово`,starting:`Запуск…`,uploadFirmware:`Вивантажити прошивку`,uploadFailed:`Не вдалося почати вивантаження: {{error}}`,uploadedToast:`Прошивку вивантажено! Запустіть оновлення з екрана принтера.`,availableVersions:`Доступні версії`,usable:`Можна використовувати`,unavailable:`Недоступна`,installed:`Установлена`,newerBadge:`новіший`,olderBadge:`старіша`,currentBadge:`поточна`},accessCodePlaceholder:`Залиште порожнім, щоб не змінювати`,roi:{title:`Область виявлення (ROI)`,xStart:`Початок X`,yStart:`Початок Y`,width:`Ширина`,height:`Висота`,instruction:`Відрегулюйте область виявлення, щоб сфокусуватися на робочій пластині. Зелене поле в попередньому перегляді показує поточну область.`},developerModeWarning:`Режим розробника LAN не ввімкнено на: {{names}}. Деякі функції можуть не працювати.`,howToEnable:`Як увімкнути`,incompatibleFile:`Цей файл нарізано для {{slicedFor}}, а модель цього принтера — {{printerModel}}`,dropNotPrintable:`Можна роздрукувати лише файли .gcode і .gcode.3mf.`,dropToPrint:`Відпустіть для друку`,cannotPrint:`Принтер зайнятий`},archives:{title:`Архіви друку`,no3mfBanner:{title:`Деякі нещодавні роздруківки не вдалося заархівувати з мініатюрами`,body:`Слайсер не залишив файл .gcode.3mf на SD-картці принтера, тому Bambuddy не зміг отримати мініатюру або метадані слайсера. Зазвичай це стається, коли в слайсері вимкнено параметр «Зберігати надіслані файли на зовнішньому накопичувачі» (вкладка «Пристрій» у Bambu Studio або OrcaSlicer).`,docsLink:`Переглянути крок 4 встановлення`,dismissLabel:`Відхилити це повідомлення`},searchPlaceholder:`Пошук в архівах...`,filterByPrinter:`Фільтрувати за принтером`,filterByStatus:`Фільтрувати за статусом`,sortBy:`Сортувати за`,sortNewest:`Спочатку найновіші`,sortOldest:`Спочатку найстаріші`,sortName:`Назва`,sortDuration:`Тривалість`,sortLargest:`Спочатку найбільші`,sortSmallest:`Спочатку найменші`,sortSize:`Розмір`,noArchives:`Архіви не знайдено`,noArchivesSearch:`Жоден архів не відповідає вашому пошуку`,originalPrintNotVisible:`Оригінальний друк не відображається — спробуйте очистити фільтри`,noArchivesYet:`Архівів ще немає`,prints:`друків`,pagination:{showing:`Показано`,to:`до`,of:`з`,show:`Показати`,page:`Сторінка`,all:`Усі`},loadingArchives:`Завантаження архівів...`,releaseToUpload:`Відпустіть, щоб вивантажити`,showAll:`Показати все`,showFavoritesOnly:`Показати лише вибране`,gridView:`Вигляд сітки`,listView:`Перегляд списку`,calendarView:`Перегляд календаря`,logView:`Журнал друку`,manageTags:`Керування тегами`,showFailedPrints:`Показати невдалі друки`,hideFailedPrints:`Приховати невдалі друки`,hideDuplicates:`Приховати дублікати`,viewOriginalPrint:`Клацніть, щоб переглянути оригінальний друк (#{{id}})`,printTime:`Час друку`,filamentUsed:`Використано філаменту`,cost:`Вартість`,preview:`Попередній перегляд`,deleteArchive:`Видалити архів`,deleteConfirm:`Ви впевнені, що хочете видалити цей архів?`,favorite:`В обраному`,unfavorite:`Видалити з вибраного`,viewDetails:`Переглянути деталі`,status:{completed:`Завершено`,failed:`Невдало`,stopped:`Зупинено`},toast:{source3mfAttached:`Вихідний файл 3MF долучено: {{filename}}`,failedUploadSource3mf:`Не вдалося вивантажити вихідний файл 3MF`,source3mfRemoved:`Вихідний файл 3MF видалено`,failedRemoveSource3mf:`Не вдалося видалити вихідний файл 3MF`,f3dAttached:`F3D долучено: {{filename}}`,failedUploadF3d:`Не вдалося вивантажити F3D`,f3dRemoved:`F3D видалено`,failedRemoveF3d:`Не вдалося видалити F3D`,timelapseAttached:`Додано покадрову зйомку: {{filename}}`,timelapseAlreadyAttached:`Таймлапс уже долучено`,noMatchingTimelapse:`Відповідного таймлапсу не знайдено`,failedScanTimelapse:`Не вдалося відсканувати покадрову зйомку`,failedAttachTimelapse:`Не вдалося долучити таймлапс`,timelapseRemoved:`Таймлапс видалено`,failedRemoveTimelapse:`Не вдалося видалити таймлапс`,timelapseUploaded:`Таймлапс вивантажено: {{filename}}`,failedUploadTimelapse:`Не вдалося вивантажити таймлапс`,archiveDeleted:`Архів видалено`,failedDeleteArchive:`Не вдалося видалити архів`,addedToFavorites:`Додано до обраних`,removedFromFavorites:`Видалено з вибраного`,projectUpdated:`Проєкт оновлений`,failedUpdateProject:`Не вдалося оновити проєкт`,linkCopied:`Посилання скопійовано в буфер обміну`,failedCopyLink:`Не вдалося скопіювати посилання`,photoDeleted:`Фото видалено`,failedDeletePhoto:`Не вдалося видалити фото`,failedDeleteArchives:`Не вдалося видалити архіви`,failedUpdateFavorites:`Не вдалося оновити вибране`,exportDownloaded:`Експорт завантажено`,exportFailed:`Помилка експорту`},menu:{print:`Друкувати`,openInBambuStudio:`Відкрити у слайсері`,slice:`Нарізати`,externalLink:`Зовнішнє посилання`,viewOnMakerWorld:`Переглянути на MakerWorld`,preview3d:`3D попередній перегляд`,viewTimelapse:`Переглянути таймлапс`,scanForTimelapse:`Знайти таймлапс`,uploadTimelapse:`Вивантажити таймлапс`,removeTimelapse:`Видалити таймлапс`,downloadSource3mf:`Завантажити вихідний файл 3MF`,uploadSource3mf:`Вивантажити вихідний файл 3MF`,replaceSource3mf:`Замінити вихідний файл 3MF`,removeSource3mf:`Видалити вихідний файл 3MF`,uploadF3d:`Вивантажити F3D`,replaceF3d:`Замінити F3D`,downloadF3d:`Завантажити F3D`,removeF3d:`Видалити F3D`,download:`Завантажити`,copyDownloadLink:`Копіювати посилання для завантаження`,qrCode:`QR-код`,viewPhotos:`Переглянути фото`,viewPhotosCount:`Переглянути фото ({{count}})`,projectPage:`Сторінка проєкту`,addToFavorites:`Додати в обране`,removeFromFavorites:`Видалити з вибраного`,edit:`Редагувати`,printLog:`Журнал друку`,goToProject:`Перейти до проєкту: {{name}}`,addToProject:`Додати до проєкту`,removeFromProject:`Видалити з проєкту`,loading:`Завантаження...`,noProjectsAvailable:`Немає доступних проєктів`,searchProjects:`Пошук проєктів…`,select:`Вибрати`,deselect:`Зняти вибір`,delete:`Видалити`},permission:{noReprint:`Ви не маєте дозволу на повторний друк цього архіву`,noAddToQueue:`Ви не маєте дозволу на додавання в чергу`,noUpdateArchives:`Ви не маєте дозволу на оновлення архівів`,noUploadFiles:`Ви не маєте дозволу на вивантаження файлів`,noDownload:`У вас немає дозволу на завантаження архівів`,noCopyLink:`Ви не маєте дозволу копіювати посилання для завантаження`,noDelete:`Ви не маєте дозволу на видалення цього архіву`,noEdit:`Ви не маєте дозволу редагувати цей запис`,noCreate:`Ви не маєте дозволу на створення архівів`},platePicker:{title:`Вибрати пластину для попереднього перегляду`,hint:`Цей архів містить кілька пластин. Виберіть одну, щоб відкрити її в переглядачі G-коду.`,plateLabel:`Пластина {{index}}`,objectCount:`Об’єктів: {{count}}`,objectCount_plural:`Об’єктів: {{count}}`,noGcode:`Цей архів не містить нарізаного G-коду для перегляду. Спочатку відкрийте його в Bambu Studio та виконайте нарізання.`},card:{previousPlate:`Попередня друкарська пластина`,nextPlate:`Наступна пластина`,plateNumber:`Пластина {{index}}`,moreOptions:`Клацніть правою кнопкою миші, щоб отримати додаткові параметри`,addToFavorites:`Додати в обране`,removeFromFavorites:`Видалити з вибраного`,cancelled:`скасовано`,failed:`не вдалося`,duplicate:`дублікат`,duplicateTitle:`Ця модель була надрукована раніше`,openSource3mf:`Відкрити вихідний файл 3MF у Bambu Studio (клацніть правою кнопкою, щоб переглянути додаткові дії)`,downloadF3d:`Завантажити файл дизайну Fusion 360`,viewTimelapse:`Переглянути сповільнену зйомку`,viewPhoto:`Переглянути 1 фото`,viewPhotos:`Переглянути фото: {{count}}`,openFolder:`Відкрити папку: {{name}}`,slicedFile:`Нарізаний файл - готовий до друку`,sourceFile:`Лише вихідний файл – зіставлення AMS недоступне`,gcode:`G-КОД`,source:`ДЖЕРЕЛО`,project:`Проєкт: {{name}}`,runsBadge:`Друків: {{count}}`,runsBadgeTitle:`Усього друків: {{count}} — успішних: {{successful}}, невдалих: {{failed}}. Натисніть, щоб переглянути повний журнал друку.`,estimated:`Приблизно: {{time}}`,actual:`Фактично: {{time}}`,accuracy:`Точність: {{percent}}%`,filament:`{{weight}} г`,layer:`{{count}} шар`,layers:`Шарів: {{count}}`,object:`{{count}} об’єкт`,objects:`Об’єктів: {{count}}`,slicedFor:`Нарізаний для {{model}}`,uploadedBy:`Вивантажив`,noPermissionReprint:`Ви не маєте дозволу на передрук`,noFileForReprint:`Файл 3MF недоступний: його не вдалося завантажити з принтера під час збереження запису про друк`,slicerAmsMapping:`Зіставлення AMS збережено ({{printer}})`,slicerAmsMappingTooltip:`Вибір слотів AMS, зроблений слайсером, збережено для принтера {{printer}}. Номери слотів мають сенс лише на ньому, тож повторний друк використає їх, тільки якщо знову спрямований на {{printer}}.`,noPermissionEdit:`Ви не маєте прав на редагування архівів`,noPermissionDelete:`Ви не маєте дозволу на видалення архівів`,openInBambuStudio:`Відкрити у слайсері`,openInBambuStudioToSlice:`Відкрити у слайсері для нарізання`,slice:`Нарізати`,externalLink:`Зовнішнє посилання`,makerWorld:`MakerWorld: {{designer}}`,viewProject:`Переглянути проєкт`,noExternalLink:`Немає зовнішнього посилання`,preview3d:`3D попередній перегляд`,download:`Завантажити`,edit:`Редагувати`,delete:`Видалити`},runLog:{title:`Журнал друку`,modalTitle:`Журнал друку — {{name}}`,modalTitleFallback:`цей архів`,empty:`Для цього архіву ще не зареєстровано жодної події друку.`,col:{date:`Дата`,status:`Статус`,duration:`Тривалість`,filament:`Філамент`,cost:`Вартість`},status:{completed:`Виконано`,failed:`Не вдалося`,cancelled:`Скасовано`,stopped:`Зупинено`,skipped:`Пропущено`,printing:`Друк`}},modal:{deleteArchive:`Видалити архів`,deleteConfirm:`Ви впевнені, що хочете видалити "{{name}}"? Цю дію не можна скасувати.`,deleteButton:`Видалити`,deletePurgeStats:`Також видалити цей друк із швидкої статистики (філамент, час, вартість, енергія)`,deleteQueueItemsWarning:`Елементи черги {{count}}, пов’язані з цим архівом, також буде видалено.`,deleteBlockedByPrinting:`Неможливо видалити — наразі друкуються елементи черги {{count}}. Спочатку зупиніть друк, а потім повторіть спробу.`,removeSource3mf:`Видалити джерело 3MF`,removeSource3mfConfirm:`Ви впевнені, що хочете видалити вихідний файл 3MF з "{{name}}"? Це призведе до видалення вихідного файлу проєкту слайсера.`,removeButton:`Видалити`,removeF3d:`Видалити F3D`,removeF3dConfirm:`Ви впевнені, що хочете видалити файл дизайну Fusion 360 із "{{name}}"?`,removeTimelapse:`Видалити Timelapse`,removeTimelapseConfirm:`Ви впевнені, що хочете видалити покадрове відео з "{{name}}"?`,timelapse:`{{name}} — таймлапс`,selectTimelapse:`Вибрати таймлапс`,selectTimelapseDesc:`Автоматичний збіг не знайдено. Виберіть покадрову зйомку для цього друку:`,deleteArchives:`Видалити архіви`,deleteArchivesConfirm:`Видалити вибрані архіви ({{count}})? Цю дію неможливо скасувати.`,deleteCount:`Видалити {{count}}`},page:{title:`Архіви`,printsCount:`Показано друків: {{filtered}} із {{total}}`,dropFilesHere:`Перетягніть файли .3mf сюди`,releaseToUpload:`Відпустіть, щоб вивантажити`,only3mfSupported:`Підтримуються лише файли .3mf.`,close:`Закрити`,selected:`Вибрано {{count}}.`,selectAll:`Вибрати усі`,tags:`Теги`,project:`Проєкт`,favorite:`В обраному`,delete:`Видалити`,toggledFavorites:`Оновлено вибране для архівів: {{count}}`,failedUpdateFavorites:`Не вдалося оновити вибране`,archivesDeleted:`Видалено архівів: {{count}}`,failedDeleteArchives:`Не вдалося видалити архіви`,photoDeleted:`Фото видалено`,failedDeletePhoto:`Не вдалося видалити фото`},list:{name:`Назва`,printer:`Принтер`,date:`Дата`,size:`Розмір`,actions:`Дії`,hasTimelapse:`Має таймлапс`},log:{date:`Дата`,printName:`Назва друку`,printer:`Принтер`,user:`Користувач`,status:`Статус`,duration:`Тривалість`,filament:`Філамент`,allPrinters:`Усі принтери`,allUsers:`Усі користувачі`,allStatuses:`Усі статуси`,cancelled:`Скасовано`,skipped:`Пропущено`,dateFrom:`Від`,dateTo:`До`,noEntries:`Записів журналу друку не знайдено`,showing:`Показано {{count}} з {{total}} записів`,rowsPerPage:`Рядків`,page:`Сторінка`,prev:`Назад`,next:`Далі`,clearLog:`Очистити журнал`,clearLogTitle:`Очистити журнал друку`,clearLogConfirm:`Усі записи журналу друку буде остаточно видалено. Архіви та елементи черги залишаться без змін. Цю дію неможливо скасувати. Продовжити?`,clearLogButton:`Очистити все`,cleared:`Очищено записів журналу: {{count}}`,clearFailed:`Не вдалося очистити журнал друку`,deleteEntryTitle:`Видалити запис журналу друку`,deleteEntryConfirm:`Запис буде видалено з журналу, а пов’язані з ним філамент, час і вартість більше не враховуватимуться у швидкій статистиці. Відповідний архів, якщо він є, залишиться без змін. Цю дію неможливо скасувати.`,entryDeleted:`Запис журналу друку видалено`,entryDeleteFailed:`Не вдалося видалити запис журналу друку`,editEntryTitle:`Редагувати запис журналу друку`,editEntryDescription:`Класифікуйте цей запуск друку. Віджет «Аналіз невдач» групує дані за цими значеннями, тому зміни одразу відобразяться у статистиці.`,entryUpdated:`Запис журналу друку оновлено`,entryUpdateFailed:`Не вдалося оновити запис журналу друку`,statuses:{completed:`Виконано`,failed:`Не вдалося`,stopped:`Зупинено`,cancelled:`Скасовано`,skipped:`Пропущено`}}},dispatchToast:{untitled:`Завдання друку`,startingPrints:`Початок друку`,progressSummary:`{{complete}}/{{total}} завершено • Обробка: {{processing}}`,expandDetails:`Розгорнути подробиці надсилання`,collapseDetails:`Згорнути відомості про відправлення`,awaitingPrinter:`Очікування принтера…`,status:{processing:`Обробка`,completed:`Виконано`,failed:`Не вдалося`},failed:{generic:`Не вдалося відправити`,upload_failed:`Не вдалося вивантажити файл на принтер`,start_command_failed:`Принтер відхилив команду запуску`},dismiss:`Відхилити`},pipelineRuns:{title:`Запуски конвеєрів`,loading:`Завантаження…`,empty:`Запусків конвеєрів ще немає.`,filter:{pipeline:`Конвеєр`,status:`Статус`,target:`Ціль`,all:`Усі`,allPipelines:`Усі конвеєри`,allStatus:`Усі статуси`,allTargets:`Усі цілі`,clear:`Очистити фільтри`,noMatches:`Жоден запуск не відповідає поточним фільтрам.`},totalCount_one:`{{n}} запуск`,totalCount_other:`Запусків: {{n}}`,copies:`Копій: {{n}}`,failedCount:`Невдалих: {{n}}`,copyN:`Копія {{n}}`,retryFailed:`Повторити невдалі`,retryOf:`повтор запуску №{{n}}`,pagination:`{{start}}–{{end}} з {{total}}`,cancelledByUser:`Скасовано користувачем`,toast:{cancelled:`Запуск скасовано`,cancelFailed:`Не вдалося скасувати`,retryStarted:`Розпочато повторну спробу`,retryFailed:`Не вдалося розпочати повторну спробу`,cleared:`Видалено запусків: {{n}}`,clearFailed:`Не вдалося очистити`},clearLog:`Очистити журнал`,clearConfirmTitle:`Очистити журнал?`,clearConfirmBody:`Видалити всі завершені, невдалі, скасовані та частково невдалі запуски конвеєрів? Активні запуски буде збережено. Цю дію неможливо скасувати.`,clearConfirmAction:`Очистити`,jobStatus:{pending:`в очікуванні`,awaiting_printer:`в очікуванні принтера`,queued:`в черзі`,printing:`друк`,completed:`завершено`,failed:`не вдалося`,cancelled:`скасовано`}},queue:{title:`Черга друку`,subtitle:`Плануйте завдання друку та керуйте ними`,filamentShort:{rowBadge:`Недостатньо філаменту для призначеної котушки`,rowTooltip:`Планувальник відправлення позначив цей елемент. Натисніть «Запустити», щоб переглянути нестачу для кожного слота й вирішити, чи друкувати попри неї.`,confirmTitle:`Недостатня кількість філаменту`,confirmIntro:`На призначеній котушці недостатньо філаменту принаймні для одного слота. Усе одно друкувати?`,lineItem:`Слот {{slot}}: потрібно {{required}} г, {{remaining}} г залишилося`,unknown:`невідомо`,printAnyway:`Усе одно друкувати`},slicerAmsMapping:{rowBadge:`Слоти AMS збережено для цього принтера`,rowTooltip:`Цей запис містить точні слоти AMS, вибрані слайсером, збережені для принтера, на який націлено це завдання. Повторний друк на ньому може використати ті самі котушки замість повторного добору за типом і кольором.`},editQueueItem:`Редагувати елемент черги`,selectAllPlates:`Вибрати всі пластини ({{count}})`,deselectAll:`Зняти вибір із усіх`,printQueued:`Друк у черзі`,printQueuedWillStartWhenIdle:`Розпочнеться, коли принтер звільниться`,itemsQueued:`Додано до черги: {{count}}`,sending:`Надсилання...`,sendingProgress:`Надсилання {{current}}/{{total}}...`,adding:`Додавання...`,addingProgress:`Додавання {{current}}/{{total}}...`,savingProgress:`Збереження {{current}}/{{total}}...`,clearQueue:`Очистити чергу`,clearHistory:`Очистити історію`,emptyQueue:`Черга порожня`,position:`Позиція`,scheduledTime:`Запланований час`,moveUp:`Перемістити вгору`,moveDown:`Перемістити вниз`,startNow:`Почати зараз`,printingInProgress:`Виконується друк...`,viewArchive:`Переглянути архів`,viewInFileManager:`Переглянути в менеджері файлів`,itemCount:`Елементів: {{count}}`,itemCount_plural:`Елементів: {{count}}`,dragToReorder:`Перетягніть, щоб змінити порядок (лише для завдань «Якнайшвидше»)`,reorderHint:`Позиція впливає лише на завдання «Якнайшвидше». Заплановані завдання запускаються у встановлений час.`,sjf:{label:`SJF`,tooltip:`SJF (спочатку найкоротше завдання) — планувальник надає пріоритет коротшим завданням друку`},addedBy:`Додав {{name}}`,nextInQueue:`Наступний у черзі`,clearPlateSuccess:`Пластина очищена — готова до наступного друку`,plateNumber:`Пластина {{index}}`,quantity:`Кількість`,quantityHint:`Буде створено елементів черги: {{count}}`,activeBatches:`Активні партії`,batchProgress:`{{completed}} з {{total}} завершено`,cancelBatch:`Скасувати решту`,batchCancelled:`Решту елементів партії скасовано`,cancelBatchConfirmTitle:`Скасувати партію`,cancelBatchConfirmMessage:`Скасувати всі елементи цієї партії, що ще очікують?`,batch:{defaultName:`Партія`,label:`Елементів: {{count}}`,label_plural:`Елементів: {{count}}`,pendingCount:`Очікують: {{count}}`,pendingCount_plural:`Очікують: {{count}}`,expand:`Розгорнути партію`,collapse:`Згорнути партію`,groupAsBatch:`Згрупувати в партію…`,groupAsBatchDescription:`Об’єднати вибрані елементи ({{count}}) в одну згортану партію.`,nameLabel:`Назва партії`,namePlaceholder:`напр. П’ятничні подарунки`,create:`Створити партію`,ungroup:`Розгрупувати`,ungroupConfirmTitle:`Розгрупувати партію?`,ungroupConfirmMessage:`Елементи залишатимуться в черзі, але більше не групуватимуться разом.`,dragGroup:`Перетягнути групу`},tabs:{queue:`Черга`,history:`Історія`,timeline:`Хронологія`,pipelines:`Запуски конвеєрів`},layout:{flatList:`Список`,byPrinter:`За принтером`,groupByPrinter:`Групувати за принтером`},history:{emptyTitle:`Історії ще немає`,emptyDescription:`Тут відображатимуться завершені, скасовані та невдалі роздруківки.`,showMore:`Показати більше`,showingCount:`Показано {{shown}} з {{total}}`},dragGhost:{multiCount:`Елементів: {{count}}`,batch:`{{name}} (копія {{count}})`,batch_plural:`{{name}} ({{count}} копій)`},sections:{currentlyPrinting:`Наразі друкується`,queued:`У черзі`,history:`Історія`},status:{pending:`В очікуванні`,waiting:`Очікування`,printing:`Друк`,paused:`Призупинено`,completed:`Виконано`,failed:`Не вдалося`,skipped:`Пропущено`,cancelled:`Скасовано`},summary:{printing:`Друк`,queued:`У черзі`,totalTime:`Загальний час у черзі`,totalWeight:`Загальна вага черги`,history:`Історія`},filter:{allPrinters:`Усі принтери`,unassigned:`Не призначено`,allStatus:`Усі статуси`,allLocations:`Усі розташування`,any:`Будь-який`},sort:{byPosition:`Сортувати за позицією`,byName:`Сортувати за назвою`,byPrinter:`Сортувати за принтером`,bySchedule:`Сортувати за розкладом`,byDate:`Сортувати за датою`,ascendingOldest:`За зростанням (найстаріші спочатку)`,descendingNewest:`За спаданням (спочатку найновіші)`},badges:{staged:`Очікує ручного запуску`,requiresPrevious:`Потрібне успішне завершення попереднього завдання`,autoPowerOff:`Автоматичне вимкнення`,gcodeInjection:`G-код`},empty:{title:`Друк не заплановано`,description:`Заплануйте друк зі сторінки «Архіви» за допомогою параметра «Розклад» у контекстному меню або перетягніть файли, щоб почати.`},time:{etaIfStartedNow:`Час завершення, якщо запустити це завдання зараз`,asap:`Якнайшвидше`,overdue:`Прострочено`,now:`Зараз`,lessThanMinute:`Менше ніж за хвилину`,inMinutes:`Через {{count}} хв`,inHours:`Через {{count}} год`},actions:{startPrint:`Розпочати друк`,stopPrint:`Зупинити друк`,requeue:`Поставити в чергу знову`},bulkEdit:{title:`Редагувати {{count}} елемент`,title_plural:`Редагувати елементи ({{count}})`,description:`Лише змінені параметри будуть застосовані до вибраних елементів.`,printer:`Принтер`,noChange:`— Без змін —`,queueOptions:`Параметри черги`,staged:`Очікує ручного запуску`,autoPowerOff:`Автоматичне вимкнення після друку`,requirePrevious:`Вимагати успішного завершення попереднього завдання`,printOptions:`Параметри друку`,bedLevelling:`Вирівнювання столу`,flowCalibration:`Калібрування потоку`,vibrationCalibration:`Калібрування вібрації`,layerInspection:`Перевірка першого шару`,timelapse:`Таймлапс`,useAms:`Використовувати AMS`,nozzleOffsetCali:`Калібрування зсуву сопла`,applyChanges:`Застосувати зміни`,selectAll:`Вибрати усі`,deselectAll:`Зняти вибір із усіх`,selected:`Вибрано: {{count}}`,editSelected:`Редагувати вибране`,cancelSelected:`Скасувати вибране`},confirm:{cancelTitle:`Скасувати запланований друк`,cancelMessage:`Ви впевнені, що бажаєте скасувати "{{name}}"?`,stopTitle:`Зупинити друк`,stopMessage:`Ви впевнені, що бажаєте зупинити поточний друк "{{name}}"? Це призведе до скасування завдання друку на принтері.`,removeTitle:`Видалити з історії`,removeMessage:`Ви впевнені, що бажаєте видалити "{{name}}" з історії черги?`,clearHistoryTitle:`Очистити історію`,clearHistoryMessage:`Видалити всі елементи з історії ({{count}})?`,cancelButton:`Скасувати друк`,stopButton:`Зупинити друк`,thisPrint:`цей друк`,thisItem:`цей елемент`},toast:{cancelled:`Пункт черги скасовано`,cancelFailed:`Не вдалося скасувати елемент`,removed:`Елемент черги видалено`,removeFailed:`Не вдалося видалити елемент`,stopped:`Друк зупинено`,stopFailed:`Не вдалося зупинити друк`,released:`Друк відправлено в чергу`,startFailed:`Не вдалося почати друк`,reorderFailed:`Не вдалося змінити порядок черги`,historyCleared:`Очищено елементів історії: {{count}}`,clearHistoryFailed:`Не вдалося очистити історію`,updateFailed:`Не вдалося оновити елементи`,bulkCancelled:`Скасовано елементів: {{count}}`,bulkCancelFailed:`Не вдалося скасувати елементи`,batchCreated:`Партію «{{name}}» створено`,batchCreateFailed:`Не вдалося створити партію`,batchUngrouped:`Розгруповано елементів: {{count}}`,batchUngroupFailed:`Не вдалося розгрупувати партію`,resumedAfterFailure:`Відновлено чергу — {{restored}} завдання відновлено до стану очікування`,resumeAfterFailureFailed:`Не вдалося відновити чергу`},resumeAfterFailure:{banner:`{{printer}} заблоковано через помилку попереднього друку — завдання {{count}} пропущено`,bannerHint:`Усуньте проблему з принтером, а потім відновіть чергу, щоб повернути пропущені завдання й зняти блокування.`,button:`Відновити після невдачі`,confirmTitle:`Відновити чергу після помилки?`,confirmMessage:`Повернути пропущені завдання ({{count}}) для {{printer}} до стану очікування та зняти блокування після невдалого попереднього друку? Переконайтеся, що принтер готовий.`},timeline:{listView:`Список`,timelineView:`Хронологія`,unassigned:`Не призначено`,noData:`На цей день немає запланованих роздруківок`,nothingCommitted:`У цьому часовому проміжку немає підтверджених розкладів. Завдання з ручним запуском, завдання в очікуванні та завдання «Якнайшвидше» для вільних принтерів тут не показано. Установіть запланований час або запустіть відкладене завдання.`,allDoneBy:`Орієнтовне завершення всіх друків: {{time}}`,staged:`Очікує ручного запуску`,filterAll:`Показати все`,filterPrinting:`Друк`,filterQueued:`У черзі`,time:{anyMoment:`будь-якої миті`,minutesLeft:`Залишилося {{minutes}} хв`,hoursLeft:`Залишилося {{hours}} год`,hoursMinutesLeft:`Залишилося {{hours}} год {{minutes}} хв`},day:{previous:`Попередній день`,next:`Наступний день`,today:`Сьогодні`},window:{back12h:`Назад 12 годин`,forward12h:`Уперед на 12 годин`,now:`Зараз`},printerColumnHeader:`Принтер`},permissions:{noStopPrint:`Ви не маєте дозволу зупиняти друк`,noStartPrint:`Ви не маєте дозволу розпочинати друк`,noEdit:`Ви не маєте дозволу редагувати цей елемент черги`,noCancel:`Ви не маєте дозволу скасувати цей елемент черги`,noRequeue:`Ви не маєте дозволу повторно ставити елементи в чергу`,noRemove:`Ви не маєте дозволу на видалення цього елемента черги`,noClearHistory:`Ви не маєте дозволу очистити всю історію`,noEditItems:`Ви не маєте дозволу редагувати елементи черги`,noCancelItems:`Ви не маєте дозволу на скасування елементів черги`}},stats:{title:`Статистика`,subtitle:`Перетягніть віджети, щоб змінити порядок. Натисніть значок ока, щоб приховати.`,overview:`Огляд`,totalPrints:`Загальна кількість друків`,successRate:`Коефіцієнт успішності`,totalPrintTime:`Загальний час друку`,printTime:`Час друку`,totalFilament:`Загальна кількість використаного філаменту`,filamentUsed:`Використано філаменту`,filamentCost:`Вартість філаменту`,totalCost:`Загальна вартість`,energyUsed:`Використана енергія`,energyCost:`Вартість енергії`,energyWarmingUpTooltip:`Відстеження енергії все ще збирає щогодинні знімки. Підсумкові показники за діапазон дат стануть точними, коли існує принаймні один знімок до вибраного діапазону. Ранні значення можуть бути заниженими.`,averagePrintTime:`Середній час друку`,printsPerDay:`Друків на день`,byPrinter:`За принтером`,printsByPrinter:`Друки за принтерами`,byMaterial:`За матеріалом`,byMonth:`За місяцями`,last7Days:`Останні 7 днів`,last30Days:`Останні 30 днів`,last90Days:`Останні 90 днів`,allTime:`За весь час`,quickStats:`Швидка статистика`,printActivity:`Активність друку`,filamentTypes:`Типи філаментів`,filamentTrends:`Тенденції філаменту`,failureAnalysis:`Аналіз невдач`,timeAccuracy:`Точність оцінки часу`,successful:`Успішно:`,failed:`Невдало:`,cancelled:`Скасовано:`,perfectEstimate:`100% = ідеальна оцінка`,noTimeAccuracyData:`Даних про точність часу ще немає`,noFilamentData:`Немає даних про філамент`,noPrinterData:`Дані принтера відсутні`,noPrintData:`Немає даних про друк`,noPrintDataLast30Days:`Немає даних про друк за останні 30 днів`,failureReasons:`Причини невдач`,topFailureReasons:`Основні причини невдач`,failedPrintsCount:`Невдалих друків: {{failed}} із {{total}}`,lastWeekRate:`Минулого тижня: {{rate}}%`,resetLayout:`Скинути макет`,recalculateCosts:`Перерахувати витрати`,recalculateCostsHint:`Перерахувати вартість усіх архівних друків за поточними цінами на філамент`,exportStats:`Експортувати статистику`,exportAsCsv:`Експортувати як CSV`,exportAsExcel:`Експортувати як Excel`,hiddenCount:`Приховано: {{count}}`,exportDownloaded:`Експорт завантажено`,exportFailed:`Помилка експорту`,layoutReset:`Розташування віджетів скинуто`,recalculatedCosts:`Перераховано вартість архівів: {{count}}`,recalculateFailed:`Не вдалося перерахувати витрати`,loadingStats:`Завантаження статистики...`,noPermissionResetLayout:`Ви не маєте дозволу на скидання макета`,noPermissionRecalculate:`Ви не маєте дозволу на перерахунок витрат`,noPrintDataInRange:`У вибраному діапазоні немає даних про друк`,periodFilament:`Філамент за період`,periodCost:`Вартість періоду`,avgPerPrint:`Середнє на друк`,usageOverTime:`Використання в часі`,energyOverTime:`Споживання енергії в часі`,filamentByWeight:`Вага`,printDuration:`Тривалість друку`,printerUtilization:`Використання принтера`,filamentSuccess:`Успіх за матеріалом`,printHabits:`Звички друку`,printTimeOfDay:`Розподіл друків за часом доби`,colorDistribution:`Розподіл кольору`,noColorData:`Немає даних про колір`,records:`Записи`,longestPrint:`Найтриваліший друк`,heaviestPrint:`Найважчий друк`,mostExpensivePrint:`Найдорожчий`,busiestDay:`Найзавантаженіший день`,successStreak:`Серія успішних друків`,streakPrint:`успішний друк поспіль`,streakPrints:`Успішних друків поспіль: {{count}}`,printerStats:`Статистика принтера`,hours:`год`,avgPrints:`Середня кількість друків`,noArchiveData:`Немає даних про друк`,filamentByTime:`Час`,avgWeight:`Середня вага`,avgTime:`Середній час`,filamentByPrints:`Друки`,timeframe:{today:`Сьогодні`,"this-week":`Цей тиждень`,"this-month":`Цей місяць`,"last-7":`Останні 7 днів`,"last-30":`Останні 30 днів`,"last-90":`Останні 90 днів`,"this-year":`Цього року`,"all-time":`За весь час`,custom:`Власний діапазон`,from:`Від`,to:`До`},allUsers:`Усі користувачі`,noUser:`Немає користувача (система)`,filterByUser:`Фільтрувати за користувачем`},maintenance:{title:`Технічне обслуговування`,overview:`Огляд`,allOk:`Усі роботи з технічного обслуговування виконано`,dueCount:`Потрібне обслуговування: {{count}}`,dueCount_plural:`Потрібне обслуговування: {{count}}`,warningCount:`{{count}} попередження`,warningCount_plural:`{{count}} попередження`,totalPrintTime:`Загальний час друку`,nextMaintenance:`Наступне технічне обслуговування`,nothingDue:`Обслуговування не потрібне`,tasks:`Завдання`,lastPerformed:`Востаннє виконано`,interval:`Інтервал`,hoursRemaining:`Залишилося {{hours}} год`,hoursOverdue:`Прострочено на {{hours}} год`,markDone:`Позначити як виконане`,performMaintenance:`Виконати технічне обслуговування`,history:`Історія`,noHistory:`Історії обслуговування немає`,editPrintHours:`Змінити години друку`,currentHours:`Поточна кількість годин`,statusTab:`Статус`,settingsTab:`Налаштування`,overdueCount:`{{count}} прострочено`,dueSoonCount:`{{count}} незабаром`,dueSoon:`Незабаром`,allGood:`Все добре`,overdueBy:`Прострочено на {{duration}}`,dueIn:`Через {{duration}}`,timeLeft:`Залишилося {{duration}}`,day:`1 день`,days:`{{count}} днів`,week:`1 тиждень`,weeks:`{{count}} тижнів`,month:`1 місяць`,months:`{{count}} місяців`,year:`1 рік`,maintenanceTypes:`Види технічного обслуговування`,maintenanceTypesDescription:`Системні та власні завдання технічного обслуговування`,addCustomType:`Додати спеціальний тип`,restoreDefaults:`Відновити завдання за замовчуванням`,intervalType:`Тип інтервалу`,intervalValue:`Інтервал ({{type}})`,icon:`значок`,documentationLink:`Посилання на документацію (необов’язково)`,assignToPrinters:`Призначити принтерам`,selectAtLeastOnePrinter:`Вибрати принаймні один принтер`,addType:`Додати тип`,custom:`Власне`,printHours:`Години друку`,calendarDays:`Календарні дні`,exampleName:`наприклад, Замінити HEPA-фільтр`,viewDocumentation:`Переглянути документацію`,timeBasedInterval:`Часовий інтервал`,intervalOverrides:`Перевизначення інтервалів`,intervalOverridesDescription:`Налаштувати інтервали для конкретних принтерів`,assignedToPrinters:`Призначено для принтерів:`,noPrintersAssigned:`Принтерів не призначено`,addPrinterShort:`Додати:`,printersAssignedClick:`Призначено принтерів: {{count}} — натисніть, щоб керувати`,removeFromPrinter:`Видалити з цього принтера`,types:{lubricateCarbonRods:`Змастити карбонові стрижні`,lubricateRails:`Змастити лінійні напрямні`,cleanNozzle:`Очистити сопло/хотенд`,checkBelts:`Перевірити натяг ременів`,cleanBuildPlate:`Очистити друкарську пластину`,checkExtruder:`Перевірити шестерні екструдера`,checkCooling:`Перевірити вентилятори охолодження`,generalInspection:`Загальний огляд`,cleanCarbonRods:`Очистити карбонові стрижні`,lubricateSteelRods:`Змастити сталеві стрижні`,cleanSteelRods:`Очистити сталеві стрижні`,cleanLinearRails:`Очистити лінійні напрямні`,checkPtfeTube:`Перевірити PTFE-трубку`,replaceHepaFilter:`Замінити HEPA-фільтр`,replaceCarbonFilter:`Замінити вугільний фільтр`,lubricateLeftNozzleRail:`Змастити ліву напрямну сопла`},maintenanceComplete:`Технічне обслуговування позначено як завершене`,typeUpdated:`Оновлено тип обслуговування`,typeDeleted:`Тип обслуговування видалено`,defaultsRestored:`Відновлено завдання за замовчуванням {{count}}`,printHoursUpdated:`Години друку оновлено`,printerAssigned:`Принтер призначено`,printerRemoved:`Принтер видалено`,deleteTypeConfirm:`Видалити "{{name}}"?`,deleteSystemTypeTitle:`Видалити завдання обслуговування за умовчанням?`,deleteSystemTypeMessage:`Ви впевнені, що бажаєте видалити стандартне завдання обслуговування "{{name}}"?`,noPermissionUpdate:`Ви не маєте дозволу на оновлення елементів обслуговування`,noPermissionPerform:`Ви не маєте дозволу на проведення технічного обслуговування`,noPermissionEditTypes:`Ви не маєте дозволу редагувати типи обслуговування`,noPermissionDeleteTypes:`Ви не маєте дозволу на видалення типів обслуговування`,noPermissionEditHours:`Ви не маєте дозволу редагувати години друку`,noPermissionRemovePrinter:`Ви не маєте дозволу на видалення призначень принтера`,noPermissionAssignPrinter:`Ви не маєте дозволу призначати принтери`,noPermissionEditIntervals:`Ви не маєте дозволу редагувати інтервали`,configureSettings:`Налаштувати типи та інтервали технічного обслуговування`},settings:{title:`Налаштування`,general:`Загальні`,tabs:{general:`Загальні`,smartPlugs:`Розумні розетки`,notifications:`Сповіщення`,queue:`Робочий процес`,queueDispatch:`Черга та відправка`,queuePipelines:`Конвеєри`,filament:`Філамент`,network:`Мережа`,apiKeys:`Ключі API`,virtualPrinter:`Віртуальний принтер`,spoolbuddy:`SpoolBuddy`,failureDetection:`Виявлення несправностей`,users:`Автентифікація`,backup:`Резервне копіювання`,emailAuth:`Автентифікація електронної пошти`,ldap:`LDAP`,twoFa:`Двофакторна автентифікація`,oidc:`SSO / OIDC`,security:`Безпека`},spoolbuddy:{infoTitle:`Пристрої SpoolBuddy`,infoBody:`Термінали SpoolBuddy автоматично реєструються за допомогою сигналів стану. Скасуйте реєстрацію пристрою, якщо він більше не використовується або після збою служби залишився застарілий дублікат.`,duplicatesTitle:`Зареєстровано пристроїв: {{count}}`,duplicatesBody:`Інтерфейс термінала використовує лише перший зареєстрований пристрій. Якщо один із записів є застарілим дублікатом після збою, скасуйте його реєстрацію. Пристрій у мережі зареєструється знову під час наступного сигналу стану.`,empty:`Ще немає зареєстрованих пристроїв SpoolBuddy.`,online:`Онлайн`,offline:`Не в мережі`,unregister:`Скасувати реєстрацію`,unregisterSuccess:`Реєстрацію пристрою скасовано`,unregisterError:`Не вдалося скасувати реєстрацію пристрою`,confirmTitle:`Скасувати реєстрацію пристрою SpoolBuddy?`,confirmBody:`Пристрій «{{hostname}}» ({{deviceId}}) буде видалено з бази даних. Якщо він у мережі, то зареєструється знову під час наступного сигналу стану.`,ipAddress:`IP-адреса`,firmware:`Прошивка`,lastSeen:`Востаннє в мережі`,daemonUptime:`Час роботи демона`,systemUptime:`Час роботи системи`,never:`Ніколи`,nfc:`NFC`,scale:`Ваги`,cpuTemp:`Температура ЦП`,cpuLoad:`Завантаження ЦП`,memory:`Пам’ять`,disk:`Диск`,update:`Оновити`,updateConfirmTitle:`Оновити демон Spoolbuddy?`,updateConfirmBody:`Запустити оновлення програмного забезпечення на "{{hostname}}"? Щойно оновлення буде застосовано, демон перезапуститься.`,restartBrowser:`Перезапустити браузер`,restartBrowserConfirmTitle:`Перезапустити веб-переглядач термінала?`,restartBrowserConfirmBody:`Перезапустити веб-переглядач кіоску на "{{hostname}}"? Дисплей на короткий час згасне.`,restartDaemon:`Перезапустити службу`,restartDaemonConfirmTitle:`Перезапустити демон Spoolbuddy?`,restartDaemonConfirmBody:`Перезапустити демон Spoolbuddy на "{{hostname}}"? Пристрій вийде з мережі на кілька секунд.`,reboot:`Перезавантажити`,rebootConfirmTitle:`Перезавантажити пристрій?`,rebootConfirmBody:`Перезавантажити «{{hostname}}»? Пристрій буде офлайн приблизно хвилину.`,shutdown:`Вимкнути`,shutdownConfirmTitle:`Вимкнути пристрій?`,shutdownConfirmBody:`Вимкнути "{{hostname}}"? Щоб увімкнути його, вам знадобиться фізичний доступ.`,commandConfirm:`Підтвердити`,commandQueued:`Команда в черзі`,commandError:`Не вдалося надіслати команду`},ldap:{title:`Автентифікація LDAP`,enabledDesc:`Автентифікація LDAP увімкнена`,disabledDesc:`Автентифікація LDAP вимкнена`,disabledHint:`Налаштуйте та збережіть налаштування LDAP нижче, а потім увімкніть.`,enabled:`LDAP автентифікація ввімкнена`,disabled:`LDAP автентифікація вимкнена`,feature1:`Користувачі можуть входити за допомогою облікових даних LDAP.`,feature2:`Обліковий запис локального адміністратора залишається резервним`,feature3:`Групи LDAP зіставляються з групами BamBuddy під час входу`,serverConfig:`Налаштування сервера LDAP`,serverUrl:`URL сервера`,serverUrlHint:`Використовуйте ldaps:// для SSL або ldap:// із StartTLS`,security:`Безпека`,securityHint:`StartTLS оновлює звичайне підключення до TLS. LDAPS використовує TLS із самого початку.`,bindDn:`DN прив’язки (службовий обліковий запис)`,bindPassword:`Пароль прив’язки`,searchBase:`Базовий DN пошуку`,userFilter:`Фільтр пошуку користувача`,userFilterHint:`{username} буде замінено на ім’я користувача, введене під час входу. Для OpenLDAP використовуйте (uid={username}).`,advanced:`Розширені налаштування`,autoProvision:`Автоматично створювати користувачів`,autoProvisionHint:`Автоматично створювати обліковий запис BamBuddy після першого входу LDAP.`,defaultGroup:`Група за замовчуванням`,defaultGroupNone:`— Немає (без резервної групи) —`,defaultGroupHint:`Запасна група призначається, коли користувач LDAP автентифікується, але його немає в списку жодної зіставленої групи LDAP. Залиште порожнім, щоб залишити непризначених користувачів без дозволів.`,groupMapping:`Зіставлення груп (JSON)`,groupMappingHint:`Зіставте DN груп LDAP із групами BamBuddy. Доступні групи: `,testConnection:`Перевірити підключення`,settingsSaved:`Налаштування LDAP збережено`,errors:{serverRequired:`Потрібна URL-адреса сервера LDAP`,searchBaseRequired:`Потрібен базовий DN пошуку`,enableAuthFirst:`Спочатку ввімкніть автентифікацію`,configureLdapFirst:`Спочатку збережіть налаштування LDAP.`}},email:{smtpSettings:`Налаштування SMTP`,smtpHost:`Сервер SMTP`,smtpPort:`Порт SMTP`,security:`Безпека`,authentication:`Автентифікація`,username:`Ім’я користувача`,password:`Пароль`,fromEmail:`Адреса відправника`,fromName:`Ім’я відправника`,testConnection:`Перевірити підключення SMTP`,testRecipient:`Електронна адреса тестового одержувача`,sendTest:`Надіслати тестовий електронний лист`,sending:`Надсилання...`,save:`Зберегти налаштування`,saving:`Збереження...`,advancedAuth:`Розширена автентифікація`,advancedAuthEnabled:`Розширену автентифікацію ввімкнено`,advancedAuthEnabledDesc:`Функції керування користувачами на основі електронної пошти активні. Нові користувачі отримають автоматично згенеровані паролі електронною поштою, і користувачі зможуть скинути свої паролі за допомогою функції «Забутий пароль».`,advancedAuthDisabled:`Розширену автентифікацію вимкнено`,advancedAuthDisabledDesc:`Увімкніть розширену автентифікацію, щоб активувати функції електронної пошти для керування користувачами.`,enable:`Увімкнути`,disable:`Вимкнути`,feature1:`Паролі генеруються автоматично та надсилаються новим користувачам електронною поштою`,feature2:`Користувачі можуть входити за іменем користувача або електронною адресою`,feature3:`Доступна функція «Забув пароль».`,feature4:`Адміністратори можуть скинути паролі користувачів електронною поштою`,errors:{requiredFields:`Заповніть усі обов’язкові поля`,usernameRequired:`Якщо ввімкнено автентифікацію, потрібне ім’я користувача`,enterTestEmail:`Введіть тестову електронну адресу`,smtpServerAndEmail:`Перед перевіркою вкажіть SMTP-сервер і адресу відправника`,usernamePasswordRequired:`Якщо ввімкнено автентифікацію, потрібні ім’я користувача та пароль`,configureSmtpFirst:`Спочатку налаштуйте та перевірте параметри SMTP`,enableAuthFirst:`Щоб використовувати функції електронної пошти, спочатку ввімкніть автентифікацію.`},success:{settingsSaved:`Налаштування SMTP успішно збережено`},securityOptions:{starttls:`STARTTLS (порт 587)`,ssl:`SSL/TLS (порт 465)`,none:`Без шифрування (порт 25)`},authOptions:{enabled:`Увімкнено`,disabled:`Вимкнено`}},appearance:`Зовнішній вигляд`,notifications:`Сповіщення`,smartPlugs:`Розумні розетки`,spoolman:`Spoolman`,updates:`Оновлення`,language:`Мова`,languageDescription:`Виберіть бажану мову`,theme:`Тема`,themeLight:`Світла`,themeDark:`Темна`,themeSystem:`Системна`,defaultView:`Початкове подання`,defaultViewDescription:`Сторінка, яка відображатиметься під час відкриття програми`,checkForUpdates:`Перевірити наявність оновлень`,autoUpdate:`Автоматичне оновлення`,currentVersion:`Поточна версія`,latestVersion:`Остання версія`,upToDate:`У вас установлено останню версію`,updateAvailable:`Доступне оновлення`,notificationLanguage:`Мова сповіщень`,notificationLanguageDescription:`Мова для push-повідомлень`,bedCooledThreshold:`Поріг охолодження столу`,bedCooledThresholdDescription:`Температура, нижче якої стіл вважається охолодженим після друку`,userNotificationsEnabled:`Сповіщення користувача`,userNotificationsEnabledDescription:`Увімкніть меню сповіщень користувача та сповіщення електронною поштою про події завдань друку. Потрібна розширена автентифікація.`,userNotificationsDisabledHint:`Увімкніть розширену автентифікацію, щоб використовувати сповіщення користувачів.`,notificationProviders:`Служби сповіщень`,addProvider:`Додати службу`,editProvider:`Редагувати службу`,providerType:`Тип служби`,testNotification:`Перевірити сповіщення`,testSuccess:`Тестове сповіщення успішно надіслано`,testFailed:`Не вдалося надіслати тестове сповіщення`,quietHours:`Період тиші`,quietHoursDescription:`Не надсилати сповіщень у цей період`,quietHoursStart:`Початок`,quietHoursEnd:`Кінець`,events:{title:`Події сповіщень`,printStart:`Друк розпочато`,printComplete:`Друк завершено`,printFailed:`Помилка друку`,printStopped:`Друк зупинено`,printProgress:`Етапи виконання`,printProgressDescription:`Сповіщати після досягнення 25%, 50% і 75%`,printerOffline:`Принтер не в мережі`,printerError:`Помилка принтера`,filamentLow:`Мало філаменту`,maintenanceDue:`Потрібне технічне обслуговування`,maintenanceDueDescription:`Повідомити, коли потрібне обслуговування`},smartPlug:{title:`Розумні розетки`,add:`Додати розумну розетку`,edit:`Редагувати розумну розетку`,name:`Назва`,ipAddress:`IP-адреса`,linkedPrinter:`Пов’язаний принтер`,autoOn:`Автоматичне ввімкнення`,autoOnDescription:`Увімкнути на початку друку`,autoOff:`Автоматичне вимкнення`,autoOffDescription:`Вимкнути після завершення друку`,offDelay:`Затримка вимкнення`,offDelayMinutes:`Хвилини після завершення друку`,offDelayTemp:`Коли температура сопла нижча за задану`,currentState:`Поточний стан`,turnOn:`Увімкнути`,turnOff:`Вимкнути`},filamentTracking:`Облік філаменту`,filamentTrackingDesc:`Виберіть спосіб обліку котушок філаменту. Можна використовувати вбудований інвентар або підключити зовнішній сервер Spoolman.`,autoAddUnknownRfid:`Автоматично додавати невідомі RFID-котушки`,autoAddUnknownRfidDesc:`Автоматично створювати запис інвентарю, коли виявлено котушку з невідомою RFID-міткою. Вимкніть, якщо ви заздалегідь реєструєте нові котушки вручну, щоб уникнути дублікатів.`,filamentChecks:`Перевірки філаменту`,disableFilamentWarnings:`Вимкнути попередження про філамент`,disableFilamentWarningsDesc:`Не показувати попередження про недостатню кількість філаменту під час запуску друку або додавання до черги`,preferLowestFilament:`Віддавати перевагу котушці з найменшим залишком`,preferLowestFilamentDesc:`Якщо підходять кілька котушок, використовувати котушку з найменшим залишком філаменту`,preferLowestFilamentBackupNote:`Діє лише тоді, коли на принтері ввімкнено AMS Filament Backup. Інакше після вичерпання вибраної котушки принтер не зможе перейти на другу.`,trackingModeBuiltIn:`Вбудований інвентар`,trackingModeBuiltInDesc:`Автоматичне зіставлення за RFID та облік використання`,trackingModeSpoolmanDesc:`Зовнішній сервер керування філаментом`,builtInFeatureRfid:`Автоматично виявляє RFID-котушки Bambu Lab в AMS`,builtInFeatureUsage:`Обліковує витрати філаменту для кожного друку`,builtInFeatureCatalog:`Керування котушками, кольорами та профілями K-фактора`,builtInFeatureThirdParty:`Котушки сторонніх виробників можна пов’язувати з котушками інвентарю`,amsSyncButton:`Синхронізувати масу з AMS`,amsSyncTitle:`Синхронізація маси котушок з AMS`,amsSyncMessage:`Масу всіх котушок інвентарю буде перезаписано відповідно до поточних значень залишку у відсотках, отриманих з AMS підключених принтерів. Скористайтеся цим для відновлення пошкоджених даних про масу. Принтери мають бути в мережі.`,amsSyncing:`Синхронізація...`,amsSyncSuccess:`Синхронізовано: {{synced}}; пропущено: {{skipped}}`,amsSyncError:`Не вдалося синхронізувати масу з AMS`,spoolmanAmsSyncButton:`Синхронізувати масу котушок Spoolman з AMS`,spoolmanAmsSyncTitle:`Синхронізація маси котушок Spoolman з AMS`,spoolmanAmsSyncMessage:`Масу всіх котушок Spoolman буде оновлено відповідно до поточних значень залишку в AMS підключених принтерів. Принтери мають бути в мережі.`,spoolmanAmsSyncing:`Синхронізація...`,spoolmanAmsSyncSuccess:`Синхронізовано: {{synced}}; пропущено: {{skipped}}`,spoolmanAmsSyncError:`Не вдалося синхронізувати масу котушок Spoolman з AMS`,spoolmanAmsSyncErrorUnreachable:`Не вдалося синхронізувати масу котушок Spoolman: сервер Spoolman недоступний`,spoolmanAmsSyncErrorNotConfigured:`Не вдалося синхронізувати масу котушок Spoolman: сервер Spoolman не налаштовано`,spoolmanNotConfigured:`Spoolman не налаштовано`,spoolmanFilamentCatalogTitle:`Каталог філаментів Spoolman`,spoolmanFilamentCatalogDesc:`Назви філаментів і вага тари з вашого екземпляра Spoolman. Тут можна редагувати назву та вагу котушки; усі інші властивості керуються безпосередньо в Spoolman.`,spoolmanUrl:`Spoolman URL`,spoolmanUrlHint:`URL вашого сервера Spoolman (наприклад, http://localhost:7912)`,spoolmanConnected:`Підключено`,spoolmanDisconnected:`Відключено`,status:`Статус`,connect:`Підключитися`,disconnect:`Від’єднатися`,howSyncWorks:`Як працює синхронізація`,syncInfoRfidOnly:`Синхронізуються лише офіційні котушки Bambu Lab із RFID.`,syncInfoAutoCreate:`Нові котушки автоматично створюються в Spoolman під час першої синхронізації`,syncInfoThirdPartySkipped:`Котушки не від Bambu Lab — сторонні або повторно заправлені — пропускаються`,linkingExistingSpools:`Зв’язування існуючих котушок`,linkingExistingSpoolsDesc:`Щоб пов’язати наявні котушки Spoolman з AMS, наведіть вказівник на слот AMS і натисніть «Пов’язати зі Spoolman».`,syncMode:`Режим синхронізації`,syncModeAuto:`Автоматичний`,syncModeManual:`Тільки вручну`,syncModeAutoDesc:`Дані AMS синхронізуються автоматично після виявлення змін`,syncModeManualDesc:`Синхронізувати лише вручну`,syncAmsData:`Синхронізувати дані AMS`,syncAmsDataDesc:`Вручну синхронізувати дані AMS принтера зі Spoolman`,allPrinters:`Усі принтери`,noDefaultPrinter:`Немає умовчання (запитувати щоразу)`,sidebarOrder:`Порядок бічної панелі`,saveThumbnails:`Зберегти мініатюри`,captureFinishPhoto:`Зробити фото після завершення`,noPrintersConfigured:`Принтери не налаштовані`,archiveMode:{always:`Завжди створювати запис архіву`,never:`Ніколи не створювати запис архіву`,ask:`Запитувати щоразу`},checkForUpdatesLabel:`Перевірити наявність оновлень`,checkPrinterFirmware:`Перевірити прошивку принтера`,includeBetaUpdates:`Включати бета-версії`,includeBetaUpdatesDesc:`Повідомляти про бета-версії та попередні версії під час перевірки оновлень`,localLogin:{disable:`Вимкнути локальний вхід за іменем користувача й паролем`,disableHint:`Якщо ввімкнено, увійти можна буде лише через постачальників SSO. На LDAP це не впливає. Щоб зберегти резервний спосіб входу, установіть на сервері BAMBUDDY_LOCAL_LOGIN=true.`},enableRetry:`Увімкнути повторну спробу`,homeAssistantDescription:`Керуйте розумними розетками через Home Assistant`,environmentManagedLabel:`(Кероване середовище)`,autoEnabledViaEnv:`Автоматично вмикається через змінні середовища`,urlFromEnvReadOnly:`Значення, встановлене змінною середовища HA_URL (лише читання)`,tokenFromEnvReadOnly:`Значення, установлене змінною середовища HA_TOKEN (лише читання)`,mqttConnectedTo:`Підключено до`,prometheusDescription:`Надавати дані принтерів у форматі Prometheus`,noSmartPlugsTitle:`Розумні розетки не налаштовано`,noSmartPlugsDescription:`Додайте розумну розетку на базі Tasmota, щоб відстежувати споживання енергії та автоматизувати керування живленням.`,noProvidersTitle:`Постачальники не налаштовані`,noProvidersDescription:`Додайте постачальника, щоб отримувати сповіщення.`,noTemplatesAvailable:`Немає доступних шаблонів. Перезапустіть серверну частину, щоб створити стандартні шаблони.`,apiPermissionView:`Перегляд стану принтера та черги`,apiPermissionEdit:`Додавання та видалення елементів із черги друку`,apiKeysEmptyTitle:`Немає ключів API`,apiKeysEmptyDescription:`Створіть ключ API для інтеграції із зовнішніми службами.`,noUsersFound:`Користувачів не знайдено`,noGroupsFound:`Групи не знайдено`,noGroupsAvailable:`Немає доступних груп`,passwordsDoNotMatch:`Паролі не збігаються`,systemGroupWarning:`Назви системних груп не можна змінювати`,authDisabledTitle:`Автентифікація вимкнена`,authDisabledFeature1:`Вимагати входу для доступу до системи`,authDisabledFeature2:`Створювати кількох користувачів із дозволами на основі груп`,authDisabledFeature3:`Керувати доступом за допомогою понад 50 окремих дозволів`,userHasCreated:`Цей користувач створив:`,userItemsQuestion:`Що зробити з цими елементами?`,deleteUserConfirm:`Ви впевнені, що хочете видалити цього користувача?`,actionCannotBeUndone:`Цю дію не можна скасувати.`,addFirstSmartPlug:`Додати першу розумну розетку`,providers:`Постачальники`,log:`Журнал`,testAll:`Перевірити все`,testResults:`Результати тестування`,testPassedCount:`{{count}} пройдено`,testFailedCount:`{{count}} не вдалося`,messageTemplates:`Шаблони повідомлень`,messageTemplatesDescription:`Налаштуйте текст сповіщень для кожної події.`,apiKeys:`Ключі API`,apiKeysDescription:`Створіть ключі API для зовнішніх інтеграцій і веб-хуків.`,createKey:`Створити ключ`,apiKeyCreated:`Ключ API створено успішно`,apiKeyCopyWarning:`Скопіюйте цей ключ зараз — його більше не буде показано!`,useInApiBrowser:`Використати в оглядачі API`,apiKeyQrButton:`QR-код`,apiKeyQrTitle:`Відскануйте для налаштування`,apiKeyQrCaption:`Скануйте за допомогою мобільного додатка, щоб додати цей сервер і ключ API.`,apiKeyQrWarning:`Містить ваш секретний ключ API. Не передавайте його іншим і не зберігайте знімки екрана там, де їх можуть побачити сторонні.`,createNewApiKey:`Створити новий ключ API`,keyName:`Назва ключа`,keyNamePlaceholder:`наприклад, Home Assistant, OctoPrint`,readStatus:`Читати статус`,readStatusDescription:`Перегляд стану принтера та черги`,manageQueue:`Керувати чергою`,manageQueueDescription:`Додавання та видалення елементів із черги друку`,controlPrinter:`Керування принтером`,controlPrinterDescription:`Призупинення, відновлення та зупинка друку`,manageLibrary:`Керувати бібліотекою`,manageLibraryDescription:`Вивантажувати, перейменовувати й видаляти файли бібліотеки; імпортувати моделі з MakerWorld`,manageInventory:`Керувати інвентарем`,manageInventoryDescription:`Створення, оновлення та видалення котушок і записів інвентарю. Потрібно для кіосків SpoolBuddy: сканування NFC, покази ваг і системні команди кіоску.`,manageMaintenance:`Керувати технічним обслуговуванням`,manageMaintenanceDescription:`Реєстрація завершеного технічного обслуговування, скидання лічильників, редагування інтервалів і керування каталогом технічного обслуговування. Підходить для автоматизації Home Assistant, яка записує «Я очистив сопло», не надаючи ширшого контролю над принтером.`,manageArchives:`Керувати архівами`,manageArchivesDescription:`Редагувати та видаляти архіви друку, у тому числі видаляти старі друки. Не включає очищення їхнього статистичного внеску. Підходить для автоматизації, яка обрізає історію друку.`,manageProjects:`Керувати проєктами`,manageProjectsDescription:`Створюйте, оновлюйте та видаляйте проєкти, додавайте до них архіви. Підходить для автоматизації, яка організовує друк у проєкти.`,libraryBadge:`Бібліотека`,inventoryBadge:`Інвентар`,maintenanceBadge:`Технічне обслуговування`,archivesBadge:`Архіви`,projectsBadge:`Проєкти`,cloudAccess:`Дозволити доступ до хмари`,cloudAccessDescription:`Дозволити читати від вашого імені профілі та філаменти Bambu Cloud. Потрібен вхід у Bambu Cloud.`,cloudBadge:`Хмара`,updateEnergyCost:`Оновлювати ціну електроенергії`,updateEnergyCostDescription:`Дозволити цьому ключу надсилати нову ціну електроенергії за кВт·год до /settings/electricity-price. Це корисно для автоматизацій Home Assistant із динамічними тарифами (Tibber, Octopus тощо). Це єдине поле налаштувань, яке можна змінювати за допомогою ключа API.`,energyCostBadge:`Енергія`,legacyKey:`Застарілий`,legacyKeyTooltip:`Створено до отримання права власності на користувача; повторно створити, щоб використовувати доступ до хмари`,unnamedKey:`Безіменний ключ`,lastUsed:`Останнє використання`,read:`Читання`,control:`Керування`,createFirstKey:`Створити перший ключ`,webhookEndpoints:`Кінцеві точки вебхуків`,webhookApiKeyHint:`Використовуйте свій ключ API у заголовку X-API-Key.`,webhook:{getAllStatus:`Отримати весь стан принтера`,getSpecificStatus:`Отримати певний стан принтера`,addToQueue:`Додати до черги друку`,pausePrint:`Призупинити друк`,resumePrint:`Відновити друк`,stopPrint:`Зупинити друк`},apiBrowser:`Оглядач API`,apiBrowserDescription:`Переглядайте й перевіряйте всі доступні кінцеві точки API.`,apiKeyForTesting:`Ключ API для тестування`,apiKeyPlaceholder:`Вставте сюди свій ключ API, щоб перевірити автентифіковані кінцеві точки...`,apiKeyHint:`Цей ключ буде надіслано як заголовок X-API-Key із запитами.`,deleteApiKeyTitle:`Видалити ключ API`,deleteApiKeyMessage:`Ви впевнені, що хочете видалити цей ключ API? Будь-які інтеграції за допомогою цього ключа перестануть працювати.`,deleteKey:`Видалити ключ`,amsDisplayThresholds:`Пороги індикаторів AMS`,amsThresholdsDescription:`Налаштуйте колірні пороги для індикаторів вологості та температури AMS.`,humidity:`Вологість`,goodGreen:`Добре (зелений)`,fairOrange:`Задовільний (помаранчевий)`,aboveFairBad:`Значення вище задовільного порога відображається червоним (погано)`,fairAlsoDryingThreshold:`Цей поріг також використовується для запуску автоматичного сушіння, якщо його ввімкнено`,temperature:`Температура`,goodBlue:`Добре (синій)`,aboveFairHot:`Значення вище задовільного порога відображається червоним (гаряче)`,historyRetention:`Збереження історії`,keepSensorHistory:`Зберігати історію датчиків для`,historyRetentionDescription:`Старіші дані про вологість і температуру буде автоматично видалено`,defaultPrintOptions:`Параметри друку за умовчанням`,defaultPrintOptionsDescription:`Установіть типові значення параметрів для нових завдань друку. Їх можна змінити для окремого завдання в діалоговому вікні друку.`,defaultBedLevelling:`Вирівнювання столу`,defaultBedLevellingDesc:`Автоматичне вирівнювання столу перед друком`,defaultFlowCali:`Калібрування потоку`,defaultFlowCaliDesc:`Калібрувати потік екструзії`,defaultVibrationCali:`Калібрування вібрації`,defaultVibrationCaliDesc:`Зменшувати артефакти від вібрації`,defaultLayerInspect:`Перевірка першого шару`,defaultLayerInspectDesc:`Перевірка першого шару за допомогою ШІ`,defaultTimelapse:`Таймлапс`,defaultTimelapseDesc:`Записувати таймлапс`,defaultNozzleOffsetCali:`Калібрування зсуву сопла`,defaultNozzleOffsetCaliDesc:`Калібрувати зміщення сопел між екструдерами`,tempFanPresetsTitle:`Профілі температури та вентилятора`,tempFanPresetsDescription:`Налаштуйте значення швидкого вибору в спливних панелях температури й швидкості вентилятора на картці принтера. Кнопка «Вимкнути» відображається завжди.`,tempFanPresetsNozzle:`Температура сопла`,tempFanPresetsBed:`Температура столу`,tempFanPresetsChamber:`Температура камери`,tempFanPresetsFan:`Швидкість вентилятора`,tempFanPresetsReset:`Відновити налаштування за замовчуванням`,concurrentUploadsTitle:`Паралельні вивантаження`,concurrentUploadsDescription:`Кількість принтерів, на які черга може одночасно надсилати файли. Передавання на принтери відбувається повільно — великий файл може передаватися кілька хвилин — і кожен принтер чекає своєї черги. Для великого парку збільшення цього значення скорочує очікування останнього принтера в партії. Зменште його, якщо мережа або сервер Bambuddy не справляється з паралельними передаваннями.`,concurrentUploadsLabel:`Кількість принтерів для одночасного передавання`,concurrentUploadsHelp:`1 надсилає на один принтер за раз (стара поведінка). За замовчуванням 4.`,staggeredStart:`Поетапний запуск`,staggeredStartDescription:`Типовий розмір групи та інтервал для поетапного запуску партії на кількох принтерах. Значення можна змінити для кожної партії у вікні друку.`,preheatTitle:`Попереднє нагрівання й термовитримка`,preheatDescription:`Нагрівати стіл — і камеру, якщо це підтримується — та витримувати задану температуру перед кожним друком із черги. Це корисно для інженерних філаментів, як-от PA й ABS, на принтерах без активного нагрівача камери: стіл нагріває камеру тепловим випромінюванням, доки триває термовитримка. Цільова температура столу зчитується з файлу друку; поведінка камери залежить від моделі принтера.`,preheatEnabled:`Увімкнути попереднє нагрівання й термовитримку`,preheatEnabledDesc:`Якщо вимкнено, завдання з черги надсилаються на друк негайно. Для кожного елемента черги це налаштування можна перевизначити окремо.`,preheatFilamentTargetsLabel:`Цільова температура камери за типом філаменту (°C)`,preheatFilamentTargetsHint:`Bambuddy вибирає найвищу цільову температуру серед завантажених слотів AMS. Для друку лише з PLA визначається значення 0, тому етап нагрівання камери автоматично пропускається.`,preheatFilamentTargetsReset:`Відновити налаштування за замовчуванням`,preheatFilamentTargetsDefaultRow:`Інше / не зіставлене`,preheatMaxWait:`Максимальний час очікування (секунди)`,preheatMaxWaitHelp:`Максимальна тривалість нагрівання камери перед переходом до наступного етапу.`,preheatSoak:`Термовитримка (с)`,preheatSoakHelp:`Час термовитримки після досягнення цільової температури або завершення максимального часу очікування.`,preheatHardwareTitle:`Особливості за моделями принтерів:`,preheatHardwareDetail:`H2C/H2D/H2D Pro/H2S/X2D/X1E активно нагрівають камеру командою M141. X1C/P2S зчитують температуру камери, але покладаються на нагрівання тепловим випромінюванням від столу. P1S/P1P/A1/A1 Mini не мають датчика камери — для них застосовується лише таймер термовитримки.`,preheatPerItemDesc:`Нагрівати стіл і камеру перед початком цього друку. Типове значення успадковується з перемикача «Налаштування → Робочий процес».`,preheatOverride_inherit:`Успадкувати`,preheatOverride_on:`Увімкнено`,preheatOverride_off:`Вимкнено`,calibrationMode_off:`Вимкнено`,calibrationMode_on:`Увімкнено`,calibrationMode_auto:`Авто`,preheatTargetOverride:`Інша цільова температура камери (°C; порожньо — типове значення для філаменту)`,plateClear:`Підтвердження очищення друкарської пластини`,requirePlateClear:`Вимагати підтвердження очищення друкарської пластини`,requirePlateClearDescription:`Якщо ввімкнено, планувальник перед запуском наступного завдання на принтері із завершеним друком очікує підтвердження, що друкарську пластину очищено. Вимкнення також приховує індикатор стану пластини та кнопку «Позначити пластину як очищену» на картках принтерів.`,gcodeInjection:`Вставлення G-коду`,gcodeInjectionDescription:`Налаштуйте власний G-код для вставлення на початку та/або наприкінці друку в системах автоматичного друку, як-от Farmloop, SwapMod, AutoClear і Printflow 3D. Фрагменти налаштовуються для кожної моделі принтера та застосовуються, коли для елемента черги ввімкнено «Вставляти G-код».`,gcodeInjectionNoPrinters:`Принтерів не знайдено. Додайте принтери, щоб налаштувати фрагменти G-коду.`,gcodeStartLabel:`Початковий G-код`,gcodeEndLabel:`Завершальний G-код`,gcodeStartPlaceholder:`G-код додається перед початком друку...`,gcodeEndPlaceholder:`G-код додається після завершення друку...`,staggerGroupSize:`Розмір групи`,staggerGroupSizeHelp:`Кількість принтерів, що одночасно запускаються в кожній групі`,staggerInterval:`Інтервал (хвилини)`,staggerIntervalHelp:`Затримка між стартом кожної групи`,queueDrying:`Автоматичне сушіння між завданнями черги`,queueDryingDescription:`Автоматично сушити філамент в AMS, коли принтер простоює між завданнями з черги. Сушіння запускається відповідно до заданого вище порога вологості.`,queueDryingEnabled:`Увімкнути автосушку`,queueDryingEnabledDescription:`Автоматичний запуск AMS сушіння, коли принтер неактивний і вологість перевищує порогове значення`,queueDryingBlock:`Чекати завершення сушіння`,queueDryingBlockDescription:`Не запускати завдання з черги до завершення сушіння. Якщо вимкнено, друк має пріоритет над сушінням.`,ambientDryingEnabled:`Фонове сушіння`,ambientDryingEnabledDescription:`Автоматичне сушіння філаменту на неактивних принтерах, коли вологість перевищує порогове значення, навіть без друку в черзі.`,printDryingEnabled:`Продовжувати сушіння під час друку`,printDryingEnabledDescription:`Дозволити автоматичному сушінню тривати під час друку на підтримуваному обладнанні (H2D, H2C, H2S, P2S, H2D Pro, X2D, X1C, A2L з новими версіями прошивки). Для захисту котушок температура сушіння автоматично обмежується значенням на 5 °C нижчим за профіль для режиму простою.`,dryingPresets:`Профілі сушіння`,dryingPresetsDescription:`Температура та тривалість для кожного типу філаменту. AMS 2 Pro використовує нижчі температури, AMS-HT підтримує вищі температури.`,dryingFilament:`Філамент`,humidityThresholds:`Пороги вологості`,humidityThresholdsDescription:`Пороги вологості за типом філаменту для автоматичного сушіння та попереджень. Для змішаного завантаження в одному AMS використовується найнижчий поріг.`,humidityThresholdCol:`Поріг`,humidityThresholdDefault:`За замовчуванням (невідомі типи)`,printModal:`Вікно друку`,expandCustomMapping:`Розгорнути настроюване зіставлення за умовчанням`,expandCustomMappingDescription:`Під час друку на кількох принтерах показувати розгорнуте зіставлення для кожного принтера AMS.`,authentication:`Автентифікація`,authEnabledDescription:`Ваш екземпляр захищено автентифікацією користувача`,authDisabledDescription:`Увімкніть запит входу та керування доступом користувачів`,authDisabledMessage:`Увімкніть автентифікацію, щоб створювати облікові записи користувачів, керувати дозволами та захищати свій екземпляр Bambuddy.`,enableAuthentication:`Увімкнути автентифікацію`,currentUser:`Поточний користувач`,changePassword:`Змінити пароль`,admin:`адмін`,users:`Користувачі`,addUser:`Додати користувача`,groups:`Групи`,addGroup:`Додати групу`,system:`система`,noDescription:`Без опису`,userCount:`{{count}} користувачів`,permissionCount:`Дозволи {{count}}.`,createUser:`Створити користувача`,username:`Ім’я користувача`,enterUsername:`Введіть ім’я користувача`,password:`Пароль`,enterPassword:`Введіть пароль`,passwordRequirements:`Принаймні 8 символів, один великий, один малий, одна цифра та один спеціальний символ.`,confirmPassword:`Підтвердити пароль`,confirmPasswordPlaceholder:`Підтвердити пароль`,viewReleaseOnGitHub:`Переглянути випуск на GitHub`,turnAllPlugsOn:`Увімкнути усі розетки`,turnAllPlugsOff:`Вимкнути усі розетки`,clearNotificationLogs:`Очистити журнали сповіщень`,clearLogsMessage:`Це назавжди видалить усі журнали сповіщень старше 30 днів. Цю дію не можна скасувати.`,clearLogs:`Очистити журнали`,resetUiPreferences:`Скинути налаштування UI.`,resetUiPreferencesMessage:`Це скине всі параметри UI до значень за замовчуванням: порядок бічної панелі, тему, макет інформаційної панелі, режими перегляду та параметри сортування. Це НЕ вплине на ваші принтери, архіви та налаштування сервера. Після очищення сторінка перезавантажиться.`,resetPreferences:`Скинути налаштування`,deleteGroupTitle:`Видалити групу`,deleteGroupMessage:`Ви впевнені, що хочете видалити цю групу? Користувачі цієї групи втратять ці дозволи.`,deleteGroup:`Видалити групу`,disableAuthenticationTitle:`Вимкнути автентифікацію`,disableAuthenticationMessage:`Ви впевнені, що бажаєте вимкнути автентифікацію? Це зробить ваш екземпляр Bambuddy доступним без входу. Усі користувачі залишаться в базі даних, але автентифікацію буде вимкнено.`,disableAuthentication:`Вимкнути автентифікацію`,configureBambuddy:`Налаштувати Bambuddy`,systemDefault:`Системне за замовчуванням`,archiveSettings:`Налаштування архіву`,newWindow:`Нове вікно`,embeddedOverlay:`Вбудоване накладання`,preferredSlicer:`Бажаний слайсер`,preferredSlicerDescription:`Слайсер для нарізання в застосунку через допоміжний API-сервіс`,openInSlicerLabel:`Відкрити у слайсері`,openInSlicerInherit:`Такий самий, як API-слайсер`,openInSlicerDescription:`Настільний слайсер, який відкриває кнопка «Відкрити в слайсері». Залиште «Такий самий, як API-слайсер», щоб успадкувати вибір, або виберіть інший слайсер для локального використання.`,orcaslicerKnownIssuesWarning:`OrcaSlicer 2.3.2 / 2.4.0-dev має відомі помилки CLI, через які не вдається нарізати багато створених Bambu файлів 3MF. Див. проблеми upstream №12426 — аварійне завершення для розфарбованих файлів із кількома екструдерами — та №13386 — відхилення через сувору перевірку діапазонів параметрів. До появи виправлень upstream рекомендовано використовувати Bambu Studio.`,useSlicerApi:`Використовувати API слайсера`,useSlicerApiDescription:`Якщо ввімкнено, команда «Нарізати» відкриває вбудоване вікно слайсера й викликає допоміжний сервіс slicer-API. Якщо вимкнено — типове значення — файл передається настільному слайсеру через URI-схему.`,slicerCard:`Слайсер`,orcaslicerApiUrl:`URL допоміжного сервісу OrcaSlicer`,bambuStudioApiUrl:`URL допоміжного сервісу Bambu Studio`,slicerStallTimeout:`Тайм-аут простою слайсера (хвилини)`,slicerStallTimeoutDescription:`Перервати нарізку, якщо sidecar не повідомляє про прогрес протягом цього часу. Важкі моделі, які продовжують повідомляти про прогрес, ніколи не перериваються, скільки б часу не знадобилося. Для sidecar без звіту про прогрес це значення використовується як загальний ліміт часу.`,slicerApiUrlDescription:`URL контейнера допоміжного сервісу slicer-API. Залиште поле порожнім, щоб використовувати типові значення зі змінних середовища SLICER_API_URL / BAMBU_STUDIO_API_URL.`,slicerBundlesRemoved:{title:`Пакети профілів слайсера (вилучено)`,description:`Імпорт пакетів профілів принтера (.bbscfg) вилучено. Експорт пакетів Bambu Studio містить лише змінені користувачем профілі, тому імпорт не надавав стандартних профілів процесу й філаменту, а під час нарізання використовувалися вбудовані налаштування.`,alternatives:`Використовуйте імпорт окремого профілю для власних профілів або синхронізацію через Bambu Cloud / Orca Cloud. Стандартні профілі автоматично надходять із допоміжного сервісу слайсера.`,lookupOrder:`Порядок пошуку профілів під час нарізання: 1) імпортовані локально, 2) Orca Cloud, 3) Bambu Cloud, 4) стандартні профілі слайсера.`},externalCameras:`Зовнішні камери`,costTracking:`Відстеження витрат`,printsOnly:`Лише друк`,totalConsumption:`Загальне споживання`,dataManagement:`Управління даними`,storageUsage:`Використання сховища`,storageUsageDescription:`Розподіл використання даних за категоріями`,storageUsageTotal:`Всього`,storageUsageErrors:`Помилки`,storageUsageOtherBreakdown:`Інше (включає статичні ресурси, сценарії та файли конфігурації)`,storageUsageSystem:`система`,storageUsageData:`Дані`,storageUsageUnavailable:`Інформація про використання сховища недоступна`,clearNotificationLogsDescription:`Видалити журнали сповіщень старші 30 днів`,resetUiPreferencesDescription:`Скинути порядок бічної панелі, тему, режими перегляду та параметри макета. Принтери, архіви та налаштування не впливають.`,enableHomeAssistant:`Увімкнути Home Assistant`,enableMqtt:`Увімкнути MQTT`,useTls:`Використовуйте TLS`,enableMetricsEndpoint:`Увімкнути кінцеву точку показників`,availableMetrics:`Доступні показники`,editUser:`Редагувати користувача`,deleteUserTitle:`Видалити користувача`,groupName:`Назва групи`,leaveEmptyForAnonymous:`Залиште порожнім для анонімного`,leaveEmptyForNoAuth:`Залиште порожнім, щоб не було автентифікації`,enterNewPassword:`Введіть новий пароль`,confirmNewPassword:`Підтвердити новий пароль`,enterGroupName:`Введіть назву групи`,enterDescriptionOptional:`Введіть опис (необов’язково)`,enterCurrentPassword:`Введіть поточний пароль`,enterNewPasswordMin6:`Введіть новий пароль (мінімум 6 символів)`,toast:{keyCopied:`Ключ скопійовано в буфер обміну`,copyFailed:`Не вдалося скопіювати ключ`,keyAddedToBrowser:`Ключ додано в браузер API.`,clearLogsFailed:`Не вдалося очистити журнали`,uiPreferencesReset:`UI налаштування скинуто. Оновлення...`,authDisabled:`Автентифікацію успішно вимкнено`,authDisableFailed:`Не вдалося вимкнути автентифікацію`,apiKeyCreated:`Ключ API створено`,apiKeyDeleted:`Ключ API видалено`,userCreated:`Користувача створено успішно`,userUpdated:`Користувача успішно оновлено`,userDeleted:`Користувача успішно видалено`,groupCreated:`Групу створено успішно`,groupUpdated:`Групу успішно оновлено`,groupDeleted:`Групу успішно видалено`,fillRequiredFields:`Будь ласка, заповніть усі необхідні поля`,passwordsDoNotMatch:`Паролі не збігаються`,passwordTooShort:`Пароль має бути не менше 8 символів`,passwordNeedsUppercase:`Пароль має містити принаймні одну велику літеру`,passwordNeedsLowercase:`Пароль має містити принаймні одну малу літеру`,passwordNeedsDigit:`Пароль має містити хоча б одну цифру`,passwordNeedsSpecial:`Пароль повинен містити хоча б один спеціальний символ`,enterGroupName:`Будь ласка, введіть назву групи`,settingsSaved:`Налаштування збережено`,noPermissionUpdate:`Ви не маєте дозволу змінювати налаштування`,cameraSettingsSaved:`Налаштування камери збережено`,enterCameraUrl:`Будь ласка, введіть камеру URL`,passwordChanged:`Пароль успішно змінено`,connectionFailed:`Помилка підключення`,testFailed:`Тест не вдалося`,cameraConnected:`Камера підключена{{resolution}}`,cameraConnectedCoalesced:`Камера підключена{{resolution}} (спільно з уже виконуваним захопленням)`},testConnection:`Тестове підключення`,catalog:{spoolCatalog:`Каталог котушок`,spoolCatalogDescription:`Вага порожніх котушок за брендом і типом. Використовується для автоматичного пошуку ваги під час додавання котушок.`,searchCatalog:`Пошук у каталозі...`,addNewEntry:`Додати новий запис`,namePlaceholder:`Назва (наприклад, Bambu Lab - пластик)`,weight:`вага`,type:`Тип`,default:`За замовчуванням`,custom:`Власний`,noMatch:`Немає записів, що відповідають вашому пошуку`,empty:`Немає записів у каталозі`,deleteEntry:`Видалити запис`,deleteConfirm:`Ви впевнені, що хочете видалити "{{name}}"?`,resetCatalog:`Скинути каталог`,resetConfirm:`Скинути каталог до стандартних? Це видалить усі спеціальні записи.`,loadFailed:`Не вдалося завантажити каталог котушок`,nameWeightRequired:`Назва й маса обов’язкові`,entryAdded:`Запис додано`,addFailed:`Не вдалося додати запис`,entryUpdated:`Запис оновлено`,updateFailed:`Не вдалося оновити запис`,entryDeleted:`Запис видалено`,deleteFailed:`Не вдалося видалити запис`,resetSuccess:`Каталог відновлено до типових значень`,resetFailed:`Не вдалося скинути каталог`,exported:`Експортовано записів: {{count}}`,imported:`Імпортовано: {{added}}; пропущено: {{skipped}}`,importFailed:`Не вдалося імпортувати: недійсний формат JSON.`,exportTooltip:`Експортувати каталог до JSON`,importTooltip:`Імпорт каталогу з JSON`,resetTooltip:`Відновити налаштування за замовчуванням`,selectedCount:`Вибрано: {{count}}`,deleteSelected:`Видалити вибране`,bulkDeleteConfirm:`Видалити вибрані записи ({{count}})?`,bulkDeleted:`Видалено записів: {{count}}`,bulkDeleteFailed:`Не вдалося видалити записи`,material:`матеріал`,spoolWeight:`Вага котушки`,color:`Колір`,updateSpoolWeight:`Оновити вагу котушки`,filamentUpdated:`Філамент оновлено`,filamentUpdateFailed:`Не вдалося оновити філамент`,filamentUpdateInvalid:`Недійсні дані філаменту`,keepExistingSpoolWeight:`Зберегти попередню вагу для наявних котушок`,keepExistingSpoolWeightDesc:`Котушки, створені з цим типом філаменту, зберігають стару вагу тари. Нові котушки використовують оновлене значення.`,applyToAllSpools:`Застосувати до всіх котушок`,applyToAllSpoolsDesc:`Усі розрахунки ваги для цього типу філаменту одразу використовують нову вагу тари.`},colorCatalog:{title:`Каталог кольорів`,description:`Кольори філаменту за виробником і матеріалом. Використовується для автоматичного пошуку кольору під час додавання котушок.`,searchColors:`Пошук кольорів...`,allManufacturers:`Усі виробники`,addNewColor:`Додати новий колір`,manufacturer:`Виробник`,colorName:`Назва кольору`,hex:`Hex-код`,materialOptional:`Матеріал (необов’язково)`,showing:`Показано {{filtered}} із {{total}} кольорів`,noMatch:`Жоден колір не відповідає вашому запиту`,empty:`Кольори в каталозі відсутні`,deleteColor:`Видалити колір`,deleteConfirm:`Ви впевнені, що хочете видалити "{{name}}"?`,resetCatalog:`Скинути каталог кольорів`,resetConfirm:`Скинути каталог до стандартних? Це видалить усі власні кольори.`,sync:`Синхронізувати`,starting:`Запуск…`,syncTooltip:`Синхронізація з FilamentColors.xyz (2000+ кольорів, може зайняти хвилину)`,loadFailed:`Не вдалося завантажити каталог кольорів`,fieldsRequired:`Необхідно вказати виробника, назву кольору та шістнадцятковий колір`,colorAdded:`Додано колір`,addFailed:`Не вдалося додати колір`,colorUpdated:`Колір оновлено`,updateFailed:`Не вдалося оновити колір`,colorDeleted:`Колір видалено`,deleteFailed:`Не вдалося видалити колір`,resetSuccess:`Каталог кольорів відновлено до типових значень`,resetFailed:`Не вдалося скинути каталог`,syncUpToDate:`Вже оновлено (кольори {{count}} перевірено)`,syncComplete:`Додано: {{added}}; уже існувало: {{skipped}}`,syncError:`Помилка синхронізації`,syncFailed:`Не вдалося синхронізувати з FilamentColors.xyz`,exported:`Експортовано кольорів: {{count}}`,imported:`Імпортовано: {{added}}; пропущено: {{skipped}}`,importFailed:`Не вдалося імпортувати: недійсний формат JSON.`,selectedCount:`Вибрано: {{count}}`,deleteSelected:`Видалити вибране`,bulkDeleteConfirm:`Ви впевнені, що бажаєте видалити кольори {{count}}?`,bulkDeleted:`Видалено кольорів: {{count}}`,bulkDeleteFailed:`Не вдалося видалити кольори`},dateFormat:`Формат дати`,dateFormatUs:`США (MM/DD/YYYY)`,dateFormatEu:`ЄС (DD/MM/YYYY)`,dateFormatIso:`ISO (РРРР-ММ-ДД)`,timeFormat:`Формат часу`,timeFormat12:`12 годин (15:30)`,timeFormat24:`24 години (15:30)`,defaultPrinter:`Принтер за умовчанням`,defaultPrinterDescription:`Попередньо вибирати цей принтер для вивантажень, повторного друку та інших операцій.`,slicerBambuStudio:`Bambu Studio`,slicerOrcaSlicer:`OrcaSlicer`,sidebarOrderDescription:`Використовуйте бічну панель, щоб змінити порядок елементів, скинути видимість і керувати спеціальними посиланнями.`,setDefault:`Установити за замовчуванням`,sidebarOrderSetDefaultHint:`За замовчуванням застосовує поточний порядок меню до користувачів, які не налаштували свій.`,sidebarDefaultSet:`Встановлено стандартний порядок меню.`,sidebarDefaultCleared:`Порядок меню за замовчуванням видалено.`,sidebarDefaultFailed:`Не вдалося встановити порядок меню за замовчуванням.`,reset:`Скинути`,darkMode:`Темний режим`,lightMode:`Світловий режим`,active:`(активний)`,background:`Фон`,accent:`Акцент`,style:`Стиль`,bgNeutral:`Нейтральний`,bgWarm:`Теплий`,bgCool:`круто`,bgOled:`OLED Чорний`,bgSlate:`Шиферно-блакитний`,bgForest:`Зелений ліс`,accentGreen:`Зелений`,accentTeal:`Чирок`,accentBlue:`Синій`,accentOrange:`Помаранчевий`,accentPurple:`Фіолетовий`,accentRed:`Червоний`,styleClassic:`класичний`,styleGlow:`Світіння`,styleVibrant:`Яскравий`,themeToggleHint:`Перемикайтеся між темним, світлим і системним режимами за допомогою значка на бічній панелі.`,progressInTitle:`Прогрес у вкладці`,progressInTitleDescription:`Показує відсоток активного друку та кільце прогресу на вкладці браузера.`,autoArchivePrints:`Автоматично архівувати друки`,autoArchiveDescription:`Автоматично зберігати файли 3MF після завершення друку`,saveThumbnailsDescription:`Витягніть і збережіть зображення попереднього перегляду з файлів 3MF.`,captureFinishPhotoDescription:`Зробіть фотографію з камери принтера після завершення друку. Bambuddy записує короткий проміжок часу під час друку, щоб фотографію можна було отримати з моменту, коли стіл опускається; файл уповільненої зйомки зберігається, якщо ви ввімкнули уповільнену зйомку для цього друку, інакше він автоматично видаляється після зйомки фотографії.`,finishPhotoRestorePlate:`Піднімати стіл для фінального знімка`,finishPhotoRestorePlateDescription:`Після завершення друку принтер опускає стіл приблизно на 100 мм, і готова модель опиняється нижче кадру камери. Bambuddy піднімає стіл назад трохи вище останнього надрукованого шару, робить знімок і знову опускає його. Пропускається, якщо висота друку невідома або в черзі є інше завдання.`,ffmpegNotInstalled:`ffmpeg не встановлено`,ffmpegRequired:`Для зйомки камерою потрібен ffmpeg. Встановіть його за допомогою brew install ffmpeg (macOS) або apt install ffmpeg (Linux).`,camera:`Камера`,cameraViewMode:`Режим перегляду камери`,cameraOverlayDescription:`Камера відкривається в накладці зі змінним розміром на головному екрані`,cameraWindowDescription:`Камера відкривається в окремому вікні браузера`,externalCamerasDescription:`Налаштуйте зовнішні камери замість вбудованої камери принтера. Підтримує потоки MJPEG, знімки RTSP, HTTP і камери USB (V4L2). Якщо ввімкнено, зовнішня камера використовується для перегляду в реальному часі та готових фотографій.`,cameraPlaceholderUsb:`Шлях пристрою (/dev/video0)`,cameraPlaceholderUrl:`Камера URL (rtsp://... або http://...)`,cameraTypeMjpeg:`Потік MJPEG`,cameraTypeRtsp:`RTSP Потік`,cameraTypeSnapshot:`HTTP Знімок`,cameraTypeUsb:`USB Камера (V4L2)`,cameraSnapshotUrl:`URL знімка (необов’язково)`,cameraSnapshotUrlPlaceholder:`http://192.168.1.61:1984/api/frame.jpeg?src=printer`,cameraSnapshotUrlHelp:`Одиночний кадр URL використовується для ескізів сповіщень, фінішних фотографій, шарових кадрів уповільненої зйомки та виявлення пластин. Уповільнена зйомка та виявлення пластин потребують окремого перемикача для кожного принтера — це URL є лише джерелом зображення, з якого вони беруть участь, коли активні. Залиште поле порожнім для запису з прямої трансляції вище. Корисно для камер go2rtc (/api/frame.jpeg) і IP із спеціальною кінцевою точкою знімка.`,cameraRotation:`Обертання`,test:`Тест`,connected:`Підключено`,disconnected:`Відключено`,currency:`Валюта`,defaultFilamentCost:`Вартість філаменту за замовчуванням (за кг)`,electricityCost:`Вартість електроенергії за kWh`,energyDisplayMode:`Режим відображення енергії`,energyModePrintDescription:`Інформаційна панель показує суму енергії, використаної під час друку`,energyModeTotalDescription:`На приладовій панелі показано енергію від розумних розеток протягом усього терміну служби`,fileManager:`Менеджер файлів`,createArchiveEntry:`Створити архівний запис під час друку`,createArchiveEntryDescription:`Під час друку з диспетчера файлів можна додатково створити запис архіву`,lowDiskSpaceWarning:`Попередження про брак місця на диску`,lowDiskSpaceDescription:`Показувати попередження, коли вільний простір на диску стає нижче цього порогу`,printerFirmware:`Прошивка принтера`,checkFirmwareDescription:`Перевірте наявність оновлень прошивки принтера від Bambu Lab`,bambuddySoftware:`Bambuddy Програмне забезпечення`,autoCheckDescription:`Автоматично перевіряти наявність нових версій під час запуску`,checkNow:`Перевір зараз`,updateAvailableVersion:`Доступне оновлення: v{{version}}`,releaseNotes:`Примітки до випуску`,updateViaDocker:`Оновити через Docker Написати:`,updateViaHomeAssistant:`Оновленнями керує супервізор Home Assistant. Відкрийте «Налаштування» → «Додатки» → Bambuddy у Home Assistant, щоб установити нову версію.`,updateViaWindowsInstaller:`Інсталяції Windows оновлюються шляхом повторного запуску інсталятора. Завантажте нову версію нижче — ваші дані, налаштування та принтери збережуться.`,downloadWindowsInstaller:`Завантажити інсталятор для v{{version}}`,installUpdate:`Встановити оновлення`,latestVersionRunning:`Ви використовуєте останню версію`,failedToCheckUpdates:`Не вдалося перевірити наявність оновлень: {{error}}`,backupRestore:`Резервне копіювання та відновлення`,backupRestoreDescription:`Експорт /import налаштувань і конфігурація GitHub резервного копіювання`,goToBackup:`Перейдіть до Резервного копіювання`,externalUrl:`Зовнішній URL`,externalUrlDescription:`Зовнішній URL, де Bambuddy доступний. Використовується для зображень сповіщень і зовнішньої інтеграції.`,bambuddyUrl:`Bambuddy URL`,externalUrlHint:`Включити протокол і порт (наприклад, http://192.168.1.100:8000)`,ftpRetry:`FTP Спробуйте ще раз`,ftpRetryDescription:`Повторювати операції FTP за ненадійного Wi-Fi принтера. Застосовується до завантаження 3MF і таймлапсів, вивантаження завдань друку та оновлення прошивки.`,autoRetryDescription:`Автоматично повторити невдалі операції FTP.`,retryAttempts:`Повторні спроби`,retryDelay:`Затримка повторної спроби`,connectionTimeout:`Час очікування підключення`,time_one:`час {{count}}.`,time_other:`{{count}} разів`,second_one:`{{count}} секунда`,second_other:`{{count}} секунд`,nSeconds:`{{count}} секунд`,increaseForWeakWifi:`Підвищення для принтерів із слабким WiFi`,homeAssistant:`Home Assistant`,homeAssistantFullDescription:`Підключіться до Home Assistant, щоб керувати розумними розетками через REST API HA. Підтримує об’єкти switch, light, input_boolean і script.`,homeAssistantUrl:`Home Assistant URL`,longLivedAccessToken:`Довгостроковий токен доступу`,haTokenHint:`Створіть токен у HA: Профіль → Довгострокові токени доступу → Створити токен`,connectionSuccessful:`Підключення успішне`,connectionFailed:`Збій підключення`,haConnectionSuccess:`Успішно підключено до Home Assistant.`,haConnectionFailed:`Не вдалося підключитися до Home Assistant.`,mqttPublishing:`MQTT Видавництво`,mqttDescription:`Публікуйте події BamBuddy зовнішньому брокеру MQTT для інтеграції з Node-RED, Home Assistant та іншими системами автоматизації.`,mqttEnableDescription:`Публікувати події зовнішньому MQTT брокеру`,brokerHostname:`Ім’я хоста брокера`,port:`Порт`,usernameOptional:`Ім’я користувача (необов’язково)`,passwordOptional:`Пароль (необов’язково)`,topicPrefix:`Префікс теми`,topicPrefixHint:`Теми будуть: {{prefix}}/printers//status тощо.`,prometheusMetrics:`Prometheus Метрики`,prometheusEndpointDescription:`Показати показники принтера на /api/v1/metrics для моніторингу Prometheus/Grafana.`,bearerTokenOptional:`Токен Bearer (необов’язково)`,bearerTokenHint:`Якщо встановлено, запити мають містити Авторизація: носій `,metricsConnectionStatus:`Статус підключення`,metricsPrinterState:`Стан принтера (неактивний /printing/etc)`,metricsPrintProgress:`Прогрес друку 0-100%`,metricsBedTemp:`Температура столу`,metricsNozzleTemp:`Температура сопла`,metricsPrintsTotal:`Загальна кількість друків за результатами`,metricsMore:`...і багато іншого (шари, вентилятори, черга, використання філаментів)`,smartPlugsDescription:`Підключіть розумні розетки (Tasmota або Home Assistant), щоб автоматизувати керування живленням і відстежувати споживання електроенергії вашими принтерами.`,allOn:`Все включено`,allOff:`Все вимкнено`,addSmartPlug:`Додати розумну розетку`,energySummary:`Відновити енергетики`,currentPower:`Поточна потужність`,plugsOnline:`Розумні розетки в мережі: {{reachable}}/{{total}}`,today:`Сьогодні`,yesterday:`вчора`,total:`Всього`,enablePlugsForSummary:`Увімкніть розетки, щоб переглянути підсумок енергії`,addNotificationProvider:`додати`,systemBadge:`(Система)`,creating:`Створення...`,changing:`Зміна...`,deleteUserAndItems:`Видалити користувача ТА його елементи`,deleteUserKeepItems:`Видалити користувача, зберегти елементи (стати без власника)`,ok:`добре`,twoFa:{totpTitle:`Програма Authenticator (TOTP)`,totpDesc:`Використовуйте програму автентифікації, наприклад Google Authenticator Aegis або Authy.`,emailOtpTitle:`Одноразовий код електронною поштою`,emailOtpDesc:`Надішліть одноразовий код на {{email}} під час входу.`,emailOtpNoEmail:`Щоб увімкнути цей метод, додайте адресу електронної пошти до свого облікового запису.`,addEmailFirst:`У вашому обліковому записі немає адреси електронної пошти. Попросіть адміністратора додати її, перш ніж вмикати одноразові коди електронною поштою.`,setupTotp:`Налаштувати додаток Authenticator`,setupAuthApp:`Налаштувати додаток Authenticator`,setupInstructions:`Відскануйте наведений нижче QR-код за допомогою програми автентифікації, а потім підтвердьте кодом.`,manualEntry:`Не можете сканувати? Введіть цей секрет вручну:`,scannedContinue:`Код відскановано — продовжити`,enterCodeToConfirm:`Введіть 6-значний код із програми автентифікації, щоб підтвердити налаштування.`,activate:`Активувати`,disableTotp:`Вимкнути автентифікатор`,disableConfirmHint:`Введіть дійсний код TOTP або резервний код, щоб вимкнути автентифікатор.`,totpDisabled:`Програму Authenticator вимкнено.`,emailOtpEnabled:`Одноразові коди електронною поштою ввімкнено.`,emailOtpDisabled:`Одноразові коди електронною поштою вимкнено.`,smtpRequired:`Спочатку налаштуйте та перевірте параметри SMTP.`,invalidCode:`Невірний код. Спробуйте ще раз.`,enableEmailOtp:`Увімкнути одноразові коди електронною поштою`,disableEmailOtp:`Вимкнути одноразові коди електронною поштою`,emailSetupEnterCode:`Код підтвердження надіслано на вашу адресу електронної пошти. Введіть його нижче, щоб підтвердити доступ до цієї поштової скриньки.`,verifyAndEnable:`Перевірити й увімкнути`,emailDisablePasswordHint:`Введіть пароль свого облікового запису, щоб підтвердити вимкнення OTP електронної пошти.`,passwordPlaceholder:`Введіть свій пароль`,backupCodesTitle:`Зберегти резервні коди`,backupCodesWarning:`Збережіть ці коди в безпечному місці. Кожен код можна використати лише один раз, і він більше не відображатиметься.`,backupCodesRemaining:`Залишилося резервних кодів: {{count}}`,savedCodes:`Я зберіг свої коди`,regenBackup:`Створити нові резервні коди`,regenBackupHint:`Введіть поточний код TOTP, щоб створити 10 нових резервних кодів. Усі існуючі резервні коди стануть недійсними.`,newBackupCodes:`Нові резервні коди`,linkedAccounts:`Пов’язані облікові записи SSO.`,linkedAccountsDesc:`Ці зовнішні постачальники ідентифікаційної інформації пов’язані з вашим обліковим записом.`,oidcUnlinked:`Обліковий запис від’єднано.`},sessionPolicy:{title:`Політика сеансу`,description:`Максимальна тривалість сеансу для входу нових користувачів. Уже випущені токени зберігають початковий термін дії.`,preset24h:`24 години`,preset7d:`7 днів`,preset30d:`30 днів`,customHoursLabel:`Тривалість користувацького сеансу в годинах`,hoursSuffix:`години`,warning:`Довші сеанси знижують захист від автоматичного виходу. Рекомендовано лише для надійних розгортань для одного користувача.`},oidc:{title:`Постачальники SSO / OIDC`,desc:`Налаштуйте постачальників OpenID Connect, щоб дозволити єдиний вхід через зовнішніх постачальників ідентифікації.`,addProvider:`Додати постачальника`,newProvider:`Новий постачальник`,empty:`Постачальників OIDC ще не налаштовано.`,created:`Постачальник створено.`,updated:`Постачальника оновлено.`,deleted:`Постачальника видалено.`,refreshIcon:`Значок оновлення`,removeIcon:`Видалити значок`,iconRefreshed:`Значок оновлено.`,iconRemoved:`Значок видалено.`,iconFetchFailed:`Не вдалося отримати значок за URL постачальника.`,deleteTitle:`Видалити постачальника`,deleteMessage:`Видалити «{{name}}»? Усі пов’язані облікові записи користувачів буде від’єднано.`,form:{name:`Відображуване ім’я`,issuerUrl:`URL емітента`,clientId:`ID клієнта`,clientSecret:`Секрет клієнта`,scopes:`Області доступу`,iconUrl:`URL значка (необов’язково)`,enabled:`Увімкнено`,autoCreate:`Автоматичне створення користувачів`,autoCreateDesc:`Автоматично створювати локальний обліковий запис під час першого входу.`,autoLink:`Автоматичне пов’язування наявних облікових записів`,autoLinkDesc:`Автоматично пов’язувати наявні локальні облікові записи за збігом адреси електронної пошти під час першого входу.`,secretHint:`залиште порожнім, щоб зберегти поточне значення`,secretPlaceholder:`новий секрет`,emailClaim:`Поле електронної пошти`,emailClaimDesc:`Поле JWT, що використовується як адреса електронної пошти. Для Azure Entra ID, який не надсилає email_verified, використовуйте preferred_username або upn. Указуйте лише назви надійних полів.`,emailClaimPlaceholder:`email`,emailClaimCustomClaimAutoLinkWarning:`Власне поле можна безпечно використовувати для автоматичного пов’язування, лише якщо його значенням керує адміністратор організації, наприклад upn або preferred_username в Azure Entra ID. Не вмикайте автоматичне пов’язування, якщо IdP дозволяє користувачам самостійно задавати це поле.`,requireEmailVerified:`Вимагати підтвердження електронної пошти`,requireEmailVerifiedDesc:`Приймати поле електронної пошти лише тоді, коли постачальник позначив адресу як підтверджену.`,requireEmailVerifiedWarning:`Попередження: адресу електронної пошти буде прийнято навіть без підтвердження. Використовуйте це лише з надійними постачальниками.`,requireEmailVerifiedAutoLink:`Щоб змінити це налаштування, спочатку вимкніть автоматичне пов’язування.`,defaultGroup:`Група за замовчуванням`,defaultGroupDesc:`Група, яку призначають автоматично створеним користувачам. Якщо її не задано, використовується група «Глядачі».`,defaultGroupViewersFallback:`Глядачі (за замовчуванням)`,autologin:`Автовхід`,autologinDesc:`Одразу перенаправляти неавтентифікованих відвідувачів до цього постачальника. Автоматичний вхід можна ввімкнути лише для одного постачальника.`}},encryption:{title:`Стан шифрування MFA`,enabledFromEnv:`Шифрування даних у сховищі ввімкнено — ключ отримано зі змінної середовища MFA_ENCRYPTION_KEY`,enabledFromFile:`Шифрування даних у сховищі ввімкнено — ключ завантажено з каталогу даних`,enabledGenerated:`Шифрування даних у сховищі ввімкнено з автоматично створеним ключем`,notConfigured:`Шифрування даних у сховищі не налаштовано`,notConfiguredDesc:`Секрети TOTP і client_secret постачальників OIDC зберігаються як відкритий текст. Установіть MFA_ENCRYPTION_KEY або перезапустіть Bambuddy з доступним для запису каталогом даних, щоб ключ було створено автоматично.`,allEncrypted:`Усі секрети MFA зашифровано у сховищі.`,legacyRowsLabel:`Застарілі рядки відкритого тексту`,encryptedRowsLabel:`Зашифровані рядки`,legacyRowsWarning:`Виявлено незашифрованих застарілих записів: {{count}}. Повторно збережіть постачальника OIDC або заново зареєструйте застосунок автентифікації користувача, щоб перенести дані до зашифрованого сховища.`,backupHint:`Автоматично згенерований ключ зберігається в DATA_DIR/.mfa_encryption_key і включено до локальних резервних ZIP-файлів. Зберігайте свої резервні копії в безпеці або явно встановіть MFA_ENCRYPTION_KEY.`,decryptionBrokenTitle:`Відсутній ключ шифрування`,decryptionBrokenError:`Не вдається розшифрувати записів: {{count}}, оскільки ключ шифрування більше недоступний. Для відновлення поверніть попередній MFA_ENCRYPTION_KEY або DATA_DIR/.mfa_encryption_key.`,migrationErrorWarning:`{{count}} застарілих рядків не вдалося повторно зашифрувати під час запуску. Перевірте журнали сервера та перезапустіть Bambuddy, щоб повторити спробу.`},pipelineLimits:{title:`Межі конвеєра слайсера`,maxCopiesLabel:`Максимальна кількість копій за один запуск`,maxCopiesDesc:`Верхня межа копій, які оператори можуть запитувати під час запуску конвеєра. Обмеження на стороні сервера становить 1000.`},pipelines:{title:`Конвеєри слайсера`,subtitle:`Багаторазові набори профілів — принтер, процес, філаменти й тип столу. Збережіть набір у вікні нарізання та застосовуйте його до наступного файлу одним натисканням.`,loading:`Завантаження конвеєрів…`,loadError:`Не вдалося завантажити конвеєри.`,confirmDelete:`Видалити цей конвеєр? Це неможливо скасувати.`,staleWarning:`Одного або кількох пов’язаних профілів більше не існує. Щоб виправити це, повторно збережіть конвеєр у вікні нарізання.`,empty:{title:`Конвеєрів ще немає.`,howto:`Відкрийте вікно нарізання для будь-якого файлу, виберіть принтер, процес, філаменти й тип столу, а потім натисніть «Зберегти як конвеєр». Збережені конвеєри з’являться тут.`},field:{name:`Назва конвеєра`,description:`опис`,targetPrinter:`Цільовий принтер`,noTarget:`— Немає цілі —`,targetKind:`Цільовий тип`,targetKindSpecific:`Конкретний принтер`,targetKindClass:`Клас принтера`,targetModelClass:`Модель принтера`,fanoutStrategy:`Стратегія розподілу`,fanout:{max_parallel:`Максимально паралельно — розподіляти між усіма відповідними вільними принтерами`,round_robin:`По колу — почергово використовувати відповідні принтери`,fill_one_first:`Спочатку один принтер — призначити всі копії одному принтеру`},fanoutShort:{max_parallel:`паралельний`,round_robin:`по колу`,fill_one_first:`спочатку один`}},action:{save:`зберегти`,cancel:`Скасувати`,rename:`Перейменувати`,delete:`Видалити`},slot:{printer:`Принтер`,process:`процес`,filament:`Філамент`,filamentN:`Філамент {{n}}`,filamentAll:`Усі {{n}} слотів`,bed:`Стіл`},group:{profiles:`Профілі`,filaments:`філаменти`},searchPlaceholder:`Шукати конвеєри…`,filterTargetType:`Фільтрувати за типом цілі`,filterTarget:`Фільтрувати за ціллю`,filter:{all:`Всі цілі`,noTarget:`Ціль не встановлена`,count:`{{shown}} / {{total}}`,noMatches:`Жоден конвеєр не відповідає поточним фільтрам.`},toast:{saved:`Конвеєр збережено`,saveFailed:`Не вдалося зберегти`,deleted:`Конвеєр видалено`,deleteFailed:`Не вдалося видалити`},noTargetHint:`Щоб запустити конвеєр, виберіть цільовий принтер`,noTargetWarning:`Перед запуском цього конвеєра встановіть цільовий принтер.`,runs:{lastRun:`Останній запуск`,status:{queued:`в черзі`,slicing:`нарізка`,dispatching:`надсилання`,in_progress:`друк`,completed:`завершено`,failed:`не вдалося`,partial_failure:`частково невдало`,cancelled:`скасовано`}}}},notification:{printStarted:{title:`Друк розпочато`,body:`{{printer}}: розпочато друк {{filename}}`},printCompleted:{title:`Друк завершено`,body:`{{printer}}: {{filename}} завершено успішно`},printFailed:{title:`Помилка друку`,body:`{{printer}}: не вдалося надрукувати {{filename}}`},printStopped:{title:`Друк зупинено`,body:`{{printer}}: {{filename}} було зупинено`},printProgress:{title:`Перебіг друку`,body:`{{printer}}: {{filename}} виконано {{percent}}%.`},printerOffline:{title:`Принтер не в мережі`,body:`{{printer}} не в мережі`},printerError:{title:`Помилка принтера`,body:`{{printer}}: {{error}}`},filamentLow:{title:`Закінчується філамент`,body:`{{printer}}: філамент майже закінчився`},maintenanceDue:{title:`Технічне обслуговування`,body:`{{printer}}: потрібна увага — {{items}}`}},errors:{generic:`Щось пішло не так`,networkError:`Помилка мережі. Перевірте підключення.`,notFound:`Не знайдено`,unauthorized:`Доступ не авторизовано`,serverError:`Помилка сервера`,validationError:`Перевірте введені дані`,printerConnectionFailed:`Не вдалося підключитися до принтера`,saveFailed:`Не вдалося зберегти зміни`,deleteFailed:`Не вдалося видалити`,loadFailed:`Не вдалося завантажити дані`},hmsErrors:{title:`Помилки - {{name}}`,noErrors:`Помилок немає`,viewOnWiki:`Переглянути на Bambu Lab Wiki`,mqttVerifyFailedRemedy:`Увімкніть режим розробника на принтері, перезавантажте принтер і запустіть завдання знову.`,unknownCode:`Невідомий код HMS — подробиці дивіться у вікі Bambu Lab.`,clearInstructions:`Усуньте помилки на принтері, щоб вони зникли тут.`,clearErrors:`Очистити помилки`,clearSuccess:`Помилки HMS видалено`,clearFailed:`Не вдалося видалити помилки HMS`,actionSuccess:`Команду надіслано принтеру`,actionFailed:`Не вдалося надіслати дію`,runoutExpectedSlot:`Філамент закінчився в {{ranOut}}. Тепер принтер очікує сумісний філамент у {{expected}}. Вставте котушку в {{expected}}, а потім виберіть «Повторити».`,runoutExpectedSlotOnly:`Принтер очікує сумісний філамент у {{expected}}. Вставте туди котушку, а потім виберіть «Повторити».`,runoutSlotUnknown:`Філамент закінчився, тому друк призупинено. Bambuddy не може визначити, якого слота тепер очікує принтер — перевірте екран принтера.`,actions:{RESUME_PRINTING:`Відновити друк`,RESUME_PRINTING_DEFECTS:`Відновити (допустимі недоліки)`,RESUME_PRINTING_PROBELM_SOLVED:`Відновити (проблему вирішено)`,STOP_PRINTING:`Зупинити друк`,CHECK_ASSISTANT:`Перевірити помічника`,FILAMENT_EXTRUDED:`Філамент екструдовано — продовжити`,RETRY_FILAMENT_EXTRUDED:`Ще не екструдовано — повторити`,CONTINUE:`Готово, продовжити`,LOAD_VIRTUAL_TRAY:`Завантажити філамент`,OK_BUTTON:`OK`,FILAMENT_LOAD_RESUME:`Філамент завантажено, відновити`,JUMP_TO_LIVEVIEW:`Перейти до перегляду наживо`,NO_REMINDER_NEXT_TIME:`Більше не нагадувати`,REFRESH_NOZZLE:`Перевірити знову`,IGNORE_NO_REMINDER_NEXT_TIME:`Ігнорувати. Не нагадувати наступного разу`,IGNORE_RESUME:`Ігнорувати й відновити друк`,PROBLEM_SOLVED_RESUME:`Проблему вирішено — відновити друк`,TURN_OFF_FIRE_ALARM:`Зрозуміло, вимкнути пожежну сигналізацію`,RETRY_PROBLEM_SOLVED:`Повторити (проблему вирішено)`,CANCLE:`Скасувати`,STOP_DRYING:`Зупинити сушіння`,PROCEED:`Продовжити`,OK_JUMP_RACK:`OK`,ABORT:`Перервати`,DISABLE_PURIFICATION:`Вимкнути очищення для цього друку`,DONT_REMIND_NEXT_TIME:`Більше не нагадувати`,DBL_CHECK_CANCEL:`Скасувати`,DBL_CHECK_DONE:`Готово`,DBL_CHECK_RETRY:`Повторити`,DBL_CHECK_RESUME:`Відновити`,DBL_CHECK_OK:`Підтвердити`,REMOVE_CLOSE_BTN:`Закрити`}},mqttDebug:{title:`Журнал налагодження MQTT`,searchPlaceholder:`Шукати тему або корисне навантаження…`,noMessages:`Ще не зареєстровано жодного повідомлення`,startLoggingHint:`Натисніть «Почати журналювання», щоб розпочати запис MQTT повідомлень`,noMessagesMatch:`Жодне повідомлення не відповідає вашому фільтру`,adjustFilterHint:`Спробуйте змінити критерії пошуку або фільтра`,incoming:`Вхідні`,outgoing:`Вихідні`,loggingStopped:`Запис припинено`,loggingActive:`Логування активне – повідомлення автоматично оновлюватимуться`,startLogging:`Розпочати журналювання`,stopLogging:`Зупинити журналювання`,clearLog:`Очистити журнал`,topic:`Тема`,timestamp:`Мітка часу`,direction:`Напрямок`,all:`Усі`},printerFiles:{title:`Менеджер файлів`,storageUsed:`Використовується:`,storageFree:`Вільно:`,filterPlaceholder:`Фільтр файлів...`,deleteButton:`Видалити`,deleteFiles:`Видалити файли {{count}}.`,deleteFileConfirm:`Видалити "{{name}}"? Це неможливо скасувати.`,deleteFilesConfirm:`Видалити вибрані файли {{count}}? Це неможливо скасувати.`,noFiles:`Немає файлів на принтері`,loadingFiles:`Завантаження файлів...`,failedToLoad:`Не вдалося завантажити файли`,toast:{filesDeleted:`Видалено файлів: {{count}}`,deleteFailed:`Не вдалося видалити: {{error}}`}},confirm:{delete:`Ви впевнені, що хочете це видалити?`,unsavedChanges:`У вас є незбережені зміни. Ви впевнені, що хочете піти?`,clearQueue:`Ви впевнені, що бажаєте очистити чергу?`},login:{title:`Вхід у Bambuddy`,subtitle:`Увійти у свій обліковий запис`,username:`Ім’я користувача`,usernamePlaceholder:`Введіть своє ім’я користувача`,usernameOrEmail:`Ім’я користувача або електронна пошта`,usernameOrEmailPlaceholder:`Ім’я користувача або електронна пошта`,password:`Пароль`,passwordPlaceholder:`Введіть свій пароль`,signIn:`Увійти`,signingIn:`Вхід...`,rememberMe:`Запам’ятати мене`,forgotPassword:`Забули пароль?`,autologinFailed:`Помилка автоматичного входу SSO. Щоб продовжити, виберіть постачальника нижче.`,localDisabledNotice:`Локальний вхід вимкнено. Використовуйте одного з наведених нижче постачальників SSO.`,loginSuccess:`Успішно ввійшли`,loginFailed:`Помилка входу`,enterCredentials:`Будь ласка, введіть ім’я користувача та пароль`,enterEmail:`Будь ласка, введіть адресу електронної пошти`,oidcLoginFailed:`Не вдалося ввійти через OIDC`,oidcErrors:{providerError:`Постачальник ідентифікації повернув помилку`,missingParameters:`У зворотному виклику OIDC відсутні необхідні параметри`,invalidState:`Стан OIDC недійсний або вже використовувався`,stateExpired:`OIDC сеанс входу закінчився — спробуйте ще раз`,providerNotFound:`OIDC постачальника не знайдено`,discoveryFailed:`Не вдалося отримати документ конфігурації OIDC`,invalidDiscovery:`Документ конфігурації OIDC недійсний`,networkError:`Помилка мережі під час обміну токена OIDC`,badResponse:`Неочікувана відповідь під час обміну токеном OIDC.`,noIdToken:`Постачальник OIDC не повернув ID-токен`,validationFailed:`Не вдалося перевірити токен OIDC`,nonceMismatch:`Не збігається nonce OIDC — можлива атака повторного використання`,missingSubClaim:`У токені OIDC відсутнє поле sub`,noLinkedAccount:`Із цим ідентифікатором OIDC не пов’язано жодного локального облікового запису`,accountInactive:`Ваш акаунт неактивний`,userResolutionFailed:`Не вдалося визначити ваш обліковий запис`,internalError:`Під час входу в систему OIDC сталася внутрішня помилка`,tokenExchangeFailed:`Помилка обміну токеном OIDC.`},forgotPasswordTitle:`Забули пароль`,forgotPasswordMessage:`Якщо ви забули свій пароль, зверніться до системного адміністратора, щоб скинути його.`,forgotPasswordEmailMessage:`Введіть адресу електронної пошти, і ми надішлемо вам новий пароль.`,emailAddress:`Адреса електронної пошти`,emailPlaceholder:`your.email@example.com`,cancel:`Скасувати`,sending:`Надсилання...`,sendResetEmail:`Надіслати лист для скидання пароля`,howToReset:`Як скинути пароль:`,resetStep1:`Зверніться до адміністратора Bambuddy.`,resetStep2:`Попросіть скинути ваш пароль у розділі «Керування користувачами»`,resetStep3:`Вони можуть встановити для вас новий тимчасовий пароль`,resetStep4:`Увійдіть із новим паролем і змініть його в налаштуваннях`,gotIt:`Зрозуміло`,resetPassword:{title:`Встановити новий пароль`,subtitle:`Введіть і підтвердьте свій новий пароль нижче.`,newPassword:`Новий пароль`,newPasswordPlaceholder:`Мінімум 8 символів`,confirmPassword:`Підтвердити пароль`,confirmPasswordPlaceholder:`Повторіть новий пароль`,saving:`Збереження…`,submit:`Встановити новий пароль`,backToLogin:`Назад до входу`,passwordsDoNotMatch:`Паролі не збігаються`,passwordTooShort:`Пароль має бути не менше 8 символів`,resetFailed:`Помилка скидання пароля. Можливо, термін дії посилання закінчився.`},twoFA:{title:`Двофакторна автентифікація`,subtitle:`Ваш обліковий запис захищено 2FA. Введіть код підтвердження нижче.`,methodAuthenticator:`Програма автентифікатора`,methodEmail:`Код електронної пошти`,methodBackup:`Резервний код`,instructionsTotp:`Відкрийте програму автентифікації та введіть 6-значний код для Bambuddy.`,instructionsEmail:`На вашу електронну адресу надіслано 6-значний код. Термін дії закінчується через 10 хвилин.`,instructionsEmailNotSent:`Натисніть кнопку нижче, щоб отримати код підтвердження електронною поштою.`,instructionsBackup:`Введіть один із ваших 8-символьних резервних кодів відновлення. Кожен код можна використати лише один раз.`,sendCodeButton:`Надіслати код електронною поштою`,sendingCode:`Надсилання...`,resendCode:`Повторно надіслати код`,codeLabel:`Код підтвердження`,backupCodeLabel:`Резервний код`,codePlaceholder:`000000`,backupCodePlaceholder:`XXXXXXXX`,verifyButton:`Підтвердити`,verifyingButton:`Перевірка...`,backToLogin:`← Назад до входу`,orContinueWith:`або продовжити`,signInWith:`Увійти за допомогою {{provider}}`,enterCode:`Будь ласка, введіть код підтвердження`,sendCodeFailed:`Не вдалося надіслати код підтвердження`,invalidCode:`Невірний код. Спробуйте ще раз.`}},setup:{title:`Налаштування Bambuddy`,subtitle:`Налаштуйте автентифікацію для свого екземпляра Bambuddy.`,enableAuth:`Увімкнути автентифікацію`,adminAccount:`Обліковий запис адміністратора`,adminAccountDesc:`Якщо користувачі-адміністратори вже існують, автентифікацію буде ввімкнено за допомогою наявних облікових записів адміністраторів. Залиште поля нижче порожніми, щоб використовувати наявних адміністраторів, або введіть нові облікові дані, щоб створити нового користувача адміністратора.`,adminUsername:`Ім’я користувача адміністратора`,adminPassword:`Пароль адміністратора`,optionalIfAdminExists:`(необов’язково, якщо є користувачі з правами адміністратора)`,adminUsernamePlaceholder:`Введіть ім’я користувача адміністратора (необов’язково)`,adminPasswordPlaceholder:`Введіть пароль адміністратора (необов’язково)`,confirmPassword:`Підтвердити пароль`,confirmPasswordPlaceholder:`Підтвердити пароль адміністратора`,settingUp:`Налаштування...`,completeSetup:`Завершити налаштування`,toast:{authEnabledAdminCreated:`Увімкнено автентифікацію та створено адміністратора`,authEnabledExistingAdmins:`Увімкнено автентифікацію за допомогою наявних користувачів адміністратора`,setupCompleted:`Налаштування завершено`,enterBothCredentials:`Будь ласка, введіть ім’я користувача та пароль адміністратора або залиште обидва поля порожніми, щоб використовувати наявних користувачів адміністратора`,passwordsDoNotMatch:`Паролі не збігаються`,passwordTooShort:`Пароль має бути не менше 6 символів`}},changePassword:{title:`Змінити пароль`,currentPassword:`Поточний пароль`,currentPasswordPlaceholder:`Введіть поточний пароль`,newPassword:`Новий пароль`,newPasswordPlaceholder:`Введіть новий пароль (мінімум 6 символів)`,confirmPassword:`Підтвердити новий пароль`,confirmPasswordPlaceholder:`Підтвердити новий пароль`,passwordsDoNotMatch:`Паролі не збігаються`,passwordTooShort:`Пароль має бути не менше 6 символів`,changing:`Зміна...`,success:`Пароль успішно змінено`,failed:`Не вдалося змінити пароль`},plateAlert:{title:`Друк призупинено!`,message:`Об’єкти, виявлені на будівельній пластині. Друк було автоматично призупинено. Очистіть пластину та відновіть друк.`,understand:`Я розумію`},camera:{title:`Вид з камери`,invalidPrinterId:`Недійсний ідентифікатор принтера`,live:`Наживо`,snapshot:`знімок`,restartStream:`Перезапустити потік`,refreshSnapshot:`Оновити знімок`,fullscreen:`Повний екран`,exitFullscreen:`Вийти з повноекранного режиму`,connectingToCamera:`Підключення до камери...`,capturingSnapshot:`Зйомка знімка...`,connectionLost:`З’єднання втрачено`,connectionFailed:`Помилка підключення камери`,reconnecting:`Повторне підключення через {{countdown}}с... (спроба {{attempt}}/{{max}})`,reconnectNow:`Повторно підключіться зараз`,cameraUnavailable:`Камера недоступна`,cameraUnavailableDesc:`Переконайтеся, що принтер увімкнено та підключено.`,noCamera:`Камера недоступна`,retry:`Повторити`,cameraStream:`Потік камери`,zoomOut:`Зменшити масштаб`,zoomIn:`Збільшити`,resetZoom:`Скинути масштаб`,recording:`Запис`,startRecording:`Почати запис`,stopRecording:`Зупинити запис`,chamberLight:`Перемкнути освітлення камери`,unavailable:`Камера недоступна`,diagnose:{button:`Діагностувати`,modalTitle:`Діагностика камери`,running:`Виконується діагностика...`,runFailed:`Не вдалося запустити діагностику: {{error}}`,retry:`Запустити знову`,stage:{tcp_reachable:`Доступність мережі`,first_frame:`Захоплення кадру`,live_stream_active:`Активна пряма трансляція`},summary:{all_ok:`Камера працює. Діагностика пройшла всі етапи успішно.`,live_stream_active_healthy:`Камера зараз транслює з останніми кадрами — перевірка не потрібна.`,printer_unreachable:`Принтер недоступний. Перевірте адресу IP, підключення до мережі та чи принтер увімкнено.`,camera_port_closed:`Принтер доступний, але порт камери закритий. Переконайтеся, що в налаштуваннях принтера ввімкнено лише режим LAN і режим розробника.`,no_frame:`Підключено до камери, але кадри не отримано. Повторіть спробу або перевірте, чи камеру ввімкнено в налаштуваннях принтера.`,unknown_failure:`Не вдалося діагностувати камеру з невідомої причини. Подробиці перевірте в журналі підтримки.`},meta:{protocol:`Протокол`,port:`Порт`,profile:`Профіль`}}},groups:{title:`Керування групами`,subtitle:`Керуйте групами дозволів для контролю доступу`,backToSettings:`Назад до налаштувань`,createGroup:`Створити групу`,noPermission:`Ви не маєте дозволу на доступ до цієї сторінки.`,system:`система`,noDescription:`Без опису`,usersCount:`{{count}} користувачів`,permissionsCount:`Дозволів: {{count}}`,edit:`Редагувати`,delete:`Видалити`,toast:{created:`Групу створено успішно`,updated:`Групу успішно оновлено`,deleted:`Групу успішно видалено`,enterGroupName:`Будь ласка, введіть назву групи`},modal:{editGroup:`Редагувати групу`,createGroup:`Створити групу`,cancel:`Скасувати`,saving:`Збереження...`,creating:`Створення...`,saveChanges:`Зберегти зміни`},form:{groupName:`Назва групи`,groupNamePlaceholder:`Введіть назву групи`,systemGroupWarning:`Назви системних груп не можна змінювати`,description:`опис`,descriptionPlaceholder:`Введіть опис (необов’язково)`,permissions:`Дозволи (вибрано {{count}})`},deleteModal:{title:`Видалити групу`,message:`Ви впевнені, що хочете видалити цю групу? Користувачі цієї групи втратять ці дозволи.`,confirm:`Видалити групу`},editor:{title:`Редагувати групу`,createTitle:`Створити групу`,search:`Шукати дозволи...`,selectAll:`Вибрати усі`,clearAll:`Очистити все`,permissionsSelected:`Вибрано: {{count}}`,noResults:`Немає дозволів, що відповідають вашому пошуку`,websocketHint:`Необхідний для оновлень у реальному часі. Без нього інтерфейс повертається до періодичного опитування.`}},users:{title:`Керування користувачами`,subtitle:`Керуйте користувачами та їхнім доступом до вашого екземпляра Bambuddy.`,backToSettings:`Назад до налаштувань`,createUser:`Створити користувача`,noPermission:`Ви не маєте дозволу на доступ до цієї сторінки.`,admin:`адмін`,noGroups:`Немає груп`,active:`Активний`,inactive:`Неактивний`,edit:`Редагувати`,delete:`Видалити`,system:`система`,noGroupsAvailable:`Немає доступних груп`,table:{username:`Ім’я користувача`,groups:`Групи`,status:`Статус`,actions:`Дії`},toast:{created:`Користувача створено успішно`,updated:`Користувача успішно оновлено`,deleted:`Користувача успішно видалено`,fillRequired:`Будь ласка, заповніть усі необхідні поля`,passwordsDoNotMatch:`Паролі не збігаються`,passwordTooShort:`Пароль має бути не менше 6 символів`,ldapProvisioned:`Користувача LDAP «{{username}}» підготовлено`},modal:{createUser:`Створити користувача`,editUser:`Редагувати користувача`,cancel:`Скасувати`,creating:`Створення...`,saving:`Збереження...`,saveChanges:`Зберегти зміни`,advancedAuthSubtitle:`з розширеною автентифікацією`,tabsAriaLabel:`Джерело користувача`,localTab:`Локальний`,ldapTab:`LDAP`,ldapSearchLabel:`Пошук у каталозі`,ldapSearchPlaceholder:`Введіть ім’я користувача, ім’я або електронну адресу...`,ldapMinChars:`Введіть принаймні 2 символи для пошуку`,ldapTypeToSearch:`Почніть вводити текст для пошуку в каталозі LDAP.`,ldapSearching:`Пошук у каталозі...`,ldapNoResults:`У каталозі немає відповідних користувачів`,ldapSearchError:`Помилка пошуку каталогу. Перевірте стан сервера LDAP.`,ldapAlreadyProvisioned:`Уже підготовлено`,ldapSelectedLabel:`Вибране`,ldapProvision:`Підготувати користувача`,ldapProvisioning:`Підготовка...`,ldapErrorProvision:`Не вдалося підготувати користувача. Перевірте стан сервера LDAP і повторіть спробу.`},form:{username:`Ім’я користувача`,usernamePlaceholder:`Введіть ім’я користувача`,email:`Електронна пошта`,emailPlaceholder:`user@example.com`,password:`Пароль`,passwordPlaceholder:`Введіть пароль`,confirmPassword:`Підтвердити пароль`,confirmPasswordPlaceholder:`Підтвердити пароль`,newPasswordPlaceholder:`Введіть новий пароль`,confirmNewPasswordPlaceholder:`Підтвердити новий пароль`,leaveBlankToKeep:`залиште порожнім, щоб зберегти поточне значення`,groups:`Групи`,optional:`необов’язково`,autoGeneratedPassword:`Надійний пароль буде автоматично згенеровано та надіслано користувачеві електронною поштою.`,passwordManagedByAdvancedAuth:`Пароль керується розширеною автентифікацією. Використовуйте «Скинути пароль», щоб надіслати новий пароль користувачеві електронною поштою.`,resetPassword:`Скинути пароль`,resettingPassword:`Скидання пароля...`},deleteModal:{title:`Видалити користувача`,message:`Ви впевнені, що хочете видалити цього користувача? Цю дію не можна скасувати.`,confirm:`Видалити користувача`}},streamOverlay:{title:`Накладання потоку`,invalidPrinterId:`Недійсний ідентифікатор принтера`,cameraStream:`Потік камери`,progress:`Прогрес`,eta:`ETA`,printerIdle:`Принтер неактивний`,printerOffline:`Принтер не в мережі`,status:{printing:`Друк`,paused:`Призупинено`,finished:`Готово`,failed:`Не вдалося`,idle:`Неактивний`,unknown:`Невідомий`}},profiles:{title:`Профілі`,subtitle:`Керуйте профілями слайсера та калібруваннями Pressure Advance`,tabs:{bambuCloud:`Bambu Cloud`,orcaCloud:`Orca Cloud`,local:`Локальні профілі`,kprofiles:`K-профілі`},orcaCloud:{connectedAs:`Підключено як`,connectedShort:`Підключено до Orca Cloud`,logout:`Відключити`,noLogoutPermission:`Ви не маєте дозволу на відключення`,noConnectPermission:`Ви не маєте дозволу на підключення до Orca Cloud`,retry:`Повторити`,connectButton:`Підключити Orca Cloud`,connect:{title:`Підключитися до Orca Cloud`,description:`Увійти у свій обліковий запис Orca Cloud, щоб синхронізувати свої профілі слайсера в Bambuddy.`},device:{title:`Підтвердити Bambuddy в Orca Cloud`,instruction:`Відкрийте Orca Cloud і підтвердьте цей код. Bambuddy підключається автоматично, коли ви підтверджуєте.`,codeLabel:`Ваш код сполучення`,openButton:`Відкрити сторінку підтвердження Orca Cloud`,manualHint:`Або перейдіть до {{url}} і введіть код вище.`,waiting:`Чекаємо на ваше схвалення…`,cancel:`Скасувати`},profiles:{title:`Ваші профілі Orca Cloud ({{count}})`,refresh:`Оновити`,empty:`У вашому обліковому записі Orca Cloud ще не знайдено профілів.`},toast:{disconnected:`Відключено від Orca Cloud`},errors:{startFailed:`Не вдалося розпочати підключення Orca Cloud.`,denied:`Сполучення було відхилено в Orca Cloud.`,expired:`Термін дії коду сполучення минув. Натисніть Підключитися, щоб повторити спробу.`,pollFailed:`Втрачено з’єднання під час очікування підтвердження. Спробуйте ще раз.`}},localProfiles:{title:`Локальні профілі`,subtitle:`Імпорт і керування профілями слайсера з OrcaSlicer`,import:`Імпортувати профілі`,importDesc:`Перетягніть сюди файли .bbscfg, .bbsflmt, .orca_filament, .zip або .json`,importing:`Імпортування…`,search:`Шукати локальні профілі…`,noPresets:`Локальних профілів ще немає`,noSearchResults:`Профілів за вашим запитом не знайдено`,badge:`Локальний`,edit:`Редагувати`,delete:`Видалити`,cancel:`Скасувати`,deleteConfirmTitle:`Видалити профіль`,deleteConfirm:`Видалити цей профіль? Цю дію неможливо скасувати.`,source:`Джерело`,inheritsFrom:`Успадковує`,filamentType:`Тип`,vendor:`Виробник`,compatiblePrinters:`Принтери`,nozzleTemp:`Температура сопла`,cost:`Вартість`,density:`Щільність`,pressureAdvance:`Випередження тиску`,filament:`Філамент`,process:`Процес`,printer:`Принтер`,toast:{importSuccess:`Імпортовано профілів: {{count}}`,importSkipped:`Пропущено профілів-дублікатів: {{count}}`,importError:`Помилок під час імпорту: {{count}}`,deleted:`Профіль видалено`,updated:`Профіль оновлено`}},connectedAs:`Підключено як`,signInExpiredTitle:`Термін входу в Bambu Cloud минув`,signInExpiredBody:`Bambu Lab більше не приймає збережений токен. Увійдіть ще раз, щоб відновити хмарні профілі, імпорт MakerWorld і перевірку прошивки.`,logout:`Вийти`,noLogoutPermission:`Ви не маєте дозволу на вихід`,failedToLoad:`Не вдалося завантажити профілі`,retry:`Повторити`,time:{justNow:`Щойно`,minsAgo:`{{count}}хв тому`,hoursAgo:`{{count}} год тому`,daysAgo:`{{count}} дн. тому`},toast:{loggedOut:`Вихід виконано`},login:{title:`Підключитися до Bambu Cloud`,subtitle:`Синхронізуйте профілі слайсера між пристроями`,email:`Електронна пошта`,password:`Пароль`,region:`Регіон`,regionGlobal:`Глобальний`,regionChina:`Китай`,verificationCode:`Код підтвердження`,totpCode:`Код автентифікатора`,checkEmail:`Перевірте свою електронну пошту ({{email}}), щоб отримати 6-значний код`,enterTotpHint:`Введіть 6-значний код із програми автентифікації`,accessToken:`Токен доступу`,accessTokenHint:`Вставте токен доступу Bambu Cloud. Облікові записи в китайському регіоні мають використовувати цей спосіб, оскільки вони прив’язані до телефона й вхід електронною поштою недоступний. У вікі описано, як отримати токен із файлів cookie MakerWorld.`,back:`Назад`,loginButton:`Увійти`,verifyButton:`Підтвердити`,setTokenButton:`Установити токен`,useToken:`Натомість використати токен доступу`,useEmail:`Увійти за допомогою електронної пошти`,toast:{loggedIn:`Успішно ввійшли`,codeSent:`Код підтвердження надіслано на вашу електронну адресу`,enterTotp:`Введіть код із програми автентифікації`,tokenSet:`Токен успішно встановлено`}},presets:{myPreset:`Мій профіль (можна редагувати)`,duplicate:`Дублювати`,editable:`Можна редагувати`,failedToLoadDetails:`Не вдалося завантажити відомості про профіль`,deleteConfirm:`Видалити цей профіль?`,deleteWarning:`Це назавжди видалить "{{name}}" із Bambu Cloud. Це неможливо скасувати.`,noDuplicatePermission:`Ви не маєте дозволу на дублювання стилів`,noEditPermission:`Ви не маєте дозволу редагувати стилі`,noDeletePermission:`Ви не маєте дозволу на видалення стилів`,types:{filament:`Попереднє налаштування філаменту`,printer:`Попереднє налаштування принтера`,process:`Попереднє налаштування процесу`},toast:{deleted:`Попереднє налаштування видалено`,created:`Попереднє налаштування створено`,updated:`Попереднє налаштування оновлено`,duplicated:`Профіль продубльовано`,fieldAdded:`Додано поле "{{key}}".`,exported:`Попереднє налаштування експортовано`},baseLabel:`База: {{name}}`,currentLabel:`Поточний профіль: {{name}}`,newPreset:`Нове налаштування`,editPreset:`Редагувати профіль`,duplicatePreset:`Дублювати профіль`,createNewPreset:`Створити новий профіль`,customizeSettings:`Налаштуйте параметри для нового стилю`,compareWithBase:`Порівняти з базовим профілем`,compare:`Порівняйте`,basePreset:`Базове передналаштування`,selectBasePreset:`Виберіть базове налаштування...`,presetName:`Назва профілю`,myCustomPreset:`Мій власний профіль`,inheritsFrom:`Успадковує від`,dropJsonToImport:`Відпустіть JSON, щоб імпортувати`,tabs:{common:`Основні`,allFields:`Всі поля`},availableFields:`Доступні поля`,searchFieldsPlaceholder:`Шукати поля...`,noMatchingFields:`Немає відповідних полів`,allFieldsAdded:`Всі поля додано`,addCustomField:`Додати спеціальне поле`,yourOverrides:`Ваші перевизначення`,noOverridesYet:`Перевизначення ще немає`,clickFieldsToAdd:`Натисніть поля ліворуч, щоб додати їх`,saveAsTemplate:`Зберегти як шаблон`,jsonTip:`Порада: перетягніть файл .json у будь-яке місце на цьому модалі, щоб імпортувати налаштування`},cloudView:{searchPlaceholder:`Шукати профілі...`,templates:`Шаблони`,refresh:`Оновити`,newPreset:`Нове налаштування`,clearFilters:`Очистити фільтри`,compareMode:`Режим порівняння`,selectAnotherPreset:`Вибрати інший попередній набір {{type}}.`,clickTwoPresets:`Клацніть два стилі одного типу, щоб порівняти`,selectFirst:`1. Виберіть перший`,selectSecond:`2. Виберіть другий`,compareNow:`Порівняти зараз`,lastSynced:`Остання синхронізація:`,showingCount:`Показано профілів: {{showing}} із {{total}}`,noPresetsFound:`Попередніх налаштувань не знайдено`,columns:{filament:`Філамент`,process:`процес`,printer:`Принтер`},noFilamentPresets:`Немає профілів філаменту`,noProcessPresets:`Немає профілів процесу`,noPrinterPresets:`Немає профілів принтера`,filters:{type:`Тип`,owner:`Власник`,printer:`Принтер`,nozzle:`Сопло`,filament:`Філамент`,layer:`Шар`,all:`Усі`,myPresets:`Мої профілі`,builtIn:`Вбудований`,process:`процес`},noTemplatesPermission:`Ви не маєте дозволу на керування шаблонами`,noRefreshPermission:`Ви не маєте дозволу оновлювати профілі`,noCreatePermission:`Ви не маєте дозволу створювати профілі`},templates:{title:`Швидкі шаблони`,noTemplates:`Шаблонів ще немає`,createFirst:`Створіть шаблони в редакторі профілів`,typeFilter:`тип:`,deleteTitle:`Видалити шаблон`,deleteWarning:`Цю дію не можна скасувати`,deleteConfirm:`Ви впевнені, що хочете видалити "{{name}}"?`,namePlaceholder:`Назва шаблону`,descriptionPlaceholder:`опис`,settingsJson:`Налаштування (JSON)`,fieldsCount:`Полів: {{count}}`,shownInModals:`Показано в модальних формах`,hiddenInModals:`Приховано в модальних формах`,apply:`Застосувати`,toast:{deleted:`Шаблон видалено`,updated:`Шаблон оновлено`,created:`Шаблон створено`,applied:`Шаблон застосовано`}}},support:{debugLoggingActive:`Журнал налагодження активний`,manageLogs:`Керувати`,collectItem7:`Підключення принтерів і версії прошивок`,collectItem8:`Статус інтеграції (Spoolman, MQTT, HA)`,collectItem9:`Мережеві інтерфейси (лише підмережі)`,collectItem10:`Версії пакетів Python`,collectItem11:`Перевірки справності бази даних`,collectItem12:`Відомості про середовище Docker`,bundleGenerating:`Створення пакета...`,bundleStepConnection:`Запуск перевірки підключення принтера`,bundleStepVirtualPrinters:`Виконання перевірок налаштування віртуального принтера`,bundleStepLogScan:`Сканування останніх журналів на наявність відомих проблем`,bundleStepBuild:`Створення ZIP-пакета підтримки`},fileManager:{title:`Менеджер файлів`,subtitle:`Упорядковуйте файли друку та керуйте ними`,uploadFiles:`Вивантажити файли`,newFolder:`Нова папка`,folderName:`Назва папки`,folderNamePlaceholder:`наприклад, функціональні частини`,renameFile:`Перейменувати файл`,renameFolder:`Перейменувати папку`,invalidFilenameChar:`Символ «{{char}}» не можна використовувати в назвах файлів для друку. SD-картка принтера не приймає такі символи: < > : " / \\ | ? *`,moveFiles:`Перемістити файли: {{count}}`,rootNoFolder:`Корінь (без папки)`,current:`поточний`,linkFolder:`Пов’язати папку`,linkFolderDescription:`Пов’язати «{{name}}» із проєктом або архівом для швидкого доступу.`,project:`Проєкт`,archive:`Архів`,noProjectsFound:`Проєкти не знайдено`,noArchivesFound:`Архіви не знайдено`,unlink:`Від’єднати`,link:`Пов’язати`,dragDropFiles:`Перетягніть файли сюди`,dropFilesHere:`Перетягніть файли сюди`,releaseToUpload:`Відпустіть, щоб вивантажити`,orClickToBrowse:`або натисніть, щоб переглянути`,allFileTypesSupported:`Підтримуються всі типи файлів. Файли ZIP будуть розпаковані.`,zipFilesDetected:`Виявлено файли ZIP.`,zipExtractOptions:`Файли ZIP будуть розпаковані. Виберіть спосіб обробки структури папок:`,preserveZipStructure:`Зберегти структуру папок із ZIP`,createFolderFromZip:`Створити папку з назви ZIP-файлу`,stlThumbnailGeneration:`Створення мініатюр STL`,zipMayContainStl:`Файли ZIP можуть містити файли STL. Мініатюри можна генерувати під час вилучення.`,thumbnailsCanBeGenerated:`Ескізи можна створити для файлів STL. Обробка великих моделей може зайняти більше часу.`,generateThumbnailsForStl:`Створювати мініатюри для файлів STL`,threemfDetected:`Виявлено файли 3MF.`,threemfExtractionInfo:`Модель принтера, матеріал, колір і параметри друку будуть автоматично витягнуті з файлів 3MF.`,willBeExtracted:`Буде розпаковано`,filesExtracted:`Розпаковано файлів: {{count}}`,uploadComplete:`Вивантаження завершено. Успішно: {{succeeded}}`,uploadFailed:`Не вдалося вивантажити`,zipFilesFailed:`Не вдалося обробити файлів: {{count}}`,uploading:`Вивантаження...`,changeLink:`Змінити посилання...`,linkTo:`Посилання на...`,linkToProjectOrArchive:`Посилання на проєкт або архів`,generateThumbnail:`Створити мініатюру`,generateThumbnails:`Створити мініатюри`,generateThumbnailsForMissing:`Створити відсутні мініатюри файлів STL`,gridView:`Вигляд сітки`,listView:`Перегляд списку`,lowDiskSpaceWarning:`Попередження про брак місця на диску`,lowDiskSpaceDetails:`Вільно лише {{free}} із {{total}}. У налаштуваннях задано поріг {{threshold}} ГБ.`,files:`Файли`,folders:`Папки`,size:`Розмір`,free:`Вільно`,allFiles:`Усі файли`,allExternal:`Зовнішні`,externalIsEmpty:`Немає зовнішніх файлів`,externalEmptyDescription:`Тут відображатимуться файли у ваших пов’язаних зовнішніх папках.`,wrap:`Перенесення`,enableTextWrapping:`Увімкнути перенесення тексту`,disableTextWrapping:`Вимкнути перенесення тексту`,collapse:`Згорнути`,collapseFoldersByDefault:`За замовчуванням згорнути папки`,expandFoldersByDefault:`Розгорнути папки за замовчуванням`,folderSort:`Сортування папок`,folderSortByName:`За назвою`,folderSortByActivity:`За останніми діями`,dragToResizeTooltip:`Перетягніть, щоб змінити розмір, двічі клацніть, щоб скинути`,searchFiles:`Пошук файлів...`,searchSubfoldersHint:`Включаючи вкладені папки`,readme:{truncated:`Усічений`,show:`Показати README`,hide:`Приховати README`,label:`README`},tags:{title:`Теги`,subtitle:`Файли міток для наскрізної фільтрації — іграшки, безпечні для дітей, лише PETG, будь-що.`,manage:`Теги`,manageTitle:`Керувати каталогом тегів`,add:`Новий тег`,edit:`Перейменувати тег`,name:`Назва`,fileCount:`Файли`,empty:`Тегів ще немає. Створіть його, щоб розпочати маркування файлів.`,noMatches:`Немає відповідних тегів.`,createPlaceholder:`напр. іграшки, безпечні для дітей, petg`,createButton:`Створити`,nameRequired:`Потрібно вказати назву.`,searchPlaceholder:`Фільтр тегів...`,created:`Тег створено.`,updated:`Тег перейменовано.`,deleted:`Тег видалено.`,saveFailed:`Не вдалося зберегти тег.`,deleteFailed:`Не вдалося видалити тег.`,applyFailed:`Не вдалося застосувати теги.`,applyAdd:`Додати теги`,applyRemove:`Видалити теги`,applyAddSuccess:`Додано теги {{count}} до файлів {{files}}.`,applyRemoveSuccess:`Видалено теги {{count}} у файлах {{files}}.`,actionAdd:`Додати до вибраних файлів`,actionRemove:`Видалити з вибраних файлів`,tagAction:`Тег`,bulkTitle:`Позначити вибрані файли ({{count}})`,bulkTooltip:`Додати або видалити теги для кожного вибраного файлу.`,noPermission:`Ви не маєте дозволу позначати файли тегами.`,filterLabel:`Фільтрування за:`,clearAll:`Очистити все`,confirmDelete:`Видалити тег "{{name}}"?`,confirmDeleteMessage:`Це видалить тег з каталогу. Файли зберігають інші теги.`,confirmDeleteInUseMessage:`Цей тег призначено файлам ({{count}}). Його буде видалено з усіх файлів, але самі файли залишаться без змін.`,editAria:`Редагувати {{name}}`,deleteAria:`Видалити {{name}}`},allTypes:`Усі типи`,prints:`Друки`,ascending:`За зростанням`,descending:`За спаданням`,showModified:`Показати змінені дати`,hideModified:`Приховати змінені дати`,lastModified:`Востаннє змінено`,lastActivity:`Остання активність`,resultsCount:`{{showing}} з {{total}} файлів`,selectAll:`Вибрати усі`,deselectAll:`Зняти вибір із усіх`,selected:`Вибрано: {{count}}`,adding:`Додавання...`,loadingFiles:`Завантаження файлів...`,folderIsEmpty:`Папка порожня`,noFilesYet:`Файлів ще немає`,folderEmptyDescription:`Щоб почати, вивантажте файли або перемістіть їх до цієї папки.`,noFilesDescription:`Вивантажте файли, щоб упорядковувати матеріали для друку.`,noMatchingFiles:`Немає відповідних файлів`,noMatchingFilesDescription:`Жоден файл не відповідає вашим поточним критеріям пошуку чи фільтру.`,clearFilters:`Очистити фільтри`,printedCount:`Надруковано {{count}}x`,uploadedBy:`Вивантажено`,deleteFolder:`Видалити папку`,deleteFile:`Видалити файл`,deleteFilesCount:`Видалити файли {{count}}.`,deleteFolderConfirm:`Ви впевнені, що хочете видалити цю папку? Усі файли всередині також буде видалено.`,deleteFileConfirm:`Ви впевнені, що хочете видалити цей файл?`,deleteFilesConfirm:`Ви впевнені, що бажаєте видалити вибрані файли {{count}}? Цю дію не можна скасувати.`,deleting:`Видалення...`,noPermissionRenameFolder:`Ви не маєте дозволу на перейменування папок`,noPermissionLinkFolder:`Ви не маєте дозволу на пов’язування папок`,noPermissionDeleteFolder:`Ви не маєте дозволу на видалення папок`,onlyEmptyFoldersDeletable:`Можна видаляти лише порожні папки`,noPermissionPrint:`Ви не маєте дозволу на друк`,noPermissionAddToQueue:`Ви не маєте дозволу на додавання в чергу`,noPermissionSlice:`Ви не маєте дозволу нарізати файли`,noPermissionDownload:`У вас немає дозволу на завантаження файлів`,noPermissionRenameFile:`Ви не маєте дозволу на перейменування цього файлу`,noPermissionGenerateThumbnail:`Ви не маєте дозволу створювати мініатюри`,noPermissionDeleteFile:`Ви не маєте дозволу на видалення цього файлу`,noPermissionCreateFolder:`Ви не маєте дозволу на створення папок`,noPermissionUpload:`Ви не маєте дозволу на вивантаження файлів`,noPermissionMoveFiles:`Ви не маєте дозволу на переміщення файлів`,noPermissionDeleteFiles:`Ви не маєте дозволу на видалення файлів`,linkExternal:`Зовнішнє посилання`,linkExternalFolder:`Посилання на зовнішню папку`,linkExternalFolderDescription:`Змонтуйте каталог хоста (NAS, USB, спільний мережевий ресурс) у файловому менеджері. Файли не копіюються — доступ до них здійснюється безпосередньо з початкового шляху.`,externalFolderNamePlaceholder:`наприклад, NAS Друкує`,externalPath:`Шлях хоста`,externalPathHelp:`Абсолютний шлях до каталогу на хості Docker. Має бути прив’язано до контейнера.`,readOnly:`Тільки для читання`,readOnlyHelp:`забороняє вивантаження й видалення`,showHiddenFiles:`Показати приховані файли (dotfiles)`,externalFolder:`Зовнішня папка`,scanFolder:`Сканувати`,toast:{folderCreated:`Папка створена`,folderDeleted:`Папку видалено`,fileDeleted:`Файл видалено`,filesDeleted:`Видалені файли {{count}}.`,filesMoved:`Файли переміщено`,folderLinked:`Папку пов’язано`,folderUnlinked:`Папку від’єднано`,externalFolderLinked:`Зовнішня папка пов’язана та просканована`,folderScanned:`Сканування завершено: {{added}} додано, {{removed}} видалено`,addedToQueue:`Додано до черги файлів: {{count}}`,addedToQueuePartial:`Додано: {{added}}; не вдалося додати: {{failed}}`,failedToAddToQueue:`Не вдалося додати файли: {{error}}`,fileRenamed:`Файл перейменовано`,folderRenamed:`Папку перейменовано`,thumbnailsGenerated:`Створено мініатюри {{count}}`,thumbnailsGeneratedPartial:`Створено мініатюри {{succeeded}}, {{failed}} не вдалося`,noStlMissingThumbnails:`Немає файлів STL без мініатюр`,failedToGenerateThumbnails:`Не вдалося створити мініатюри: {{error}}`,thumbnailGenerated:`Створено мініатюру`,failedToGenerateThumbnail:`Не вдалося створити мініатюру: {{error}}`}},projects:{title:`Проєкти`,subtitle:`Організовуйте та відстежуйте свої проєкти 3D-друку`,newProject:`Новий проєкт`,editProject:`Редагувати проєкт`,deleteProject:`Видалити проєкт`,projectName:`Назва проєкту`,description:`опис`,noProjects:`Проєктів ще немає`,noProjectsFiltered:`Немає проєктів {{status}}.`,noProjectsFilteredHelp:`У вас немає {{status}} проєктів. Проєкти з’являться тут, коли їхній статус зміниться.`,createFirst:`Створіть свій перший проєкт, щоб почати впорядковувати пов’язані роздруківки, відстежувати прогрес і керувати збірками.`,createFirstButton:`Створіть свій перший проєкт`,create:`Створити`,files:`Файли`,prints:`Принти`,plates:`пластини`,parts:`частин`,lastModified:`Остання зміна`,deleteConfirm:`Ви впевнені, що хочете видалити цей проєкт? Архіви та елементи черги буде від’єднано, але не видалено.`,addFiles:`Додати файли`,removeFile:`Видалити файл`,viewDetails:`Переглянути деталі`,namePlaceholder:`наприклад, Voron 2.4 Build`,descriptionPlaceholder:`Додатковий опис...`,urlLabel:`URL`,urlPlaceholder:`https://makerworld.com/...`,urlInvalid:`URL має починатися з http:// або https://`,openExternalUrl:`Відкритий проєкт URL`,coverImageLabel:`Фото обкладинки`,coverImageAlt:`Обкладинка проєкту`,coverImageUpload:`Вивантажити`,coverImageReplace:`Замінити`,coverImageRemove:`видалити`,color:`Колір`,targetPlates:`Цільові пластини`,targetPlatesPlaceholder:`наприклад, 25`,targetPlatesHelp:`Кількість завдань друку`,targetParts:`Цільові частини`,targetPartsPlaceholder:`наприклад, 150`,targetPartsHelp:`Загальна кількість необхідних об’єктів`,targetSets:`Копій кожного файлу`,targetSetsPlaceholder:`наприклад, 10`,targetSetsHelp:`Кількість друків кожного придатного до друку файлу`,tagsLabel:`Теги (розділені комами)`,tagsPlaceholder:`напр., ворон, функціональний, подарунок`,dueDate:`Термін виконання`,priority:`Пріоритет`,priorityLow:`Низький`,priorityNormal:`нормальний`,priorityHigh:`Високий`,priorityUrgent:`Терміново`,statusActive:`Активний`,statusCompleted:`Виконано`,statusArchived:`Архівовано`,done:`Готово`,completed:`завершено`,failed:`не вдалося`,inQueue:`в черзі`,noPrintsYet:`Ще немає відбитків`,printJobs:`Завдання друку (пластини)`,partsPrinted:`Надруковані частини`,failedParts:`Вийшли з ладу деталі`,import:`Імпорт`,export:`Експорт`,importProject:`Імпорт проєкту`,exportAll:`Експортуйте всі проєкти`,loading:`Завантаження проєктів...`,noEditPermission:`Ви не маєте дозволу на редагування проєктів`,noDeletePermission:`Ви не маєте дозволу на видалення проєктів`,noCreatePermission:`Ви не маєте дозволу на створення проєктів`,noImportPermission:`Ви не маєте дозволу на імпорт проєктів`,noExportPermission:`Ви не маєте дозволу на експорт проєктів`,toast:{created:`Проєкт створено`,updated:`Проєкт оновлений`,deleted:`Проєкт видалено`,imported:`Проєкт імпортовано`,multipleImported:`{{count}} проєкти імпортовані`,importFailed:`Помилка імпорту`,exported:`Експортовані проєкти (лише метадані)`}},projectDetail:{notFound:`Проєкт не знайдено`,backToProjects:`Назад до проєктів`,export:`Експорт`,exportProject:`Експортний проєкт`,noExportPermission:`Ви не маєте дозволу на експорт проєктів`,noEditPermission:`Ви не маєте дозволу на редагування проєктів`,partOf:`частина:`,priorityLabel:`Пріоритет:`,noPrints:`У цьому проєкті ще немає роздруківок`,status:{active:`Активний`,completed:`Виконано`,archived:`Архівовано`},priority:{low:`Низький`,normal:`нормальний`,high:`Високий`,urgent:`Терміново`},dueDate:{overdue:`Прострочена`,today:`Термін виконання сьогодні`,daysLeft:`Залишилося {{count}} днів`},progress:{platesProgress:`Пластини Прогрес`,partsProgress:`Прогрес запчастин`,setsProgress:`Завершені комплекти`,sets:`комплектів`,setsHint:`Комплект вважається завершеним, коли кожен придатний до друку файл надруковано стільки разів`,printJobs:`завдання друку`,parts:`частин`,percentComplete:`{{percent}}% виконано`,remaining:`Залишилося {{count}}.`},stats:{printJobs:`Завдання друку`,total:`всього`,failed:`{{count}} не вдалося`,partsPrinted:`Надруковані частини {{count}}.`,printTime:`Час друку`,filamentUsed:`Філамент, що використовується`},cost:{title:`Відстеження витрат`,filamentCost:`Вартість філаменту`,energy:`Енергія`,totalCost:`Загальна вартість`,total:`Всього`,includesBom:`в т.ч. BOM`,budget:`Бюджет`,remaining:`Залишилося`},subProjects:{title:`Підпроєкти ({{count}})`},notes:{title:`Примітки`,noEditPermission:`Ви не маєте дозволу редагувати нотатки`,placeholder:`Додайте примітки щодо цього проєкту...`,empty:`Приміток ще немає. Натисніть Редагувати, щоб додати примітки.`},files:{title:`Файли`,linkFolders:`Зв’язувати папки з файлового менеджера`,forQuickAccess:`до цього проєкту для швидкого доступу.`,fileCount:`Файлів: {{count}}`,empty:`Немає пов’язаних папок. Перейдіть до файлового менеджера та зв’яжіть папку з цим проєктом.`,printedCount:`Надруковано разів: {{count}}`,progressTooltip:`Завершено друків: {{done}} із {{target}}`,noFiles:`У цій папці немає файлів.`},bom:{title:`Перелік матеріалів`,acquired:`{{completed}}/{{total}} придбано`,showAll:`Показати все`,hideDone:`Сховати готове`,addPart:`Додати частину`,noAddPermission:`Ви не маєте дозволу додавати частини`,partNamePlaceholder:`Назва деталі (наприклад, гвинти M3x8)`,partName:`Назва частини`,qty:`кількість`,price:`Ціна ({{currency}})`,sourcingUrlPlaceholder:`URL джерела (необов’язково)`,remarksPlaceholder:`Примітки (необов’язково)`,deletePart:`Видалити частину`,deleteConfirm:`Ви впевнені, що хочете видалити "{{name}}"?`,noUpdatePermission:`Ви не маєте дозволу на оновлення частин`,noEditPermission:`Ви не маєте дозволу редагувати частини`,noDeletePermission:`Ви не маєте дозволу на видалення частин`,totalCost:`Загальна вартість:`,empty:`Немає частин у описі матеріалів. Додайте обладнання, електроніку чи інші компоненти, щоб відстежувати, що потрібно отримати.`},timeline:{title:`Хронологія діяльності`,empty:`Активності ще немає.`},template:{saveAsTemplate:`Зберегти як шаблон`,noCreatePermission:`Ви не маєте дозволу на створення шаблонів`},queue:{title:`Черга`,viewAll:`Переглянути всі`,printing:`Друкується: {{count}}`,queued:`{{count}} у черзі`},prints:{title:`Друки ({{count}})`},toast:{projectUpdated:`Проєкт оновлений`,partAdded:`Частина додана`,partRemoved:`Частину видалено`,exportFailed:`Помилка експорту`,projectExported:`Проєкт експортовано`,templateCreated:`Шаблон створено`}},system:{title:`Інформація про систему`,version:`Версія`,uptime:`Час роботи`,cpuUsage:`CPU Використання`,memoryUsage:`Використання пам’яті`,diskUsage:`Використання диска`,networkInfo:`Інформація про мережу`,logs:`Журнали`,debugMode:`Режим налагодження`,enableDebug:`Увімкнути журнал налагодження`,disableDebug:`Вимкнути ведення журналу налагодження`,downloadLogs:`Завантажити журнали`,clearLogs:`Очистити журнали`,dockerInfo:`Docker Інформація`,containerName:`Назва контейнера`,imageName:`Назва зображення`,platform:`Платформа`,architecture:`Архітектура`},sponsors:{sectionTitle:`Незалежний і фінансований громадою`,tagline:`Bambuddy є безкоштовним і залишається таким, тому що люди вирішили його підтримати. Ні VC, ні блокування в хмарі.`,viewSupporters:`Переглянути прихильників`,toastPrints:`Завершено друків із Bambuddy: {{count}}. Bambuddy залишається безкоштовним завдяки своїм прихильникам.`,toastCost:`За допомогою Bambuddy обліковано філаменту на {{total}}. Дізнайтеся, хто допомагає проєкту залишатися незалежним.`,toastArchives:`Заархівовано друків із Bambuddy: {{count}}. Дізнайтеся, хто допомагає проєкту залишатися незалежним.`,toastAnniversary:`Рік з Bambuddy! Подивіться, хто зберігає незалежність проєкту.`,toastVersionUpdate:`Оновлено до v{{version}}. Bambuddy залишається безкоштовним завдяки своїм прихильникам.`,toastBusiness:`Використовуєте Bambuddy на принтерах ({{count}})? Для команд доступний план підтримки: пріоритетні виправлення, виставлення рахунків і прямий зв’язок із супровідником.`,businessCta:`Bambuddy для бізнесу`,businessTitle:`Bambuddy для бізнесу`,businessTagline:`Ви використовуєте принтери {{count}}. Пріоритетна підтримка, комерційне ліцензування та виставлення рахунків доступні для команд і друкарень.`},library:{title:`Бібліотека філаментів`,addFilament:`Додати філамент`,editFilament:`Редагувати філамент`,deleteFilament:`Видалити філамент`,vendor:`Продавець`,material:`матеріал`,color:`Колір`,kFactor:`Фактор K`,temperature:`температура`,noFilaments:`У бібліотеці немає філаментів`,deleteConfirm:`Ви впевнені, що хочете видалити цю філамент?`,importFromPrinter:`Імпорт із принтера`,exportToFile:`Експорт у файл`,runWithPipeline:{actionLabel:`Запустити з конвеєром`,noPermission:`Ви не маєте дозволу на запуск конвеєрів`,modalTitle:`Запустити з конвеєром`,confirmTitle:`Підтвердити запуск`,confirmIntro:`Під час попередньої перевірки виявлено проблеми з цим запуском`,sourceHint:`Джерело`,pipelineHint:`Конвеєр`,targetHint:`Ціль`,pipelineListAria:`Наявні конвеєри`,runAnyway:`Усе одно запустити`,loading:`Завантаження…`,empty:`Збережених конвеєрів ще немає. Відкрийте вікно нарізання й натисніть «Зберегти як конвеєр», щоб створити його.`,noTarget:`Цільовий принтер не встановлено`,noTargetMessage:`Для цього конвеєра не задано цільовий принтер. Відкрийте конвеєр у налаштуваннях і виберіть принтер.`,copies:`Копії`,copiesHint:`максимум {{n}}`,classTarget:`Будь-який {{model}}`,toast:{started:`Пуск конвеєра розпочато`,failed:`Не вдалося розпочати запуск`},issue:{printerNotSet:`У цьому конвеєрі не встановлено цільовий принтер.`,printerNotFound:`Цільовий принтер більше не існує.`,printerDisabled:`Цільовий принтер вимкнено.`,printerOffline:`Цільовий принтер не в мережі.`,filamentType:`Слот філаменту {{slot}}: очікується {{expected}}, в AMS — {{actual}}`,filamentColor:`Слот філаменту {{slot}}: колір не збігається (очікується {{expected}}, в AMS — {{actual}})`,amsSlotMissing:`Слот AMS {{slot}} недоступний на цьому принтері`,filamentUnverified:`Філамент для слота {{slot}} походить із хмарного або стандартного профілю, тому його неможливо перевірити заздалегідь.`,noClassMatches:`Жоден принтер у цій інсталяції не належить до цільового класу моделей конвеєра ({{expected}}).`,classNotSet:`Ціллю конвеєра вибрано клас принтерів, але модель не задано.`}}},slice:{title:`Нарізання моделі`,action:`Нарізати`,actionAll:`Нарізати всі пластини ({{count}})`,actionAllTitle:`Нарізати всі пластини в один багатопластинний результат (один архів). Вибір філаменту охоплює всі слоти, визначені проєктом.`,allPlatesToggle:`Нарізати всі пластини ({{count}})`,slicing:`Нарізання…`,printer:`Профіль принтера`,process:`Профіль процесу`,filament:`Профіль філаменту`,filamentSlot:`Філамент {{index}} ({{type}})`,selectPreset:`— Виберіть профіль —`,loadingPresets:`Завантаження профілів…`,analyzingPlateFilaments:`Аналіз філаментів пластини…`,analyzingPlateFilamentsHint:`Виконується попереднє нарізання, щоб визначити, які слоти AMS використовує ця пластина. Результат кешується, тому повторне відкриття відбувається миттєво.`,previewToast:`Аналіз {{name}} — {{elapsed}}`,previewWithProgress:`Аналіз {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}`,notUsedByPlate:`— не використовується на цій пластині`,noPresetsForSlot:`Немає профілів`,otherPrinters:`Інші принтери`,presetsLoadFailed:`Не вдалося завантажити профілі. Спочатку імпортуйте їх у розділі Налаштування → Профілі.`,refreshPresets:`Оновити`,refreshPresetsTitle:`Оновити профілі — отримати найновіші хмарні та вбудовані списки (скористайтеся після видалення профілю в Bambu Studio або Bambu Handy)`,allPresetsRequired:`Потрібно вибрати всі профілі`,useEmbedded:`Використати вбудовані налаштування файлу`,useEmbeddedHint:`Нарізати модель із налаштуваннями автора файлу — стінками, заповненням і філаментом — замість профілів вище. Ця можливість доступна, оскільки модель принтера відповідає файлу.`,designSettings:`Зберегти налаштування автора`,designSettingsHint:`Цей файл змінює {{count}} налаштувань друку порівняно зі стандартним профілем.`,designSettingsSelected:`Вибрано {{selected}} із {{total}}`,designSettingsPrinterCoupled:`залежить від принтера`,designSettingsPrinterCoupledHint:`Значення підібрано для принтера, під який створено файл, — на вашому воно може бути неправильним або поза допустимим діапазоном.`,enqueuing:`Надсилання завдання нарізання…`,queued:`У черзі…`,failed:`Не вдалося виконати нарізання. Перевірте журнали слайсера.`,startedToast:`Нарізання {{name}} у фоновому режимі…`,queuedToast:`У черзі: {{name}} — {{elapsed}}`,runningToast:`Нарізання {{name}} — {{elapsed}}`,runningWithProgress:`{{name}} — {{stage}} ({{percent}}%) — {{elapsed}}`,runningWithProgressMultiPlate:`Пластина {{plateIndex}} з {{plateCount}} • {{name}} — {{stage}} ({{percent}}%) — {{elapsed}}`,completedToast:`Нарізання {{name}} завершено`,failedTitle:`Помилка нарізання`,failedToast:`Помилка нарізання {{name}}: {{detail}}`,tier:{local:`Імпортовані`,cloud:`Bambu Cloud`,orcaCloud:`Orca Cloud`,standard:`Стандартний`},cloud:{notAuthenticated:`Увійдіть у Bambu Cloud (Налаштування → Профілі → Bambu Cloud), щоб переглянути хмарні профілі.`,expired:`Сеанс Bambu Cloud завершився — увійдіть знову, щоб оновити хмарні профілі.`,unreachable:`Bambu Cloud зараз недоступний. Локальні та стандартні профілі й надалі працюють.`},orcaCloud:{notAuthenticated:`Увійдіть до Orca Cloud (Профілі → Orca Cloud), щоб переглянути профілі Orca.`,expired:`Сеанс Orca Cloud завершився — увійдіть ще раз, щоб оновити профілі Orca.`,unreachable:`Orca Cloud зараз недоступний. Інші профілі й надалі працюють.`},bedType:{label:`Друкарська пластина`,auto:`Авто (використовувати профіль процесу)`,coolPlate:`Холодна друкарська пластина`,coolPlateSuperTack:`Cool Plate SuperTack`,engineering:`Інженерна пластина`,highTemp:`Високотемпературна пластина`,texturedPEI:`Текстурована PEI-пластина`,smoothPEI:`Гладка PEI-пластина`},pipelines:{label:`Конвеєр`,applyAria:`Застосувати конвеєр`,applyPrompt:`Застосувати конвеєр…`,empty:`Немає збережених конвеєрів`,saveButton:`Зберегти як конвеєр`,saveTitle:`Зберегти поточний вибір чотирьох слотів як конвеєр для повторного використання`,namePlaceholder:`Назва конвеєра`,nameAria:`Нова назва конвеєра`,toast:{applied:`Застосовано "{{name}}"`,saved:`Конвеєр збережено`,saveFailed:`Не вдалося зберегти`}}},spoolman:{title:`Spoolman Інтеграція`,enabled:`Spoolman Увімкнено`,url:`Spoolman URL`,connected:`Підключено`,disconnected:`Не підключено`,testConnection:`Тестове підключення`,sync:`Синхронізувати`,syncing:`Синхронізація...`,lastSync:`Остання синхронізація`,linkToSpoolman:`Посилання на Spoolman`,openInSpoolman:`Відкрити в Spoolman`,unlinkSpool:`Від’єднати котушка`,unlinkConfirmTitle:`Скасувати призначення котушки?`,unlinkConfirmMessage:`Це призведе до видалення котушки з цього слота. Самі дані котушки залишаться незмінними.`,selectSpool:`Вибрати Spool`,noUnlinkedSpools:`Немає непризначених котушок`,linkSuccess:`Котушку успішно призначено`,linkFailed:`Не вдалося призначити котушку`,unlinkSuccess:`Призначення котушки успішно скасовано`,unlinkFailed:`Не вдалося скасувати призначення котушки`,linkedSpool:`Призначена котушка`,spoolId:`Ідентифікатор котушки`,fillSourceLabel:`(Spoolman)`,weight:`вага`,remaining:`Залишилося`,disableWeightSync:`Вимкнути синхронізацію приблизної ваги AMS.`,disableWeightSyncDesc:`Не оновлюйте залишкову ємність із оцінок AMS. Використовуйте це, якщо ви віддаєте перевагу відстеженню використання Spoolman, а не оцінкам на основі відсотка AMS. Нові котушки все ще використовуватимуть оцінку AMS як початкову вагу.`,reportPartialUsage:`Повідомити про часткове використання для невдалого друку`,reportPartialUsageDesc:`Якщо друк не вдається або скасовується, повідомте приблизну кількість філаменту, використаної до цього моменту, на основі виконання шару.`},locations:{title:`Місця зберігання`,subtitle:`Керуйте полицями, шухлядами та іншими фізичними місцями для зберігання своїх котушок`,add:`Додати місцезнаходження`,addShort:`додати`,edit:`Редагувати місцезнаходження`,name:`Назва`,spools:`Котушки`,empty:`Місць зберігання ще немає. Створіть свою першу полицю або ящик.`,manage:`Розташування`,createPlaceholder:`напр. Полиця А, ящик 1`,nameRequired:`Потрібно вказати назву місця`,created:`Розташування створено`,updated:`Розташування оновлено`,deleted:`Розташування видалено`,saveFailed:`Не вдалося зберегти місцезнаходження`,deleteFailed:`Не вдалося видалити місцезнаходження`,deleteBlocked:`Видаліть усі котушки з цього місця перед видаленням`,confirmDelete:`Видалити "{{name}}"?`,confirmDeleteMessage:`Це місце буде видалено з каталогу. Котушки спочатку потрібно перемістити.`},inventory:{title:`Облік котушок`,subtitle:`Керуйте своїми котушками`,addToInventory:`Додати до обліку`,addToInventoryPending:`Додавання...`,addToInventorySuccess:`Котушку додано до обліку`,addToInventoryFailed:`Не вдалося додати котушку до обліку`,unknownSpoolTitle:`Виявлено нову котушку філаменту`,unknownSpoolMessage:`У {{location}} виявлено котушку з невідомою RFID-міткою. Додати її до обліку?`,unknownSpoolSlot:`Слот`,bulk:{selectAllVisible:`Вибрати усі видимі`,selectRow:`Вибрати рядок`,selectGroup:`Вибрати групу`,selectionCount:`Вибрано {{count}}.`,edit:`Редагувати`,printLabels:`Друк етикеток`,resetUsage:`Скинути використання`,restore:`Відновити`,archive:`Архівувати`,delete:`Видалити`,clearSelection:`Очистити вибір`,editTitle:`Масове редагування котушок`,editSubtitle:`Застосовується до вибраних котушок {{count}}. Оновлюються лише ті поля, які ви позначите.`,editHint:`Введіть значення в поле, щоб позначити його для оновлення: буде надіслано лише позначені поля. Порожнє поле не змінює котушки; очистити поле можна лише під час редагування окремої котушки.`,useCustom:`Використати «{{value}}»`,toggleField:`Перемкнути оновлення для цього поля`,changeCount:`Буде оновлено полів: {{count}}`,applyPending:`Застосування...`,applyButton:`Застосувати до котушок ({{count}})`,deleteTitle:`Видалити вибрані котушки`,archiveTitle:`Архівувати вибрані котушки`,restoreTitle:`Відновити вибрані котушки`,resetUsageTitle:`Скинути використання на вибраних котушках`,deleteMessage:`Назавжди видалити котушки {{count}}? Це неможливо скасувати.`,archiveMessage:`Архівувати котушки {{count}}? Пізніше їх можна відновити.`,restoreMessage:`Відновити заархівовані котушки {{count}}?`,resetUsageMessage:`Скинути лічильник «Всього спожито» на котушках {{count}}? Залишок ваги зберігається.`,updateSuccess:`Котушок оновлено: {{count}}`,updateFailed:`Помилка масового оновлення`,updatePartial:`Оновлено: {{ok}}; не вдалося оновити: {{failed}}`,updateAllFailed:`Не вдалося оновити жодну з вибраних котушок ({{count}}). Вибір збережено для повторної спроби.`,deleteSuccess:`Котушок видалено: {{count}}`,deleteFailed:`Не вдалося масово видалити`,deletePartial:`Видалено: {{ok}}; не вдалося видалити: {{failed}}`,deleteAllFailed:`Не вдалося видалити жодну з вибраних котушок ({{count}}). Вибір збережено для повторної спроби.`,archiveSuccess:`Котушок заархівовано: {{count}}`,archiveFailed:`Помилка масового архівування`,archivePartial:`Заархівовано: {{ok}}; не вдалося заархівувати: {{failed}}`,archiveAllFailed:`Не вдалося заархівувати жодну з вибраних котушок ({{count}}). Вибір збережено для повторної спроби.`,restoreSuccess:`Котушок відновлено: {{count}}`,restoreFailed:`Помилка масового відновлення`,restorePartial:`Відновлено: {{ok}}; не вдалося відновити: {{failed}}`,restoreAllFailed:`Не вдалося відновити жодну з вибраних котушок ({{count}}). Вибір збережено для повторної спроби.`,invalidHex:`Введіть 6 шістнадцяткових символів (RRGGBB) або 8 (RRGGBBAA). Інакше поле не застосовуватиметься.`},spoolmanMixedContentTitle:`Spoolman не може Завантажити через HTTPS — змішаний вміст заблоковано вашим браузером`,spoolmanMixedContentBody:`Bambuddy обслуговується через HTTPS (через ваш зворотний проксі), але ваш Spoolman URL усе ще звичайний HTTP. Браузери блокують змішаний вміст для безпеки, тому вбудований Spoolman UI не може відтворюватися. Щоб це працювало, Spoolman має бути доступним через HTTPS.`,spoolmanMixedContentFixReverseProxy:`Розмістіть Spoolman за тим самим зворотним проксі, що й Bambuddy (Traefik / Nginx / Caddy) з HTTPS, а потім оновіть Spoolman URL у налаштуваннях до нової адреси HTTPS.`,spoolmanMixedContentFixOpenNewTab:`Як обхідний шлях, відкрийте Spoolman у новій вкладці браузера поверх HTTP — правила змішаного вмісту застосовуються лише до вбудованих фреймів, тому окрема вкладка все ще працює.`,spoolmanOpenInNewTab:`Відкрийте Spoolman у новій вкладці`,labels:{title:`Друк етикеток на котушках`,selectedCount:`Вибрано {{count}}.`,pickSpools:`Виберіть котушки для друку етикеток:`,monochrome:`Монохромний (чорно-білий принтер)`,monochromeHint:`Прибирає зразок кольору та розширює область тексту`,searchPlaceholder:`Шукайте назву, бренд або #ID`,filterByMaterial:`матеріал:`,allMaterials:`все`,selectVisible:`Вибрати все видиме ({{count}})`,deselectVisible:`Скасувати вибір видимого`,clearAll:`Очистити все`,noSpoolsToShow:`Немає котушок для показу. Налаштуйте фільтр і повторіть спробу.`,noMatches:`Жодна котушка не відповідає поточному пошуку чи фільтру.`,printOne:`Друк етикетки для цієї котушки`,printLabels:`Друк етикеток…`,bulkTitle:`Виберіть котушки для друку етикеток серед показаних ({{count}})`,noSpoolsTitle:`Немає котушок для маркування`,error:`Не вдалося створити мітки: {{msg}}`,sortBy:{label:`Сортувати:`,id:`За ідентифікатором`,color:`За кольором`},templates:{amsHolderSmall:{label:`Тримач AMS — малий (74 × 33 мм)`,hint:`Одна етикетка на сторінці; відповідає етикетці для друку від MakerWorld моделі 752566 (AMS Filament Label Holder).`},amsHolderLarge:{label:`Тримач AMS — великий (75 × 55 мм)`,hint:`Одна етикетка на сторінці; підходить для варіанту тримача етикеток із філаментом AMS із вкладенням картону. Досить місткий для зразка, бренду, матеріалу, ідентифікатора та QR-коду.`},box40x30:{label:`Етикетка коробки (40 × 30 мм)`,hint:`Одна етикетка на сторінці; звичайний розмір рулону DK/Brother, підходить для етикеток у пакетах із філаментом та контейнерах для зберігання.`},box:{label:`Етикетка коробки (62 × 29 мм)`,hint:`Одна етикетка на сторінці; розміром для маленьких етикеток Brother PT/QL і Dymo.`},averyL7160:{label:`Avery L7160 — аркуш А4 (38,1 × 63,5 мм × 21)`,hint:`Європейський аркуш; 21 етикетка на сторінці A4.`},avery5160:{label:`Avery 5160 — аркуш US Letter (25,4 × 66,7 мм × 30)`,hint:`Аркуш американського формату; 30 етикеток на сторінці Letter.`}}},csv:{importButton:`Імпорт CSV`,exportButton:`Експорт CSV`,modalTitle:`Імпорт котушок з CSV`,selectFile:`Виберіть файл CSV або перетягніть його сюди`,dragHint:`Заголовок: material (обов’язково), brand, subtype, color_name, rgba, …`,parsing:`Читання файлу…`,previewError:`Не вдалося прочитати файл CSV.`,validCount:`{{count}} дійсний`,errorCount:`{{count}} помилка`,skippedCount:`{{count}} пропущено`,colRow:`Рядок`,colStatus:`Статус`,colColor:`Колір`,colorResolved:`Кольорове заповнення з каталогу`,colorCrossMaterial:`Колір узятий з іншого матеріалу — точної відповідності в каталозі немає`,duplicateExisting:`Котушка з таким матеріалом, брендом і кольором вже є — вона ще буде імпортована як нова котушка`,spoolmanHint:`У режимі Spoolman використовуйте вбудовані засоби імпорту й експорту Spoolman.`,importValidRows:`Імпорт {{count}} дійсних рядків`,noValidRows:`Немає дійсних рядків`,importing:`Імпорт…`,importSuccess:`Імпортовано котушок: {{count}}`,importError:`Помилка імпорту`,exportError:`Помилка експорту`},addSpool:`Додати котушку`,editSpool:`Редагувати котушку`,copySpool:`Копіювати котушку`,material:`матеріал`,selectMaterial:`Виберіть матеріал...`,subtype:`Підтип`,brand:`Бренд`,searchBrand:`Шукати бренд...`,useCustomBrand:`Використовуйте "{{brand}}"`,useCustomMaterial:`Використовуйте спеціальний матеріал: {{material}}`,suggestedOptions:`Рекомендовані`,allOptions:`Усі`,colorName:`Назва кольору`,colorNamePlaceholder:`Нефритовий білий, вогненно-червоний...`,color:`Колір`,hexColor:`Шістнадцятковий колір`,pickColor:`Вибрати індивідуальний колір`,labelWeight:`Номінальна вага філаменту`,coreWeight:`Вага порожньої котушки`,searchSpoolWeight:`Шукати вагу котушки...`,weightUsed:`Використано`,currentWeight:`Вага, що залишилася`,measuredWeight:`Виміряна вага`,spoolName:`Котушка`,costPerKg:`Вартість за кг`,storageLocation:`Місце зберігання`,storageLocationPlaceholder:`напр. Полиця А, ящик 1`,openInInventory:`Відкрити в інвентарі`,measuredWeightError:`Виміряна вага має бути між {{min}}g і {{max}}g.`,slicerFilament:`Філамент для нарізки`,slicerFilamentName:`Назва профілю слайсера`,slicerPreset:`Попереднє налаштування слайсера`,searchPresets:`Шукати профілі філаменту...`,selectedPreset:`Вибране`,noPresetsFound:`Попередніх налаштувань не знайдено`,tempOverrides:`Перевизначення температури`,note:`Примітка`,notePlaceholder:`Будь-які додаткові зауваження щодо цієї котушки...`,category:`Категорія`,categoryPlaceholder:`напр. Виробництво, прототип, клієнт А`,categoryNone:`Без категорії`,storageLocationNone:`Місцезнаходження не встановлено`,lowStockThresholdOverride:`Поріг низького запасу (ця котушка)`,lowStockThresholdOverrideHelp:`Залиште поле порожнім, щоб використовувати глобальне порогове значення ({{global}}%).`,clearRfid:`Очистити тег RFID.`,rfidCleared:`Тег RFID видалено`,archive:`Архівувати`,restore:`Відновити`,noSpools:`Ще немає котушок. Щоб почати, додайте свою першу котушку.`,noAvailableSpools:`Немає котушок. Додайте котушку до свого інвентарю або спершу скасуйте призначення іншого слота.`,kProfiles:`K-профілі`,addKProfile:`Додати K-профіль`,assignSpool:`Призначити котушку`,unassignSpool:`Скасувати призначення`,assignSuccess:`Котушку призначено, слот AMS налаштовано`,assignPendingInsert:`Котушку призначено. Слот буде налаштовано після її встановлення.`,assignFailed:`Не вдалося призначити котушку`,selectSpool:`Виберіть котушку, щоб призначити цьому слоту`,assigned:`Призначено`,assigning:`Призначення...`,searchSpools:`Пошук котушок...`,showAllSpools:`Показати всі котушки`,spoolmanSpools:`Котушки Spoolman`,allMaterials:`Усі матеріали`,filterByBrand:`Фільтрувати за брендом...`,showArchived:`Показати архівні`,quickAdd:`Швидке додавання (запас)`,quantity:`Кількість`,stock:`Запас`,configured:`Налаштовано`,spoolsCreated:`Створено котушок: {{count}}`,spoolsPartiallyCreated:`{{created}} з {{total}} котушок створено (деякі не вдалося)`,spoolCreated:`Котушку створено`,spoolUpdated:`Котушку оновлено`,spoolDeleted:`Котушку видалено`,deepLinkSpoolNotFound:`Котушку не знайдено`,deepLinkFetchFailed:`Не вдалося завантажити котушку — спробуйте ще раз`,spoolArchived:`Котушку заархівовано`,spoolRestored:`Котушку відновлено`,kProfileSaveFailed:`Не вдалося зберегти налаштування K-профілю`,syncWeightSpoolNotFound:`Котушку не знайдено — можливо, її видалено`,syncWeightSpoolmanUnreachable:`Spoolman недоступний — спробуйте пізніше`,syncWeightFailed:`Не вдалося синхронізувати вагу`,spoolmanUnreachable:`Spoolman недоступний — спробуйте пізніше`,deleteSpoolNotFound:`Котушку не знайдено — можливо, її вже видалено`,deleteFailed:`Не вдалося видалити котушку`,archiveSpoolNotFound:`Котушку не знайдено — можливо, її вже видалено`,archiveFailed:`Не вдалося заархівувати котушку`,restoreSpoolNotFound:`Котушку не знайдено — можливо, її вже видалено`,restoreFailed:`Не вдалося відновити котушку`,saveFailed:`Не вдалося зберегти зміни`,tagClearFailed:`Не вдалося очистити тег`,deleteConfirm:`Ви впевнені, що хочете видалити цю котушку? Це неможливо скасувати.`,archiveConfirm:`Ви впевнені, що хочете заархівувати цю котушку?`,advancedSettings:`Розширені налаштування`,filamentInfoTab:`Інформація про філамент`,paProfileTab:`Профіль PA`,filamentInfo:`Філамент`,additional:`Додатково`,loadingPresets:`Завантаження хмарних профілів...`,cloudConnected:`Хмара підключена`,cloudNotConnected:`Хмара не підключена (за умовчанням)`,recentColors:`Останні`,searchColors:`Пошук кольорів...`,searchResults:`Результати пошуку`,allColors:`Всі кольори`,commonColors:`Поширені кольори`,showLess:`Показувати менше`,showAll:`Показати все`,noColorsFound:`Жоден колір не відповідає вашому запиту`,noResults:`Збігів не знайдено`,extraColorsLabel:`Додаткові кольори`,extraColorsPlaceholder:`EC984C,#6CD4BC,A66EB9,D87694`,extraColorsHint:`Вставте від 2 до 8 шістнадцяткових знаків, розділених комами. Візуалізація як градієнт.`,extraColorsInvalid:`Проігнорований недійсний шістнадцятковий код: {{tokens}}`,colorEffectLabel:`Ефект`,colorEffect:{none:`Жодного`,sparkle:`Блиск`,wood:`Деревина`,marble:`Мармур`,glow:`Світіння`,matte:`Матовий`,silk:`Шовк`,galaxy:`Галактика`,rainbow:`Веселка`,metal:`метал`,translucent:`Напівпрозорий`,gradient:`Градієнт`,dualColor:`Подвійний колір`,triColor:`Три кольори`,multicolor:`Багатобарвність`},selectMaterialFirst:`Спочатку виберіть матеріал на вкладці «Інформація про філамент».`,noPrintersConfigured:`Принтери не налаштовані. Додайте принтери для використання профілів PA.`,matchingFilter:`Зіставлення`,anyBrand:`Будь-який бренд`,anyVariant:`Будь-який варіант`,autoSelect:`Автоматичний вибір`,matches:`збіги`,match:`збіг`,noMatches:`Немає збігів`,connected:`Підключено`,offline:`Не в мережі`,printerOffline:`Принтер не в мережі. Підключіться, щоб переглянути профілі калібрування.`,noKProfilesMatch:`Немає K-профілів, що відповідають вибраному філаменту.`,leftNozzle:`Ліве сопло`,rightNozzle:`Праве сопло`,profilesSelected:`вибрані профілі калібрування`,totalInventory:`Загальний запас`,totalConsumed:`Всього спожито`,byMaterial:`За матеріалом`,inPrinter:`У принтері`,lowStock:`Низький запас`,sinceTracking:`З початку відстеження`,resetConsumedCounter:`Скинути лічильник`,resetConsumedCounterTooltip:`Обнулити лічильник спожитих грамів для цієї котушки. Залишкова вага не зміниться.`,resetConsumedCounterConfirm:`Скинути лічильник спожитих грамів на 0? Майбутні роздруківки знову відстежуватимуться з нуля. Сама котушка, розрахунок її залишкової ваги та ваші налаштування не змінюються.`,resetAllConsumedCounters:`Обнулити всі лічильники`,resetAllConsumedCountersTooltip:`Обнулити лічильник спожитих грамів для кожної котушки. Залишкова вага не зміниться.`,resetAllConsumedCountersConfirm:`Скинути лічильники спожитих грамів до 0 для всіх котушок ({{count}}, включно з архівними)? Статистику «Всього спожито» буде очищено, а облік майбутніх друків почнеться з нуля. Самі котушки та їхня залишкова вага не зміняться.`,consumedCounterReset:`Скидання лічильника`,allConsumedCountersReset:`Скинуто лічильники котушок: {{count}}`,resetConsumedCounterFailed:`Не вдалося скинути лічильник`,loadedInAms:`Завантажено в AMS/Ext`,remaining:`Залишилося`,weightCheck:`Перевірка ваги`,lastWeighed:`Останнє зважування`,neverWeighed:`Ще не зважувалася`,search:`Пошук котушок...`,showing:`Показ`,to:`до`,of:`з`,show:`Показати`,spools:`котушки`,spool:`котушка`,page:`Сторінка`,noSpoolsMatch:`Результатів не знайдено`,noSpoolsMatchDesc:`Спробуйте налаштувати пошук або фільтри, щоб знайти те, що ви шукаєте.`,active:`Активний`,archived:`Архівовано`,all:`все`,used:`Використані`,new:`Нові`,clearFilters:`Очистити фільтри`,table:`Таблиця`,cards:`картки`,net:`Нетто`,groupSimilar:`Групувати`,groupedSpools:`Однакових котушок: {{count}}`,groupedRows:`рядки`,columns:`Стовпці`,configureColumns:`Налаштувати стовпці`,configureColumnsDesc:`Перетягніть, щоб змінити порядок стовпців, або використовуйте стрілки. Перемкніть видимість за допомогою значка ока.`,visible:`видно`,reset:`Скинути`,cancel:`Скасувати`,applyChanges:`Застосувати зміни`,moveUp:`Перемістити вгору`,moveDown:`Перемістити вниз`,hideColumn:`Сховати стовпець`,showColumn:`Показати стовпець`,linkToSpool:`Прив’язати до котушки`,tagLinked:`Тег пов’язано з котушкою`,tagLinkFailed:`Не вдалося зв’язати тег`,tagAlreadyLinked:`Тег уже пов’язано з іншою котушкою`,unknownTag:`Виявлено невідомий тег RFID.`,usageHistory:`Історія використання`,noUsageHistory:`Використання ще не зареєстровано`,printName:`Назва друку`,weightConsumed:`Витрачена вага`,clearHistory:`Очистити`,historyCleared:`Історію використання очищено`,fillSourceLabel:`(Інвентар)`,lowStockThresholdError:`Порогове значення має бути від 0,1 до 99,9`,assignMismatchTitle:`Невідповідність матеріалу`,assignMismatchMessage:`Вибраний матеріал котушки "{{spoolMaterial}}" не відповідає матеріалу лотка "{{trayMaterial}}" для {{location}}. Все одно призначити?`,assignMismatchConfirm:`Все одно призначити`,assignPartialMismatchMessage:`Матеріал котушки "{{spoolMaterial}}" схожий на "{{trayMaterial}}" у {{location}}, але не зовсім відповідає. Ви бажаєте продовжити?`,assignProfileMismatchMessage:`Профіль котушки «{{spoolProfile}}» не відповідає профілю лотка «{{trayProfile}}» у {{location}}. Ви бажаєте продовжити?`,assignReconfigureNote:`Слот AMS буде переналаштовано для використання профілю котушки.`,spoolmanFilamentCatalog:`Каталог філаментів Spoolman`,pickFromSpoolmanCatalog:`Вибрати з каталогу Spoolman…`,spoolmanFilamentSelected:`Філамент вибрано з каталогу Spoolman`,spoolmanFilamentUnlinked:`Посилання на каталог філаментів видалено`,noSpoolmanFilaments:`У каталозі Spoolman не знайдено філаментів`,spoolmanFilamentColorSwatch:`Колір філаменту`,spoolWeightManagedBySpoolman:`Вага порожньої котушки керується залежно від типу філаменту в Spoolman`,spoolmanCatalogLoadFailed:`Не вдалося завантажити каталог філаментів Spoolman`},timelapse:{title:`Таймлапс`,create:`Створити Timelapse`,download:`Завантажити`,delete:`Видалити`,preview:`Попередній перегляд`,frameRate:`Частота кадрів`,quality:`якість`,processing:`Обробка...`,noTimelapses:`Немає таймлапсів`},ams:{title:`AMS`,slot:`Слот`,empty:`Порожній`,emptySlot:`Порожній слот`,slotEmpty:`Порожній`,slotUnconfigured:`?`,emptySlotReset:`Філамент не призначено`,unknown:`Невідомий`,humidity:`Вологість`,temperature:`температура`,filamentType:`Тип філаменту`,filamentColor:`Колір`,remaining:`Залишилося`,history:`AMS Історія`,noHistory:`Історія недоступна`,configureSlot:`Налаштувати слот`,externalSpool:`Зовнішня котушка`,profile:`Профіль`,kFactor:`Фактор K`,fill:`Рівень заповнення`,configure:`Налаштувати`,used:`використовується`,remainingUnit:`залишилося`},printModal:{selectPrinter:`Вибрати принтер`,selectPlate:`Вибрати пластину`,filamentMapping:`Зіставлення філаментів`,useArchiveMapping:`Зіставлення`,useArchiveMappingTooltip:`Вибрати всі слоти зі зіставлення AMS, збереженого з цим записом (зі слайсера), замість добору за типом/кольором.`,clickToChangeSlot:`Натисніть, щоб змінити призначення слота`,reRead:`Перечитати`,plateN:`Пластина {{n}}`,plateFilamentsUnreadable:`Не вдалося прочитати філаменти вибраної пластини, тому їх неможливо зіставити. Зніміть вибір із цієї пластини, щоб додати решту до черги.`,totalCost:`Загальна вартість:`,slotRemainingShort:` — залишилося {{grams}} г`,printSettings:`Налаштування друку`,bedLeveling:`Вирівнювання столу`,flowCalibration:`Калібрування потоку`,vibrationCalibration:`Калібрування вібрації`,layerInspection:`Перевірка першого шару`,timelapse:`Таймлапс`,cancel:`Скасувати`,noPrintersAvailable:`Немає доступних принтерів`,printerBusy:`Принтер зайнятий`,printerOffline:`Принтер не в мережі`,sameTypeDifferentColor:`Одного типу, іншого кольору`,filamentTypeNotLoaded:`Тип філаменту не завантажено`,whenToPrint:`Коли друкувати`,asap:`Якнайшвидше`,queue:`Черга`,schedule:`За розкладом`,dateTime:`Дата й час`,invalidDateTime:`Введіть дійсну дату й час`,openCalendar:`Відкрити календар`,requireManualStart:`Потрібен ручний запуск`,requirePreviousSuccess:`Починати, лише якщо попередній друк вдався`,autoOffAfter:`Вимкнути принтер після завершення`,helpAsap:`Завдання буде додано на початок черги й розпочнеться, щойно відповідний принтер звільниться.`,helpSchedule:`Друк розпочнеться в запланований час, якщо принтер буде вільний. Якщо принтер зайнятий, завдання чекатиме, доки він звільниться.`,helpQueue:`Завдання буде додано в кінець черги.`,leftNozzle:`Л`,rightNozzle:`Р`,leftNozzleTooltip:`Ліве сопло`,rightNozzleTooltip:`Праве сопло`,filamentOverride:`Перевизначення філаменту`,filamentOverrideHint:`Необов’язково замініть філаменти для призначення на основі моделі. Планувальник зіставлятиметься з вибраними філаментами замість вихідних значень 3MF.`,originalFilament:`Оригінал`,overrideWith:`Перевизначити за допомогою`,resetToOriginal:`Скинути до оригіналу`,insufficientFilamentTitle:`Недостатньо філаменту`,waitingForAmsStatus:`Очікування статусу AMS від {{printer}}…`,insufficientFilamentMessage:`У деяких призначених котушках залишилося менше філаменту, ніж потрібно для друку:`,insufficientFilamentLine:`{{printer}} - {{slot}}: потрібно {{required}}g, залишилося {{remaining}}g`,printAnyway:`Усе одно друкувати`,forceColorMatch:`Примусовий збіг кольорів`,staggerPrinterStarts:`Запускати принтери почергово`,staggerGroupSize:`Розмір групи`,staggerInterval:`Інтервал (хв)`,staggerPreview:`Принтерів: {{printers}} → груп: {{groups}}, по {{size}}; інтервал запуску — {{interval}} хв`,staggerLastGroup:`остання група: {{count}}`,staggerTotal:`всього: {{minutes}} хв`,staggerToPrinters:`Розподілити запуск між {{count}} принтерами`,gcodeInjection:`Додати G-код автоматичного друку`},backup:{includesEncryptionKey:`Локальні резервні копії включають файл ключа шифрування MFA (DATA_DIR/.mfa_encryption_key), тому резервна копія ZIP є автономною. Вважайте ZIP конфіденційним — кожен, хто має файл, може розшифрувати секрети клієнта OIDC і секрети TOTP, що зберігаються в ньому.`,title:`Резервне копіювання та відновлення`,createBackup:`Створити резервну копію`,restoreBackup:`Відновити резервну копію`,restoreDescription:`Замінити всі дані даними з файлу резервної копії`,downloadBackup:`Завантажити резервну копію`,uploadBackup:`Вивантажити резервну копію`,lastBackup:`Остання резервна копія`,autoBackup:`Автоматичне резервне копіювання`,backupNow:`Створити резервну копію зараз`,restoreWarning:`Увага: відновлення резервної копії перезапише всі поточні дані.`,includeArchives:`Включати архіви`,includeSettings:`Включити налаштування`,includeProfiles:`Включити профілі`,backupSuccess:`Резервну копію створено успішно`,restoreSuccess:`Резервну копію успішно відновлено`,backupFailed:`Помилка резервного копіювання`,restoreFailed:`Не вдалося відновити`,restoreNote:`Віртуальний принтер буде зупинено під час відновлення`,githubBackup:`Резервне копіювання Git`,enabled:`Увімкнено`,cloudLoginRequired:`Потрібно ввійти в Bambu Cloud. Перейдіть до Профілі → Хмарні профілі, щоб увімкнути резервне копіювання до GitHub.`,cloudLoginRequiredShort:`Потрібен вхід у хмару`,githubDescription:`Автоматично синхронізуйте свої профілі з приватним репозиторієм GitHub для резервного копіювання та історії версій.`,repoIsPrivate:`Репозиторій приватний — безпечно створювати резервні копії.`,repoIsPublicWarning:`Репозиторій є ПУБЛІЧНИМ. Резервні копії Bambuddy містять облікові дані MQTT, токени Home Assistant, токени Prometheus, вашу електронну пошту Bambu Cloud і коди доступу до принтера через K-профілі. Збереження блокується, доки ви не зробите репозиторій приватним у налаштуваннях постачальника.`,repoVisibilityUnknown:`Не вдалося визначити видимість репозиторію. Bambuddy створює резервні копії лише в підтверджено приватних репозиторіях, тому збереження буде заблоковано.`,repositoryUrl:`URL репозиторію`,repoUrlPlaceholderGitHub:`https://github.com/username/repo-name`,repoUrlPlaceholderGitea:`https://gitea.example.com/username/repo-name`,repoUrlPlaceholderForgejo:`https://forgejo.example.com/username/repo-name`,repoUrlPlaceholderGitLab:`https://gitlab.com/username/repo-name`,allowInsecureHttp:`Дозволити незахищений HTTP`,allowInsecureHttpHint:`Увімкнути для саморозміщених екземплярів у приватних мережах без TLS`,personalAccessToken:`Персональний токен доступу`,tokenSaved:`(збережено)`,enterNewToken:`Введіть новий токен для оновлення`,tokenHint:`Токен із деталізованими правами та дозволом на читання й запис вмісту`,branch:`Гілка`,provider:`Постачальник Git`,providerGitHub:`GitHub`,providerGitLab:`GitLab`,providerGitea:`Gitea`,providerForgejo:`Forgejo`,manualOnly:`Тільки вручну`,hourly:`щогодини`,daily:`Щодня`,weekly:`Щотижня`,includeInBackup:`Включити в резервну копію`,kProfiles:`K-профілі`,kProfilesDescription:`Калібрування Pressure Advance (PA) від підключених принтерів`,noPrintersConnected:`Немає підключених принтерів`,printersConnected:`{{connected}}/{{total}} підключено`,cloudProfiles:`Хмарні профілі`,cloudProfilesDescription:`Попередні налаштування філаменту, принтера та процесу від Bambu Cloud і Orca Cloud`,cloudProfilesAccounts:`Підключені акаунти — Bambu Cloud: {{bambu}}, Orca Cloud: {{orca}}`,appSettings:`Налаштування програми`,appSettingsDescription:`Конфігурація Bambuddy (повна база даних)`,spoolInventory:`Облік котушок`,spoolInventoryDescription:`Котушки з філаментом, історія використання та відстеження витрат`,printArchives:`Архіви друку`,printArchivesDescription:`Метадані історії друку (без файлів gcode/3MF)`,lastBackupAt:`Остання резервна копія:`,noBackupsYet:`Резервних копій ще немає`,next:`Наступне виконання:`,startingBackup:`Початок резервного копіювання...`,test:`Тест`,enableBackup:`Увімкнути резервне копіювання`,testConnection:`Тестове підключення`,enterRepoUrl:`Введіть URL репозиторію`,enterRepoAndToken:`Введіть URL репозиторію та токен доступу`,repoRequired:`Потрібно вказати URL репозиторію`,tokenRequired:`Потрібен токен доступу`,githubBackupEnabled:`GitHub резервне копіювання ввімкнено`,tokenUpdated:`Токен оновлено`,settingsSaved:`Налаштування збережено`,failedToSave:`Не вдалося зберегти: {{message}}`,backupCompleteFiles:`Резервне копіювання завершено – файли {{count}} оновлено`,backupSkippedNoChanges:`Резервне копіювання пропущено – без змін`,backupFailed2:`Помилка резервного копіювання: {{message}}`,clearedLogs:`Очищено журнали {{count}}.`,failedToClearLogs:`Не вдалося очистити журнали: {{message}}`,history:`історія`,clear:`Очистити`,date:`Дата`,status:`Статус`,commit:`Коміт`,localBackup:`Локальна резервна копія`,localBackupDescription:`Створити повну резервну копію даних Bambuddy, включно з базою даних, архівами, вивантаженнями та всіма файлами.`,downloadBackupLabel:`Завантажити резервну копію`,completeBackupZip:`Повне резервне копіювання: база даних + усі файли (ZIP)`,download:`Завантажити`,preparingBackup:`Підготовка резервної копії...`,creatingArchive:`Створення резервного архіву... Для великих архівів це може зайняти деякий час.`,downloadingFile:`Завантаження файлу резервної копії...`,backupDownloaded:`Резервну копію успішно завантажено`,failedToCreateBackup:`Не вдалося створити резервну копію: {{message}}`,restore:`Відновити`,restoreReplacesAll:`Відновлення замінює всі дані.`,restoreReplacesAllDetail:`Вашу поточну базу даних і файли буде повністю замінено. Після відновлення потрібен перезапуск.`,restoreConfirmTitle:`Відновити резервну копію`,restoreConfirmMessage:`Ви впевнені, що бажаєте відновити з "{{filename}}"? Це повністю замінить вашу поточну базу даних і всі файли. Після відновлення програму потрібно буде перезапустити.`,restoreConfirmButton:`Відновити резервну копію`,uploadingFile:`Вивантаження файлу резервної копії...`,backupRestoredRestart:`Резервну копію відновлено. Перезапустіть Bambuddy.`,failedToRestore:`Не вдалося відновити резервну копію. Будь ласка, перевірте формат файлу.`,reloadNow:`Перезавантажити зараз`,creatingBackup:`Створення резервної копії`,restoringBackup:`Відновлення з резервної копії`,preparing:`Підготовка...`,processing:`Обробка...`,doNotClosePage:`Будь ласка, не закривайте цю сторінку та не виходьте з неї. Для великих резервних копій ця операція може зайняти кілька хвилин.`,restoring:`Відновлення...`,restoreComplete:`Відновлення завершено`,restoreFailed2:`Не вдалося відновити`,importSettings:`Імпорт налаштувань із файлу резервної копії`,pleaseWaitRestoring:`Зачекайте, поки ваші дані відновляться`,selectBackupFile:`Натисніть, щоб вибрати файл резервної копії (.json або .zip)`,duplicateHandling:`Як працює обробка дублікатів:`,matchPrinters:`Принтери`,matchPrintersBy:`відповідає серійному номеру`,matchSmartPlugs:`Розумні розетки`,matchSmartPlugsBy:`зіставляються за IP-адресою`,matchNotificationProviders:`Постачальники сповіщень`,matchNotificationProvidersBy:`відповідність за назвою`,matchFilaments:`філаменти`,matchFilamentsBy:`відповідність за назвою + типом + брендом`,matchArchives:`Архіви`,matchArchivesBy:`відповідає хешу вмісту (завжди пропускається)`,matchPendingUploads:`Вивантаження, що очікують`,matchPendingUploadsBy:`зіставляються за назвою файлу`,matchSettingsTemplates:`Налаштування та шаблони`,matchSettingsTemplatesBy:`завжди перезаписується`,replaceExisting:`Замінити існуючі дані`,keepExisting:`Зберегти наявні дані`,overwriteDescription:`Замінити наявні елементи даними з резервної копії`,keepDescription:`Відновлюйте лише елементи, яких ще не існує`,overwriteCaution:`Увага:`,overwriteWarning:`Перезапис замінить ваші поточні конфігурації даними з резервної копії. Коди доступу до принтера ніколи не перезаписуються з міркувань безпеки.`,cancel:`Скасувати`,processingBackup:`Обробка файлу резервної копії...`,itemsRestored:`Елементів відновлено`,itemsSkipped:`Пропущено елементів`,restored:`Відновлено`,skippedAlreadyExist:`Пропущено (вже існує)`,filesCategory:`Файли (3MF, мініатюри тощо)`,andMore:`…і ще {{count}}`,newApiKeysGenerated:`Створено нові API ключі`,keysShownOnce:`Ці ключі відображаються лише один раз. Скопіюйте їх зараз!`,copy:`Копіювати`,noDataFound:`У файлі резервної копії не знайдено даних для відновлення.`,close:`Закрити`,scheduledBackup:`Резервне копіювання за розкладом`,scheduledBackupDescription:`Автоматично створюйте резервні знімки за розкладом. Вихідний каталог можна підключити до NAS або зовнішнього накопичувача.`,frequency:`Частота`,backupTime:`час`,retention:`Термін зберігання`,retentionDescription:`Кількість резервних копій, які потрібно зберегти`,outputPath:`Вихідний шлях`,outputPathPlaceholder:`За замовчуванням: {{path}}`,outputPathDescription:`Залиште порожнім для розташування за умовчанням`,runNow:`Запустити зараз`,backupFiles:`Файли резервних копій`,noScheduledBackups:`Резервних копій ще немає`,deleteBackup:`Видалити`,deleteBackupConfirm:`Видалити цей файл резервної копії?`,backupRunning:`Виконується резервне копіювання...`,scheduledBackupComplete:`Резервне копіювання успішно завершено`,scheduledBackupFailed:`Помилка резервного копіювання`,nextBackup:`Наступна резервна копія`,backupSize:`Розмір`,localTimeHint:`Місцевий час ({{tz}})`,defaultPathLabel:`За замовчуванням:`,pathCheck:{title:`Bambuddy не може писати в цей каталог`,howToFix:`Як виправити:`,sandboxed:`Служба Bambuddy не може писати в {{path}}. Його модуль systemd працює з ProtectSystem=strict, що робить кожен каталог за межами каталогів встановлення, даних і журналу доступними лише для читання для служби — навіть той, у який ви можете писати з власної оболонки.`,read_only:`{{path}} знаходиться у файловій системі лише для читання.`,permission_denied:`Bambuddy не має права записувати в {{path}}. Перевірте власника каталогу та дозволи.`,no_space:`У файловій системі, де розташовано {{path}}, закінчилося місце.`,not_a_directory:`{{path}} існує, але не є каталогом.`,missing:`{{path}} не існує і не може бути створений.`,error:`Bambuddy не може писати в {{path}}.`,ephemeralTitle:`Ці резервні копії не збережуться після перезапуску контейнера`,container_ephemeral:`{{path}} розташовано всередині контейнера Bambuddy, а не на хості. Резервні копії в цьому каталозі буде втрачено після повторного створення контейнера. Змонтуйте каталог із хоста:`},categories:{settings:`Налаштування`,notification_providers:`Постачальники сповіщень`,notification_templates:`Шаблони сповіщень`,smart_plugs:`Розумні розетки`,printers:`Принтери`,filaments:`філаменти`,maintenance_types:`Види технічного обслуговування`,archives:`Архіви`,projects:`Проєкти`,pending_uploads:`Вивантаження, що очікують`,external_links:`Зовнішні посилання`,api_keys:`Ключі API`}},tags:{title:`Теги`,addTag:`Додати тег`,editTag:`Редагувати тег`,deleteTag:`Видалити тег`,tagName:`Назва тегу`,tagColor:`Колір мітки`,noTags:`Без тегів`,deleteConfirm:`Ви впевнені, що бажаєте видалити цей тег?`,manageTags:`Керування тегами`},uploadModal:{title:`Вивантажити файли 3MF`,dragDrop:`Перетягніть файли .3mf сюди`,or:`або`,browseFiles:`Огляд файлів`,extractionInfo:`Модель принтера буде автоматично витягнуто з метаданих файлу 3MF.`,uploaded:`вивантажено`,failed:`не вдалося`,uploading:`Вивантаження...`,upload:`Вивантажити`,uploadFailed:`Не вдалося вивантажити`},editArchive:{title:`Редагувати архів`,name:`Назва`,namePlaceholder:`Друкування імені`,printer:`Принтер`,noPrinter:`Немає принтера`,project:`Проєкт`,noProject:`Жодного проєкту`,itemsPrinted:`Надруковано об’єктів`,itemsPrintedHelp:`Кількість елементів, виготовлених у цьому завданні друку`,notes:`Примітки`,notesPlaceholder:`Додайте примітки щодо цього друку...`,externalLink:`Зовнішнє посилання`,externalLinkPlaceholder:`https://printables.com/model/...`,externalLinkHelp:`Посилання на Printables, Thingiverse або інше джерело`,tags:`Теги`,tagsPlaceholder:`Додати теги...`,addMoreTags:`Додати більше тегів...`,matchingTags:`Відповідає "{{query}}"`,existingTags:`Існуючі теги`,clickToAdd:`(натисніть, щоб додати)`,status:`Статус`,failureReason:`Причина невдачі`,selectReason:`Виберіть причину...`,photos:`Фотографії надрукованих результатів`,photosHelp:`Натисніть +, щоб додати фотографії результату друку`,printResult:`Роздрукувати результат`,saving:`Збереження...`,failureReasons:{adhesionFailure:`Порушення адгезії`,spaghettiDetached:`Спагетті / Відр`,layerShift:`Зсув шару`,cloggedNozzle:`Засмічене сопло`,filamentRunout:`Биття філаменту`,warping:`Викривлення`,stringing:`Нанизування`,underExtrusion:`Підвидавлювання`,powerFailure:`Збій живлення`,userCancelled:`Користувач скасовано`,other:`інше`},statuses:{completed:`Виконано`,failed:`Не вдалося`,aborted:`Скасовано`,printing:`Друк`}},kProfiles:{title:`K-профілі`,noPrintersConfigured:`Принтери не налаштовані`,addPrinterInSettings:`Додайте принтер у налаштуваннях, щоб керувати K-профілями`,noActivePrinters:`Немає активних принтерів`,enablePrinterConnection:`Увімкніть підключення до принтера, щоб переглянути його K-профілі`,loadingProfiles:`Завантаження K-профілів...`,printerOffline:`Принтер не в мережі`,printerOfflineDesc:`Вибраний принтер не підключено. Увімкніть його, щоб переглянути K-профілі.`,noMatchingProfiles:`Немає відповідних профілів`,noMatchingProfilesDesc:`Немає профілів, які відповідають вашим критеріям пошуку`,noKProfiles:`Без K-профілів`,noKProfilesDesc:`Не знайдено профілів підвищення тиску для сопла {{diameter}} мм`,createFirstProfile:`Створити перший профіль`,printer:`Принтер`,nozzle:`Сопло`,refresh:`Оновити`,addProfile:`Додати профіль`,export:`Експорт`,import:`Імпорт`,select:`Вибрати`,selectAll:`Вибрати усі`,delete:`Видалити`,searchPlaceholder:`Пошук за назвою або філаментом...`,allExtruders:`Всі екструдери`,leftOnly:`Тільки зліва`,rightOnly:`Тільки право`,allFlow:`Весь потік`,hfOnly:`Тільки HF`,sOnly:`Тільки S`,sortName:`Сортувати за назвою`,sortKValue:`Сортувати: К-значення`,sortFilament:`Сорт: філамент`,leftExtruder:`Лівий екструдер`,rightExtruder:`Правий екструдер`,modal:{addTitle:`Додати K-профіль`,editTitle:`Редагувати K-профіль`,profileName:`Назва профілю`,profileNamePlaceholder:`Мій профіль PLA.`,kValue:`К-значення`,kValuePlaceholder:`0,020`,kValueHelp:`Типовий діапазон: 0,01–0,06 для PLA, 0,02–0,10 для PETG`,filament:`Філамент`,selectFilament:`Виберіть філамент...`,source:{local:`Імпортовані`,orcaCloud:`Orca Cloud`,bambuCloud:`Bambu Cloud`,builtin:`Вбудований`},noFilamentsHelp:`Немає доступних філаментів. Увійдіть у Bambu Cloud або імпортуйте пресети в розділі Профілі → Локальні профілі.`,searchFilaments:`Пошук філаментів...`,noFilamentMatches:`Немає філаментів, що відповідають запиту`,flowType:`Тип потоку`,highFlow:`Сопло з високим потоком`,standard:`Стандартний`,nozzleSize:`Розмір сопла`,extruder:`Екструдер`,extruders:`Екструдери`,left:`Ліворуч`,right:`правильно`,notes:`Примітки (зберігаються локально)`,notesPlaceholder:`Додайте примітки щодо цього профілю...`,notesHelp:`Примітки зберігаються в Bambuddy, а не на принтері`,syncing:`Синхронізація з принтером...`,savingExtruder:`Збереження в екструдер {{current}}/{{total}}...`,pleaseWait:`Будь ласка, зачекайте`},deleteConfirm:{title:`Видалити профіль`,cannotUndo:`Це неможливо скасувати`,message:`Ви впевнені, що хочете видалити "{{name}}" із принтера?`},bulkDelete:{title:`Видалити профілі`,cannotUndo:`Це неможливо скасувати`,message:`Ви впевнені, що бажаєте видалити {{count}} вибрані профілі з принтера?`},toast:{profileSaved:`K-профіль збережено`,profilesSaved:`K-профіль збережено в екструдери {{count}}.`,selectAtLeastOneExtruder:`Виберіть принаймні один екструдер`,selectFilament:`Спочатку виберіть філамент`,filamentNotResolvable:`Немає ідентифікатора філаменту Bambu для {{name}} — принтер не зможе зберегти профіль`,profileDeleted:`K-профіль видалено`,profilesDeleted:`Видалені профілі {{count}}.`,exportedProfiles:`Експортовані профілі {{count}}.`,importedProfiles:`Імпортовано {{count}} з {{total}} профілів`,noProfilesToExport:`Немає профілів для експорту`,invalidFileFormat:`Недійсний формат файлу`,failedToParseImport:`Не вдалося проаналізувати імпортований файл`,failedToSaveBatch:`Не вдалося зберегти K-профілі`,noteSaved:`Нотатку збережено`,failedToSaveNote:`Не вдалося зберегти нотатку`},permission:{noRead:`Ви не маєте дозволу оновлювати профілі`,noCreate:`Ви не маєте дозволу додавати профілі`,noUpdate:`Ви не маєте дозволу на оновлення K-профілів`,noDelete:`Ви не маєте дозволу на видалення K-профілів`,noExport:`Ви не маєте дозволу на експорт профілів`,noImport:`Ви не маєте дозволу на імпорт профілів`}},virtualPrinter:{title:`Віртуальний принтер`,running:`Працює`,stopped:`Зупинено`,description:{default:`Увімкніть віртуальний принтер, який відображатиметься в Bambu Studio та OrcaSlicer. Надіслані на нього файли буде одразу заархівовано без друку.`,proxy:`Увімкніть проксі, який передає трафік слайсера на реальний принтер і дає змогу друкувати віддалено через будь-яку мережу.`},enable:{title:`Увімкнути віртуальний принтер`,visibleInSlicer:`Відображається як "Bambuddy" у виявленні слайсера`,proxyingTo:`Проксування до {{name}}`,notActive:`Неактивний`},model:{title:`Модель принтера`,description:`Виберіть модель принтера для емуляції.`,restartWarning:`Зміна моделі перезапустить віртуальний принтер`},accessCode:{title:`Код доступу`,isSet:`Код доступу встановлено`,notSet:`Немає встановленого коду доступу – потрібно для ввімкнення`,placeholder:`Введіть 8-символьний код`,placeholderChange:`Введіть новий код для зміни`,hint:`Має бути рівно 8 символів. Використовується слайсерами для автентифікації.`,charCount:`({{count}}/8)`,inheritedFromTarget:`Успадковано від цільового принтера`,derivedFromTargetHint:`Використовує код доступу цільового принтера. Міст пересилає автентифікацію слайсера на справжній принтер, тому коди мають збігатися — відредагуйте код доступу принтера, щоб змінити це значення.`,reveal:`Показати код доступу`,hide:`Приховати код доступу`},targetPrinter:{title:`Цільовий принтер`,configured:`Ціль проксі налаштовано`,notConfigured:`Цільовий принтер не вибрано – потрібен для режиму проксі`,placeholder:`Виберіть принтер...`,hint:`Виберіть принтер, на який проксі передаватиме трафік слайсера. Принтер має працювати в режимі LAN.`,noPrinters:`Принтери не налаштовані. Щоб використовувати режим проксі, спочатку додайте принтер.`},remoteInterface:{title:`Перевизначення мережевого інтерфейсу`,configured:`Перевизначення інтерфейсу активне`,optional:`Необов’язково – використовуйте, якщо автоматичне визначення IP є неправильним (наприклад, кілька мережевих карток, Docker, VPN)`,placeholder:`Автоматичне визначення (за замовчуванням)...`,hint:`Заміна адреси IP, яка оголошується через SSDP і використовується в сертифікаті TLS. Корисно, коли Bambuddy має кілька мережевих інтерфейсів.`},mode:{title:`Режим`,archive:`Архів`,archiveDesc:`Одразу архівувати файли`,review:`Перевірка`,reviewDesc:`Перевіряти перед архівуванням`,queue:`Черга`,queueDesc:`Архівувати та додати в чергу`,proxy:`Проксі`,proxyDesc:`Пересилати на фізичний принтер`},autoDispatch:{title:`Автоматичний запуск`,description:`Автоматично запускати завдання після додавання до черги. Якщо вимкнено, завдання чекатимуть ручного запуску.`},queueForceColorMatch:{title:`Примусовий збіг кольорів`,description:`Не надсилати завдання на принтер без філаменту точного типу й кольору. Типово вимкнено: без цього черга зіставляє лише модель і може вибрати принтер із філаментом іншого кольору.`},saveAmsMapping:{title:`Зберігати зіставлення AMS`,description:`Зберігати в записі вибір слота AMS, зроблений самим слайсером (з MQTT-команди project_file), щоб пізніший повторний друк використав ту саму фізичну котушку замість повторного визначення за типом/кольором файлу. Типово вимкнено.`},gcodeInjection:{title:`Вставлення G-коду`,description:`Застосовувати до завдань цього віртуального принтера фрагменти G-коду, налаштовані для кожної моделі. Типово вимкнено.`},tailscaleDisabled:{title:`Інтеграція з Tailscale`,description:`Увімкніть, щоб позначити цей віртуальний принтер як доступний через Tailscale. Буде показано Tailscale-адресу хоста, яку потрібно ввести в слайсері. Імпорт сертифіката ЦС залишається обов’язковим; цей перемикач не впливає на сертифікати.`},setupRequired:{title:`Потрібне налаштування`,description:`Для роботи функції віртуального принтера потрібна додаткова конфігурація системи. Це включає переадресацію портів, правила брандмауера та параметри, що стосуються платформи.`,readGuide:`Перед увімкненням прочитайте посібник із налаштування`},archiveNameSource:{title:`Джерело назви архіву`,description:`Виберіть, як називати нові архіви, що надходять через віртуальний принтер. «Метадані» використовують вбудоване слайсером поле Title з 3MF (типовий варіант). «Назва файлу» використовує назву, яку Bambu Studio надіслала через FTP. За наявності поля Title Bambu Studio замінює ним назву, введену у вікні «Надіслати на принтер», тому обидва режими часто дають однаковий результат.`,metadata:`Метадані`,filename:`Назва файлу`},caCert:{title:`Сертифікат слайсера`,description:`Віртуальні принтери використовують сертифікат TLS, підписаний ЦС Bambuddy. Імпортуйте цей сертифікат ЦС у довірче сховище вашого слайсера, щоб він прийняв з’єднання — не потрібно копіювати його з командного рядка.`,copy:`Копіювати`,copied:`Скопійовано`,download:`Завантажити`,fingerprint:`SHA-256`},howItWorks:{title:`Як це працює`,step1:`У тій самій локальній мережі віртуальні принтери автоматично з’являються в слайсері (Bambu Studio або OrcaSlicer). З інших мереж додайте їх вручну за IP-адресою та кодом доступу.`,step2:`У режимах архівування, перевірки та черги натисніть «Надіслати» у слайсері, щоб вивантажити файли 3MF до Bambuddy. Слайсер покаже повідомлення про успішний друк, але файл буде лише збережено, а не надруковано.`,step3:`У режимі проксі-сервера віртуальний принтер передає весь трафік на справжній принтер — друк починається негайно, ніби підключений безпосередньо.`},status:{title:`Деталі статусу`,printerName:`Назва принтера`,model:`Модель`,serialNumber:`Серійний номер`,mode:`Режим`,pendingFiles:`Файли, що очікують на розгляд`,targetPrinter:`Цільовий принтер`,ftpPort:`Порт FTP`,mqttPort:`Порт MQTT`,ftpConnections:`Підключення FTP`,mqttConnections:`Підключення MQTT`},toast:{updated:`Налаштування віртуального принтера оновлено`,failedToUpdate:`Не вдалося оновити налаштування`,copyFailed:`Не вдалося скопіювати — спробуйте вибрати текст вручну`,accessCodeRequired:`Спочатку встановіть код доступу`,targetPrinterRequired:`Спочатку виберіть цільовий принтер`,bindIpRequired:`Спочатку встановіть прив’язку IP.`,accessCodeEmpty:`Код доступу не може бути порожнім`,accessCodeLength:`Код доступу має містити рівно 8 символів`,targetCodeChangedRebind:`Код доступу тепер відповідає новому цільовому принтеру. Повторно додайте цей пристрій у свій слайсер, щоб отримати новий код.`,created:`Створено віртуальний принтер`,failedToCreate:`Не вдалося створити віртуальний принтер`,deleted:`Віртуальний принтер видалено`,failedToDelete:`Не вдалося видалити віртуальний принтер`},list:{title:`Віртуальні принтери`,add:`додати`,addFirst:`Додати віртуальний принтер`,empty:`Віртуальні принтери не налаштовані. Додайте один, щоб почати.`},bindIp:{title:`Інтерфейс прив’язки`,placeholder:`Виберіть інтерфейс...`,hint:`Мережевий інтерфейс, до якого прив’язуватиметься цей віртуальний принтер. Для кожного принтера він має бути унікальним.`},proxy:{accessCodeHint:`У режимі проксі використовуйте код доступу цільового принтера в слайсері. З’єднання прозоро пересилається на справжній принтер.`},addDialog:{title:`Додати віртуальний принтер`,name:`Назва`,hint:`Ви можете налаштувати код доступу, цільовий принтер та інші параметри після створення.`,create:`Створити`},deleteConfirm:{title:`Видалити віртуальний принтер`,message:`Ви впевнені, що хочете видалити «{{name}}»? Усі служби цього принтера буде зупинено.`}},modelViewer:{openInSlicer:`Відкрити у слайсері`,tabs:{model:`3D-модель`,gcode:`Попередній перегляд G-коду`},notAvailable:`недоступно`,notSliced:`не нарізано`,plates:`Пластини`,allPlates:`Усі пластини`,plateNumber:`Пластина {{number}}`,plateCount:`Пластин: {{count}}`,plateCount_other:`Пластин: {{count}}`,objectCount:`Об’єктів: {{count}}`,objectCount_other:`Об’єктів: {{count}}`,filamentCount:`Філаментів: {{count}}`,filamentCount_other:`Філаментів: {{count}}`,eta:`ETA {{minutes}} хв`,noPreview:`Попередній перегляд цього файлу недоступний`,pagination:{pageOf:`Сторінка {{current}} з {{total}}`,prev:`Назад`,next:`Далі`},errors:{failedToLoad:`Не вдалося завантажити файл`,noMeshes:`У файлі 3MF не знайдено жодної сітки`,unsupportedFormat:`Непідтримуваний формат файлу`}},maintenanceDescriptions:{lubricateCarbonRods:`Нанесіть мастило на карбонові стрижні для плавного руху`,lubricateRails:`Нанесіть мастило на лінійні рейки для плавного руху`,cleanNozzle:`Очистіть нагрівач і сопло, щоб запобігти засміченню`,checkBelts:`Перевірте натяг ременя для точного друку`,cleanBuildPlate:`Очистіть будівельну пластину для кращого зчеплення`,checkExtruder:`Перевірте шестерні екструдера на знос`,checkCooling:`Переконайтеся, що вентилятори охолодження працюють належним чином`,generalInspection:`Загальний огляд принтера`,cleanCarbonRods:`Очистіть карбонові стрижні, щоб зменшити тертя`,lubricateSteelRods:`Нанесіть мастило на сталеві стрижні для плавного руху`,cleanSteelRods:`Очистіть сталеві стрижні, щоб зменшити тертя`,cleanLinearRails:`Протріть лінійні рейки, щоб видалити пил і сміття`,checkPtfeTube:`Перевірте трубку PTFE на знос або пошкодження`,replaceHepaFilter:`Замініть фільтр HEPA для забезпечення якості повітря`,replaceCarbonFilter:`Замініть фільтр з активованим вугіллям`,lubricateLeftNozzleRail:`Змастіть ліву рейку сопла (серія H2)`},smartPlugs:{offline:`Не в мережі`,admin:`Адміністрування`,openPlugAdminPage:`Відкрити сторінку адміністратора розетки`,deleteSmartPlug:`Видалити розумну розетку`,turnOnSmartPlug:`Увімкнути розумну розетку`,turnOffSmartPlug:`Вимкнути розумну розетку`,turnOn:`Увімкнути`,turnOff:`Вимкнути`,addSmartPlug:{scanningNetwork:`Сканування мережі...`,chooseEntity:`Виберіть сутність…`,connectionFailed:`Помилка підключення`,searchEntities:`Пошук сутностей...`,searchPowerSensors:`Пошук датчиків потужності...`,searchEnergySensors:`Пошук датчиків енергії...`,placeholders:{plugName:`Розетка у вітальні`,mqttStateOnValue:`ON, true, 1`,mqttSameAsPower:`Та сама тема, що й для потужності, або інша`}},linkedTo:`Пов’язано з:`,monitorOnly:`Лише моніторинг`,alerts:`Оповіщення`,scheduleOn:`Увімкнення: {{time}}`,scheduleOff:`Вимкнення: {{time}}`,on:`Увімкнено`,off:`Вимкнено`,power:`Потужність`,kwhToday:`кВт·год сьогодні`,settings:`Налаштування`,automationSettings:`Налаштування автоматизації`,showInSwitchbar:`Показати на панелі перемикачів`,quickAccessSidebar:`Швидкий доступ із бічної панелі`,enabled:`Увімкнено`,enableAutomation:`Увімкнути автоматизацію для цієї розетки`,autoOn:`Автоматичне ввімкнення`,autoOnDescription:`Увімкнути на початку друку`,autoOff:`Автоматичне вимкнення`,autoOffDescription:`Вимкнути після завершення друку (одноразово)`,autoOffPersistent:`Залишити ввімкненим`,autoOffPersistentDescription:`Залишати ввімкненою між друками, а не лише після одного завдання`,controlsPrinterPower:`Живить принтер`,controlsPrinterPowerDescription:`Вимкніть цей параметр, якщо розетка живить лише аксесуар — наприклад, вентилятор фільтра або освітлення. Інакше вимкнення розетки позначатиме принтер як недоступний.`,autoOffAfterDrying:`Автоматичне вимкнення після сушіння`,autoOffAfterDryingDescription:`Вимкнути після завершення сушіння AMS`,delayAfterDryingMinutes:`Затримка після сушіння (хв)`,turnOffDelayMode:`Режим затримки вимкнення`,time:`Час`,temp:`Температура`,delayMinutes:`Затримка (хвилин)`,tempThreshold:`Температурний поріг (°C)`,tempThresholdDescription:`Вимикається, коли сопло охолоне нижче цієї температури`,edit:`Редагувати`,deleteConfirm:`Ви впевнені, що хочете видалити "{{name}}"? Це неможливо скасувати.`,turnOnConfirm:`Ви впевнені, що бажаєте ввімкнути "{{name}}"?`,turnOffConfirm:`Ви впевнені, що бажаєте вимкнути "{{name}}"? Це призведе до відключення живлення підключеного пристрою.`,failedToTurn:`Не вдалося змінити стан «{{name}}» ({{action}})`,unknown:`Невідомий`,addTitle:`Додати розумну розетку`,editTitle:`Редагувати розумну розетку`,stopScanning:`Зупинити сканування`,discoverTasmota:`Виявити пристрої Tasmota`,foundDevices:`Знайдено {{count}} пристроїв - натисніть, щоб вибрати:`,noDevicesFound:`У вашій мережі не знайдено пристроїв Tasmota.`,haNotConfigured:`Home Assistant не налаштовано. Налаштуйте його в`,haSettingsPath:`Налаштування → Мережа → Home Assistant`,selectEntity:`Вибрати сутність *`,ipAddress:`IP Адреса *`,nameLabel:`Назва *`,username:`Ім’я користувача`,password:`Пароль`,authHint:`Залиште поле пустим, якщо ваш пристрій Tasmota не вимагає автентифікації`,linkToPrinter:`Прив’язати до принтера`,noPrinter:`Без принтера (лише ручне керування)`,linkingDescription:`Прив’язування дає змогу автоматично вмикати й вимикати розетку на початку та після завершення друку`,powerAlerts:`Сповіщення про живлення`,alertAbove:`Сповіщати, якщо вище (Вт)`,alertBelow:`Сповіщати, якщо нижче (Вт)`,alertDescription:`Сповіщати, коли споживана потужність перетинає ці пороги. Залиште відповідне поле порожнім, щоб вимкнути сповіщення для цього напрямку.`,dailySchedule:`Щоденний розклад`,turnOnAt:`Увімкнути о`,turnOffAt:`Вимкнути о`,scheduleDescription:`Щодня автоматично вмикати й вимикати розетку в зазначений час. Залиште поле порожнім, щоб пропустити відповідну дію.`,showOnPrinterCard:`Показати на картці принтера`,displayOnPrinterCard:`Показувати кнопку на картці принтера`,connectedResult:`Підключено!`,deviceLabel:`Пристрій: {{name}} - `,stateLabel:`Стан: {{state}}`,test:`Тест`,delete:`Видалити`,save:`Зберегти`,add:`Додати`,cancel:`Скасувати`,failedToStartScan:`Не вдалося почати сканування`,nameRequired:`Необхідно вказати ім’я`,entityRequired:`Сутність необхідна для розеток Home Assistant.`,mqttTopicRequired:`Для моніторингу потужності, енергії або стану потрібно налаштувати принаймні одну тему MQTT`,loadingEntities:`Завантаження об’єктів...`,loading:`Завантаження...`,failedToLoadEntities:`Не вдалося завантажити сутності: {{error}}`,noEntitiesMatching:`Не знайдено об’єктів, що відповідають "{{search}}"`,noEntitiesAvailable:`Немає доступних сутностей`,searchingEntities:`Пошук у всіх об’єктах ({{count}} знайдено)`,showingEntities:`Показано сутності switch, light та input_boolean (доступно: {{count}})`,energyMonitoringOptional:`Моніторинг енергії (необов’язково)`,energyMonitoringHint:`Знайдіть і виберіть датчики, що надають дані про потужність або споживання енергії.`,powerSensorW:`Датчик потужності (Вт)`,energyTodayKwh:`Споживання за сьогодні (кВт·год)`,totalEnergyKwh:`Загальне споживання енергії (кВт·год)`,noMatchingSensors:`Немає відповідних датчиків`,none:`Жодного`,mqttNotConfigured:`MQTT-брокер не налаштований. Укажіть адресу брокера в розділі`,mqttSettingsPath:`Налаштування → Мережа → Публікація MQTT`,mqttNotConfiguredSuffix:`(вмикати публікацію не потрібно — достатньо вказати параметри брокера).`,mqttMonitorOnlyDescription:`MQTT-розетки отримують дані про потужність і споживання енергії через підписку MQTT. Керування ввімкненням і вимкненням недоступне — використовуйте MQTT-брокер або систему домашньої автоматизації.`,powerMonitoring:`Моніторинг потужності`,energyMonitoring:`Моніторинг споживання енергії`,stateMonitoring:`Моніторинг стану`,optional:`необов’язково`,topic:`Тема`,jsonPath:`Шлях JSON`,multiplier:`Множник`,onValue:`Значення «увімкнено»`,mqttPowerHint:`Шлях JSON витягує значення з корисного навантаження JSON (наприклад, "power_l1"). Залиште поле порожнім, якщо тема публікує безпосередньо числові значення. Для перетворення mW→W використовуйте множник 0.001, а для kW→W — 1000.`,mqttEnergyHint:`Шлях JSON витягує значення з корисного навантаження JSON. Залиште поле порожнім для безпосередньо переданих значень. Для перетворення Wh→kWh використовуйте множник 0.001, а для MWh→kWh — 1000.`,mqttStateHint:`Шлях JSON витягує значення з корисного навантаження JSON. Залиште поле порожнім для безпосередньо переданих значень. -Значення «увімкнено»: точний рядок, що означає стан «увімкнено». Залиште поле порожнім для автоматичного визначення (ON, true, 1).`,restControl:`Керування`,restOnUrl:`Увімкнути URL`,restOffUrl:`Вимкнути URL`,restOnBody:`Тіло запиту ввімкнення`,restOffBody:`Тіло запиту вимкнення`,restMethod:`Метод HTTP`,restHeaders:`Спеціальні заголовки (JSON)`,restStatusUrl:`URL стану`,restStatusPath:`Шлях JSON до стану`,restStatusOnValue:`Значення «увімкнено»`,restPowerUrl:`URL даних про потужність`,restPowerPath:`Шлях JSON до потужності`,restPowerMultiplier:`Множник потужності`,restEnergyUrl:`URL даних про енергію`,restEnergyPath:`Шлях JSON до споживання за сьогодні`,restEnergyTotalPath:`Шлях JSON до загального споживання`,restEnergyTotalMultiplier:`Множник загального споживання`,restEnergyTotalPathHint:`наприклад, aenergy.total`,restEnergyTotalHint:`Багато розеток, зокрема всі моделі Shelly, повідомляють лише загальний лічильник споживання, який ніколи не скидається. Його слід указувати саме тут, а не в полі вище: якщо трактувати це значення як споживання за сьогодні, воно не скинеться опівночі, а показники «Учора» та «Усього» залишатимуться порожніми. Bambuddy сам обчислює показники за сьогодні й учора на основі цього лічильника; для їх появи потрібні один-два дні даних. Shelly передає значення у ват-годинах, тому використовуйте множник 0.001.`,restEnergyMultiplier:`Множник енергії`,restUrlRequired:`Для REST-розетки потрібно вказати принаймні один URL — для ввімкнення або вимкнення.`,restHeadersHint:`наприклад, {"Authorization": "Bearer your-token"}`,restBodyHint:`напр. ON, {"state": "on"}`,restStatusHint:`URL для опитування поточного стану`,restPathHint:`наприклад, state або data.power.status`,restPowerUrlHint:`Окремий URL для даних про потужність; якщо поле порожнє, використовується URL стану`,restEnergyUrlHint:`Окремий URL для даних про енергію; якщо поле порожнє, використовується URL стану`,restEnergyHint:`Для кожного значення можна використовувати окремий URL або URL стану як резервний. Для перетворення одиниць використовуйте множники, наприклад 0.001 для перетворення Wh у kWh.`,testConnection:`Тестове підключення`,connectionSuccess:`Підключення успішне`,noSwitchesInSwitchbar:`На панелі перемикачів немає розеток`,enableSwitchbarHint:`Увімкніть «Показувати на панелі перемикачів» у розділі «Налаштування → Розумні розетки».`},notifications:{providerTypes:{callmebot:`CallMeBot/WhatsApp`,ntfy:`ntfy`,pushover:`Pushover`,telegram:`Telegram`,email:`Електронна пошта`,discord:`Discord`,webhook:`Webhook`,homeassistant:`Home Assistant`,bark:`Bark`},providerDescriptions:{email:`Сповіщення електронною поштою SMTP`,telegram:`Сповіщення через бота Telegram.`,discord:`Надіслати на канал Discord через webhook`,ntfy:`Безкоштовні push-сповіщення з можливістю самостійного розгортання`,pushover:`Прості та надійні push-повідомлення`,callmebot:`Безкоштовні сповіщення WhatsApp через CallMeBot`,webhook:`Універсальний HTTP POST-запит на будь-який URL`,homeassistant:`Постійні сповіщення на інформаційній панелі Home Assistant.`,bark:`Push-сповіщення iOS через Bark із можливістю самостійного розгортання`},lastSuccess:`Останнє успішне надсилання: {{date}}`,error:`Помилка`,printer:`Принтер:`,allPrinters:`Всі принтери`,sendTestNotification:`Надіслати тестове сповіщення`,eventSettings:`Налаштування події`,enabled:`Увімкнено`,sendFromProvider:`Надсилати сповіщення від цього постачальника`,printEvents:`Події друку`,printerStatus:`Стан принтера`,amsAlarms:`Попередження AMS`,amsHtAlarms:`Попередження AMS-HT`,printQueue:`Черга друку`,start:`Початок`,plateCheck:`Перевірка пластини`,complete:`Завершено`,failed:`Помилка`,stopped:`Зупинено`,progress:`Прогрес`,offline:`Не в мережі`,lowFilament:`Закінчується філамент`,maintenance:`Технічне обслуговування`,amsHumidity:`AMS Вологість`,amsTemp:`AMS Темп`,amsHtHumidity:`AMS-HT Вологість`,amsHtTemp:`Температура AMS-HT`,bedCooled:`Стіл охолов`,firstLayer:`Перший шар`,quiet:`Тихо`,digest:`Дайджест {{time}}`,printStarted:`Друк розпочато`,plateNotEmpty:`Друкарська пластина не порожня`,plateNotEmptyDescription:`Перед друком виявлено об’єкти`,plateClearRequired:`Потрібно очистити пластину`,plateClearRequiredDescription:`Друк завершено, черга очікує підтвердження очищення пластини`,plateClear:`Очищення пластини`,printCompleted:`Друк завершено`,bedCooledLabel:`Стіл охолов`,bedCooledDescription:`Після друку стіл охолов нижче заданого порога`,firstLayerCompleteLabel:`Перший шар завершено`,firstLayerCompleteDescription:`Сповістити зі знімком після завершення першого шару`,missingSpoolAssignmentLabel:`Відсутнє призначення котушки`,missingSpoolAssignmentDescription:`Сповіщати, коли починається друк і для необхідних лотків не призначено котушку`,printFailed:`Помилка друку`,printStopped:`Друк зупинено`,progressMilestones:`Віхи прогресу`,progressMilestonesDescription:`Сповіщати на 25%, 50%, 75%`,printerOffline:`Принтер не в мережі`,printerError:`Помилка принтера`,aiFailureDetection:`Виявлення помилок за допомогою ШІ`,aiFailureDetectionDescription:`Сповіщати, коли ШІ Obico виявляє можливу помилку друку`,lowFilamentLabel:`Закінчується філамент`,maintenanceDue:`Настав час технічного обслуговування`,maintenanceDueDescription:`Повідомити, коли потрібне обслуговування`,amsHumidityHigh:`AMS Висока вологість`,amsHumidityHighDescription:`Звичайна AMS вологість перевищує порогове значення`,amsTemperatureHigh:`AMS Висока температура`,amsTemperatureHighDescription:`Звичайна AMS температура перевищує порогове значення`,amsHtHumidityHigh:`AMS-HT Висока вологість`,amsHtHumidityHighDescription:`AMS-HT вологість перевищує порогове значення`,amsHtTemperatureHigh:`Висока температура AMS-HT`,amsHtTemperatureHighDescription:`Температура AMS-HT перевищує порогове значення`,inventoryAlerts:`Сповіщення про запаси`,stockReorderAlert:`Сповіщення про необхідність поповнення`,stockReorderAlertDescription:`Запас SKU досяг точки повторного замовлення`,stockBreakAlert:`Сповіщення про ризик вичерпання запасу`,stockBreakAlertDescription:`Запас закінчиться до того, як надійде поповнення`,jobAdded:`Завдання додано`,jobAddedDescription:`Завдання додано до черги`,jobAssigned:`Завдання призначено`,jobAssignedDescription:`Завдання на основі моделі, призначене принтеру`,jobStarted:`Завдання розпочато`,jobStartedDescription:`Розпочато друк завдання черги`,jobWaiting:`Завдання очікує`,jobWaitingDescription:`Завдання очікує на філамент або принтер`,jobSkipped:`Завдання пропущено`,jobSkippedDescription:`Завдання пропущено (попереднє не вдалося)`,jobFailed:`Помилка завдання`,jobFailedDescription:`Не вдалося розпочати завдання`,queueComplete:`Черга завершена`,queueCompleteDescription:`Усі завдання черги завершено`,quietHours:`Тихі години`,noNotificationsDuring:`Жодних сповіщень у ці години`,editProviderToChangeQuietHours:`Змініть постачальника, щоб змінити години тиші`,dailyDigest:`Щоденний дайджест`,batchNotifications:`Групуйте сповіщення в єдиний щоденний підсумок`,sendAt:`Надсилати о {{time}}`,editProviderToChangeDigestTime:`Відредагуйте постачальника, щоб змінити час дайджесту`,edit:`Редагувати`,deleteProvider:`Видалити постачальника сповіщень`,deleteConfirm:`Видалити «{{name}}»? Цю дію неможливо скасувати.`,delete:`Видалити`,addTitle:`Додати постачальника сповіщень`,editTitle:`Редагувати постачальника сповіщень`,nameLabel:`Назва *`,namePlaceholder:`Мої сповіщення`,providerTypeLabel:`Тип постачальника *`,configuration:`Конфігурація`,testConfiguration:`Перевірити конфігурацію`,printerFilter:`Фільтр принтера`,onlyFromPrinter:`Надсилати лише сповіщення про події з цього принтера`,quietHoursDnd:`Тихі години (не турбувати)`,quietStart:`Початок`,quietEnd:`Кінець`,dailyDigestLabel:`Щоденний дайджест`,sendDigestAt:`Надсилати дайджест о`,digestCollected:`Події буде зібрано й надіслано в цей час одним зведенням`,notificationEvents:`Події сповіщень`,progressPercent:`(25%, 50%, 75%)`,bedCooledAfterPrint:`(після завершення друку)`,eventPriority:{sectionTitle:`Пріоритет ntfy`,helpNtfy:`Виберіть пріоритет для кожної ввімкненої події. ntfy використовує їх для ескалації сповіщень (звук, видимість, поведінка push). Для рівнів, які тут не встановлено, використовується сервер ntfy за замовчуванням.`,min:`Мін`,low:`Низький`,default:`За замовчуванням`,high:`Високий`,urgent:`Терміново`},cancel:`Скасувати`,save:`зберегти`,add:`додати`,nameRequired:`Необхідно вказати ім’я`,fieldRequired:`{{field}} — обов’язкове поле.`,haDataInvalid:`Поле «Дані» має містити дійсний об’єкт JSON, наприклад {"priority": "high", "ttl": 0}`,phoneNumber:`Номер телефону`,apiKey:`Ключ API`,serverUrl:`Сервер URL`,topic:`Тема`,authToken:`Токен авторизації`,userKey:`Ключ користувача`,appToken:`Токен застосунку`,priority:`Пріоритет`,pushoverRetry:`Інтервал повторення екстреного сповіщення (с)`,pushoverExpire:`Термін дії екстреного сповіщення (с)`,botToken:`Токен бота`,chatId:`Ідентифікатор чату`,telegramThreadId:`ID теми форуму`,telegramThreadIdHelp:`Необов'язково. Надсилає в конкретну тему форум-групи — останнє число у посиланні на тему (t.me/c/.../25). Залиште порожнім для теми General.`,telegramThreadIdInvalid:`ID теми форуму має бути числом.`,smtpServer:`Сервер SMTP`,smtpPort:`Порт SMTP`,security:`Безпека`,authentication:`Автентифікація`,username:`Ім’я користувача`,password:`Пароль`,fromEmail:`Адреса відправника`,toEmail:`Адреса одержувача`,webhookUrl:`Webhook URL`,payloadFormat:`Формат корисного навантаження`,authorization:`Авторизація`,titleFieldName:`Назва поля заголовка`,messageFieldName:`Назва поля повідомлення`,editTemplate:`Редагувати шаблон: {{name}}`,titleLabel:`Заголовок`,bodyLabel:`Текст`,titlePlaceholder:`Назва сповіщення...`,bodyPlaceholder:`Текст сповіщення...`,availableVariables:`Доступні змінні`,clickToInsert:`Натисніть, щоб вставити в текст у позиції курсора`,livePreview:`Попередній перегляд`,hide:`Сховати`,show:`Показати`,loadingPreview:`Завантаження попереднього перегляду...`,enterTemplateContent:`Введіть вміст шаблону, щоб побачити попередній перегляд`,titlePreview:`Назва:`,bodyPreview:`Текст:`,resetToDefault:`Відновити типові значення`,titleRequired:`Необхідно вказати назву`,bodyRequired:`Текст є обов’язковим`,notificationLog:`Журнал повідомлень`,showFailedOnly:`Лише невдалі`,last24Hours:`Останні 24 години`,last7Days:`Останні 7 днів`,last30Days:`Останні 30 днів`,last90Days:`Останні 90 днів`,justNow:`Щойно`,noFailedNotifications:`Немає невдалих сповіщень`,noNotificationsLogged:`Сповіщення не зареєстровано`,unknownProvider:`Невідомий постачальник`,logTitle:`Назва`,logMessage:`повідомлення`,logError:`Помилка`,logProvider:`Постачальник: {{type}}`,logTime:`Час: {{time}}`,refresh:`Оновити`,clearOld:`Очистити старі`,statsSummary:`За останні {{days}} дн.:`,statsNotifications:`сповіщення`,statsSent:`{{count}} надіслано`,statsFailed:`не вдалося надіслати: {{count}}`,eventTypes:{print_start:`Друк розпочато`,print_complete:`Друк завершено`,print_failed:`Помилка друку`,print_stopped:`Друк зупинено`,print_progress:`Прогрес`,printer_offline:`Принтер не в мережі`,printer_error:`Помилка принтера`,filament_low:`Закінчується філамент`,maintenance_due:`Технічне обслуговування`,test:`Тест`},userEmail:{title:`Сповіщення`,emailNotifications:`Сповіщення електронною поштою`,emailNotificationsDesc:`Отримуйте сповіщення електронною поштою про власні завдання друку. Електронні листи надсилаються за допомогою системних параметрів SMTP, налаштованих у розширеній автентифікації.`,sendingTo:`Сповіщення будуть надіслані на адресу`,noEmailWarning:`У вашому обліковому записі немає адреси електронної пошти. Зверніться до адміністратора, щоб її додати.`,printJobNotifications:`Повідомлення про завдання друку`,printJobNotificationsDesc:`Виберіть, які події викликають сповіщення електронною поштою про завдання друку, які ви надсилаєте.`,printJobStarts:`Початок завдання друку`,printJobStartsDesc:`Отримуйте сповіщення, коли розпочнеться ваше завдання друку.`,printJobFinishes:`Завершення завдання друку`,printJobFinishesDesc:`Отримуйте сповіщення, коли ваше завдання друку буде успішно завершено.`,printErrors:`Помилки друку`,printErrorsDesc:`Отримуйте сповіщення, якщо завдання друку завершується невдало або під час нього виникає помилка.`,printJobStops:`Зупинення завдання друку`,printJobStopsDesc:`Отримуйте сповіщення, коли ваше завдання друку скасовано або зупинено.`,saveSuccess:`Параметри сповіщень збережено.`,saveError:`Не вдалося зберегти налаштування сповіщень.`}},richTextEditor:{bold:`жирний`,italic:`Курсив`,underline:`Підкреслити`,bulletList:`Список маркерів`,numberedList:`Нумерований список`,alignLeft:`Вирівняти по лівому краю`,alignCenter:`Вирівняти по центру`,alignRight:`Вирівняти праворуч`,addLink:`Додати посилання`,removeLink:`Видалити посилання`},externalLinks:{title:`Посилання на бічній панелі`,sidebarLayout:`Бічна панель`,sidebarLayoutDescription:`Показуйте або приховуйте вбудовані сторінки, додавайте зовнішні посилання та перетягуйте елементи, щоб змінити порядок навігації на бічній панелі.`,systemPages:`Bambuddy сторінок`,externalLinks:`Зовнішні посилання`,visibleInSidebar:`Видно на бічній панелі`,hiddenFromSidebar:`Приховано від бічної панелі`,requiredInSidebar:`Обов’язково на бічній панелі`,hidePage:`Приховати сторінку`,showPage:`Показати сторінку`,settingsCannotBeHidden:`Налаштування не можна приховати`,noLinksConfigured:`Зовнішні посилання не налаштовано`,deleteLink:`Видалити посилання`,removeCustomIcon:`Видалити спеціальний значок`,openInNewTab:`Відкрити в новій вкладці`,placeholders:{linkName:`Моє посилання`}},keyboardShortcuts:{title:`Комбінації клавіш`,navigation:`Навігація`,archivesSection:`Архіви`,kProfilesSection:`K-профілі`,generalSection:`Загальний`,shortcuts:{goToPrinters:`Перейдіть до Принтери`,goToArchives:`Перейдіть до архіву`,goToQueue:`Перейдіть до черги`,goToStats:`Перейти до статистики`,goToProfiles:`Перейдіть до Cloud Profiles`,goToSettings:`Перейдіть до Налаштувань`,focusSearch:`Пошук по фокусу`,openUploadModal:`Відкрити вікно вивантаження`,clearSelection:`Очистити виділення / розмити введення`,contextMenu:`Контекстне меню на картках`,refreshProfiles:`Оновити профілі`,newProfile:`Новий профіль`,exitSelectionMode:`Вийти з режиму вибору`,showHelp:`Покажіть цю довідку`},footer:`Натисніть Esc або клацніть зовні, щоб закрити`},notificationLog:{title:`Журнал повідомлень`,events:{printStarted:`Друк розпочато`,printComplete:`Друк завершено`,printFailed:`Помилка друку`,printStopped:`Друк зупинено`,progress:`Прогрес`,printerOffline:`Принтер не в мережі`,printerError:`Помилка принтера`,lowFilament:`Закінчується філамент`,maintenanceDue:`Технічне обслуговування`,test:`Тест`},timeAgo:{justNow:`Просто зараз`,minutesAgo:`{{minutes}}хв тому`,hoursAgo:`{{hours}} год тому`}},restoreBackup:{title:`Відновити резервну копію`,restoring:`Відновлення...`,restoreComplete:`Відновлення завершено`,restoreFailed:`Не вдалося відновити`,importSettings:`Імпорт налаштувань із файлу резервної копії`,pleaseWait:`Зачекайте, поки ваші дані відновляться`,clickToSelect:`Натисніть, щоб вибрати файл резервної копії (.json або .zip)`,howDuplicateHandling:`Як працює обробка дублікатів:`,categories:{printers:`Принтери`,smartPlugs:`Розумні розетки`,notificationProviders:`Постачальники сповіщень`,filaments:`філаменти`,archives:`Архіви`,pendingUploads:`Вивантаження, що очікують`,settingsTemplates:`Налаштування та шаблони`},matchingInfo:{printers:`відповідає серійному номеру`,smartPlugs:`збігається з адресою IP.`,notificationProviders:`відповідність за назвою`,filaments:`відповідність за назвою + типом + брендом`,archives:`відповідає хешу вмісту`,pendingUploads:`відповідає імені файлу`,settingsTemplates:`завжди перезаписується`},replaceExisting:`Замінити існуючі дані`,keepExisting:`Зберегти наявні дані`,replaceDescription:`Замінити елементи, які вже існують, резервними копіями`,keepDescription:`Відновлюйте лише елементи, яких ще не існує`,caution:`Увага:`,cautionText:`Під час перезапису поточні конфігурації буде замінено даними з резервної копії. З міркувань безпеки коди доступу до принтерів ніколи не перезаписуються.`,itemsRestored:`Елементів відновлено`,itemsSkipped:`Елементи пропущені`,restored:`Відновлено`,skipped:`Пропущено (вже існує)`,filesLabel:`Файли (3MF, мініатюри тощо)`,newApiKeysGenerated:`Створено нові API ключі`,newApiKeysWarning:`Ці ключі буде показано лише один раз. Скопіюйте їх зараз!`,processingBackup:`Обробка файлу резервної копії...`,noDataFound:`У файлі резервної копії не знайдено даних для відновлення.`,failedToRestore:`Не вдалося відновити резервну копію. Будь ласка, перевірте формат файлу.`},backupExport:{title:`Експорт резервної копії`,selectData:`Вибрати дані для включення`,selectAll:`Вибрати усі`,selectNone:`Вибрати Немає`,categoryDescriptions:{settings:`Мова, тема, параметри оновлення`,notifications:`ntfy, Pushover, Discord тощо.`,templates:`Користувацькі шаблони повідомлень`,smartPlugs:`Конфігурації розетки Tasmota.`,externalLinks:`Посилання на бічній панелі на зовнішні служби`,printers:`Інформація про принтер (без кодів доступу)`,plateDetection:`Еталонні зображення порожньої пластини`,filaments:`Види та вартість філаменти`,maintenance:`Спеціальні графіки технічного обслуговування`,archives:`Усі дані для друку + файли (3MF, мініатюри, фотографії)`,projects:`Проєкти, елементи специфікації та вкладення`,pendingUploads:`Вивантаження на віртуальний принтер очікують на розгляд`,apiKeys:`Ключі Webhook API (нові ключі створюються під час імпорту)`},requiresPrinters:`Необхідно вибрати принтери`,zipFileWarning:`Буде створено файл ZIP.`,zipFileDescription:`До архіву ввійдуть усі файли 3MF, мініатюри, таймлапси та фотографії. Створення може тривати певний час, а отриманий файл може мати великий розмір.`,includeAccessCodes:`Додати коди доступу`,includeAccessCodesDescription:`Для перенесення на іншу машину`,includeAccessCodesWarning:`Коди доступу буде збережено у відкритому вигляді. Надійно захистіть файл резервної копії!`,categoriesSelected:`Вибрано категорії {{selectedCount}}.`},pendingUploads:{placeholders:{notes:`Додайте примітки щодо цього друку...`},discardUpload:`Відхилити вивантаження`,archiveAllUploads:`Архівувати всі вивантаження`,discardAllUploads:`Відхилити всі вивантаження`,archive:`Архів`,timeAgo:{justNow:`Просто зараз`,minutesAgo:`{{minutes}}хв тому`,hoursAgo:`{{hours}} год тому`,daysAgo:`{{days}} дн. тому`}},apiBrowser:{placeholders:{requestBody:`JSON тіло запиту...`,searchEndpoints:`Пошук кінцевих точок...`}},configureAmsSlot:{title:`Налаштувати слот AMS.`,slotConfigured:`Слот налаштовано!`,configuringSlot:`Налаштування слота:`,slotLabel:`{{ams}} Слот {{slot}}`,searchPresets:`Шукати профілі...`,colorPlaceholder:`Назва або шістнадцяткова назва кольору (наприклад, коричневий, FF8800)`,clearCustomColor:`Очистити спеціальний колір`,noCloudPresets:`Хмарних профілів немає. Увійдіть у Bambu Cloud для синхронізації.`,noPresetsAvailable:`Профілів немає. Увійдіть у Bambu Cloud або імпортуйте локальні профілі.`,noMatchingPresets:`Відповідних стилів не знайдено.`,custom:`Власний`,builtin:`Вбудований`,orcaCloud:`Orca Cloud`,bambuCloud:`Бамбукова хмара`,settingsSentToPrinter:`Налаштування надіслано на принтер`,filamentProfile:`Профіль філаменту`,kProfileLabel:`Профіль K (випередження тиску)`,filteringFor:`Фільтрування за: {{material}}`,noKProfile:`Немає профілю K (використовуйте значення за замовчуванням 0,020)`,noMatchingKProfiles:`Не знайдено відповідних K профілів. Використовуватиметься K=0,020 за замовчуванням.`,otherKProfiles:`Інші K-профілі на цьому принтері`,selectFilamentFirst:`Спочатку виберіть профіль філаменту`,kFromCalibration:`K={{value}} від калібрування принтера`,customColorLabel:`Власний колір (необов’язково)`,presetColors:`{{name}} кольори:`,showLessColors:`Показувати менше кольорів`,showMoreColors:`Показати більше кольорів`,clear:`Очистити`,hexLabel:`Шістнадцятковий: #{{hex}}`,resetting:`Скидання...`,resetSlot:`Скинути слот`,cancel:`Скасувати`,configuring:`Налаштування...`,configureSlot:`Налаштувати слот`},githubBackup:{title:`Резервне копіювання Git`,history:`історія`,downloadBackup:`Завантажити резервну копію`,restoreBackup:`Відновити резервну копію`,noBackupsYet:`Резервних копій ще немає`},emailSettings:{placeholders:{fromName:`BamBuddy`}},tagManagement:{searchTags:`Пошук тегів...`,renameTag:`Перейменувати тег`,deleteTag:`Видалити тег`},notificationTemplates:{placeholders:{title:`Назва сповіщення...`,body:`Текст сповіщення...`}},batchTag:{placeholders:{newTag:`Введіть новий тег...`}},photoGallery:{deletePhoto:`Видалити фото`},filamentHoverCard:{copySpoolUuid:`Копіювати UUID буфера`},kProfilesView:{hasNote:`Має примітку`,copyProfile:`Копіювати профіль`},layout:{openMenu:`Відкрити меню`,noPermissionSystemInfo:`У вас немає дозволу на перегляд системної інформації`},dashboard:{dragToReorder:`Перетягніть, щоб змінити порядок`,hideWidget:`Сховати віджет`},notificationProviderCard:{deleteNotificationProvider:`Видалити постачальника сповіщень`},fileManagerModal:{closeFileManager:`Закрити файловий менеджер`,sortFiles:`Сортування файлів`,goToParentFolder:`Перейти до батьківської папки`,threeView:`3D перегляд`},embeddedCameraViewer:{refreshStream:`Оновити потік`,close:`Закрити`,zoomOut:`Зменшити масштаб`,resetZoom:`Скинути масштаб`,zoomIn:`Збільшити`,dragToResize:`Перетягніть, щоб змінити розмір`},timelapseViewer:{skipBack5s:`Перейти на 5 секунд назад`,skipForward5s:`Перейти вперед на 5 с`},notificationProviders:{descriptions:{email:`Сповіщення електронною поштою SMTP`,telegram:`Сповіщення через бота Telegram.`,discord:`Надіслати на канал Discord через webhook`,ntfy:`Безкоштовні push-сповіщення з можливістю самостійного розгортання`,pushover:`Прості та надійні push-повідомлення`,callmebot:`Безкоштовні сповіщення WhatsApp через CallMeBot`,webhook:`Універсальний HTTP POST-запит на будь-який URL`}},logViewer:{searchPlaceholder:`Шукати повідомлення або назву реєстратора...`,noLogEntries:`Записів у журналі не знайдено`},switchbarPopover:{noSwitchesInSwitchbar:`На панелі перемикачів немає`},projectPageModal:{placeholders:{title:`Назва`,designer:`Дизайнер`,license:`Ліцензія`,description:`Введіть опис...`,profileTitle:`Назва профілю`,profileDescription:`Опис профілю...`}},spoolmanSettings:{},time:{unknown:`-`,waiting:`Очікування`,justNow:`Просто зараз`,now:`Зараз`,minsAgo:`{{count}}хв тому`,inMins:`в {{count}}м`,hoursAgo:`{{count}} год тому`,inHours:`в {{count}} год`,daysAgo:`{{count}} дн. тому`,inDays:`в {{count}}d`},spoolbuddy:{nav:{dashboard:`Приладова панель`,ams:`AMS`,inventory:`Інвентар`,writeTag:`Записати`,settings:`Налаштування`},status:{nfcReady:`NFC Готовий`,nfcOff:`NFC Вимк`,offline:`Не в мережі`,online:`Онлайн`,noPrinters:`Немає принтерів`,deviceOffline:`Пристрій не в мережі`,waitingConnection:`Очікування підключення пристрою...`,systemReady:`Система готова`,status:`Статус`},dashboard:{readyToScan:`Готовий до сканування`,idleMessage:`Покладіть котушку на ваги, щоб ідентифікувати її`,nfcHint:`Тег NFC буде прочитано автоматично`,device:`пристрій`,syncWeight:`Синхронізувати вагу`,weightSynced:`Синхронізовано!`,unknownTag:`Невідомий тег`,newTag:`Виявлено новий тег`,onScale:`на вагах`,linkSpool:`Прив’язати до котушки`,linkTagTitle:`Прив’язати тег до котушки`,linkTag:`Прив’язати тег`,selectSpool:`Виберіть котушку, до якої потрібно прив’язати цей тег:`,noUntagged:`Не знайдено котушок без тегів`,tagDetected:`Тег виявлено`,noTag:`Без тегу`,tagId:`Тег`,grossWeight:`Вага брутто`,spoolSize:`Розмір котушки`,close:`Закрити`,currentSpool:`Поточна котушка`,plateReady:`Пластина готова: {{name}}`,plateReadyLabel:`Пластини готові до очищення`,plateClearAction:`Очистити`,plateClearedToast:`Друкарська пластина позначена як очищена`,plateClearFailed:`Не вдалося позначити пластину як очищену`},modal:{spoolDetected:`Виявлено котушку`,assignToAms:`Призначити AMS`,syncWeight:`Синхронізувати вагу`,weightSynced:`Синхронізовано!`,syncing:`Синхронізація...`,newTagDetected:`Виявлено новий тег`,addToInventory:`Додати в інвентар`,assignToAmsTitle:`Призначити AMS`,selectSlot:`Вибрати слот`,assign:`Призначити`,assigning:`Призначення...`,assignSuccess:`Призначено!`,assignPendingInsert:`Призначений. Слот буде налаштовано, коли ви вставите котушку.`,assignError:`Не вдалося призначити котушку. Спробуйте ще раз.`,noPrinterSelected:`Виберіть принтер...`,noAmsDetected:`AMS не виявлено на цьому принтері`,slot:`Слот`},weight:{noReading:`Немає показань`,stable:`Стабільно`,measuring:`Вимірювання…`,tare:`Тарувати`,calibrate:`Відкалібрувати`},spool:{remaining:`Залишилося`,material:`матеріал`,brand:`Бренд`,color:`Колір`,coreWeight:`Сердечник`,labelWeight:`Етикетка`,scaleWeight:`Показання ваг`,netWeight:`Нетто`,lastUsed:`Останнє використання`},ams:{noData:`AMS не виявлено`,connectAms:`Підключіть AMS, щоб побачити слоти для філаментів`,noPrinter:`Принтер не вибрано`,selectPrinter:`Виберіть принтер у верхній панелі`,printerDisconnected:`Принтер відключений`,humidity:`Вологість`,level:`Рівень`,active:`Активний`,slot:`Слот`,empty:`Порожній`},inventory:{search:`Пошук котушок...`,empty:`Немає котушок в інвентарі`,noResults:`Немає відповідних котушок`,spools:`котушки`,addSpool:`Додати котушку`},settings:{tabDevice:`пристрій`,tabDisplay:`Дисплей`,tabScale:`Ваги`,tabUpdates:`Оновлення`,nfcReader:`NFC Читач`,type:`Тип`,connection:`Підключення`,notConnected:`Н/Д`,deviceInfo:`Інформація про пристрій`,hostname:`Хост`,uptime:`Час роботи`,systemConfig:`Серверна частина та автентифікація`,backendUrl:`Bambuddy Сервер URL`,apiToken:`API Токен`,apiTokenPlaceholder:`Введіть API-токен.`,saveConfig:`Зберегти конфігурацію`,systemQueued:`Конфігурацію в черзі.`,nfcDiagnostic:`NFC Діагностика`,scaleDiagnostic:`Діагностика ваг`,readTagDiagnostic:`Прочитайте діагностику тегів`,testNfc:`Тестовий читач`,testScale:`Перевірити точність`,testReadTag:`Прочитати тег`,systemFieldsRequired:`Потрібен бекенд URL.`,brightness:`Яскравість`,saved:`Збережено`,noBacklight:`Підсвічування DSI не виявлено. Для керування яскравістю потрібен дисплей DSI.`,screenBlank:`Час очікування порожнього екрана`,screenBlankDesc:`Екран вимикається після бездіяльності. Торкніться, щоб розбудити.`,displayNote:`Яскравість використовується як програмний фільтр.`,scaleCalibration:`Калібрування ваг`,currentWeight:`Поточна вага`,tareOffset:`Зміщення тари`,calFactor:`Коефіцієнт калібрування`,knownWeight:`Відома маса`,calStep1:`Приберіть усі предмети з ваг і натисніть «Установити нуль».`,calStep2:`Покладіть на ваги предмет відомої маси.`,setZero:`Встановити нуль`,calibrateNow:`Відкалібрувати`,calibrated:`Відкалібровано`,tareSet:`Надіслано команду тарування. Очікування пристрою...`,tareComplete:`Тарування завершено!`,tareTimedOut:`Час очікування тарування минув — чи запущено демон SpoolBuddy?`,tareFailed:`Не вдалося надіслати команду тарування`,zeroSet:`Нульову точку встановлено. Покладіть на ваги предмет відомої маси.`,calibrationDone:`Калібрування завершено!`,calibrationFailed:`Помилка калібрування`,lastCalibrated:`Останнє калібрування`,stable:`Стабільно`,settling:`Стабілізація…`,firmware:`Прошивка`,scale:`Ваги`,noDevice:`Пристрій SpoolBuddy не знайдено`,daemonVersion:`Демон версія`,currentVersion:`поточний`,versionPending:`В очікуванні демона...`,checking:`Перевірка...`,checkUpdates:`Перевірте наявність оновлень`,updateAvailable:`Доступне оновлення`,updateInstructions:`Оновлення через SSH: запустіть сценарій встановлення SpoolBuddy для оновлення.`,upToDate:`В актуальному стані`,includeBeta:`Включати бета-версії`},writeTag:{tabExisting:`Наявна котушка`,tabNew:`Нова котушка`,tabReplace:`Замінити тег`,searchPlaceholder:`Пошук за матеріалом, кольором, брендом...`,noUntaggedSpools:`Немає котушок без тегів`,noTaggedSpools:`Немає котушок із тегами`,selectSpool:`Виберіть котушку, а потім помістіть порожній NTAG на зчитувач`,placeTag:`Помістіть NTAG на зчитувач`,tagReady:`Тег виявлено — готовий до запису`,writeTag:`Записати тег`,replaceTag:`Замінити тег`,writing:`Записування тегу…`,waiting:`Очікування SpoolBuddy...`,writeSuccess:`Тег успішно записано!`,writeFailed:`Помилка запису`,queueFailed:`Не вдалося поставити команду запису в чергу`,tryAgain:`Спробуйте знову`,cancel:`Скасувати`,replaceWarning:`Старий тег буде від’єднано від котушки, а замість нього буде прив’язано новий.`,deviceOffline:`SpoolBuddy не в мережі`,material:`матеріал`,colorName:`Назва кольору`,color:`Колір`,brand:`Бренд`,weight:`Вага (г)`,createSpool:`Створити котушку`,creating:`Створення...`,spoolCreated:`Котушку створено! Можна записувати тег.`,createFailed:`Не вдалося створити котушку`,incompleteDataWarning:`Тег записано з неповними даними Spoolman.`},quickMenu:{printerPower:`Живлення принтера`,systemControls:`система`,restartDaemon:`Перезапустити демон`,restartBrowser:`Перезапустити браузер`,reboot:`Перезавантажити`,shutdown:`Вимкнути`,swipeToClose:`Проведіть пальцем вниз, щоб закрити`,confirmTitle:`Підтвердити`,confirmShutdown:`Вимкнути SpoolBuddy? Щоб увімкнути його знову, знадобиться фізичний доступ до пристрою.`,confirmReboot:`Перезавантажити SpoolBuddy?`,confirmRestartDaemon:`Перезапустити демон SpoolBuddy? NFC і ваги будуть тимчасово недоступні.`,confirmRestartBrowser:`Перезапустити веб-переглядач кіоску? Дисплей на короткий час погасне.`,confirm:`Підтвердити`,confirmPlugOn:`Увімкнути {{name}}?`,confirmPlugOff:`Вимкнути {{name}}?`,turnOn:`Увімкнути`,turnOff:`Вимкнути`}},diagnostic:{modalTitle:`Діагностика підключення — {{name}}`,running:`Виконується діагностика...`,runningElapsed:`Виконується діагностика… ({{elapsed}} с)`,waitingForReportHint:`Очікуємо, доки принтер опублікує звіт про стан — це може тривати до {{max}} с.`,runFailed:`Не вдалося запустити діагностику: {{error}}`,retry:`Запустити знову`,runButton:`Запустити діагностику`,sectionTitle:`Діагностика підключення`,sectionDescription:`Перевірте, чому принтер не підключається або не друкує — доступність порту, режим розробника LAN, режим мережі Docker та облікові дані.`,noPrinters:`Принтери не налаштовані.`,overall:{ok:`Проблем не виявлено — з’єднання принтера справне.`,warnings:`Принтер має працювати, але деякі параметри потребують уваги.`,problems:`Знайдено проблеми, які пояснюють, чому принтер не підключається або не друкує.`},check:{port_mqtt:{title:`Порт керування (MQTT 8883)`,pass:`Доступний — принтер приймає керівні з’єднання.`,fail:`Порт 8883 недоступний. Принтер може бути вимкнений, мати іншу IP-адресу або бути заблокований брандмауером. Перевірте IP-адресу принтера й переконайтеся, що порт 8883 не заблоковано.`},port_ftps:{title:`Порт передачі файлів (FTPS 990)`,pass:`Доступний — файли друку можна буде надсилати.`,warn:`Порт 990 недоступний. Моніторинг може й надалі працювати, але надсилання завдань друку на принтер завершуватиметься помилкою. Переконайтеся, що порт 990 не заблоковано.`},external_storage:{title:`Зберігання надісланих файлів у зовнішньому сховищі (крок установлення 4)`,pass:`Принтер повідомляє, що цю опцію ввімкнено — надіслані файли зберігатимуться на картці SD, а архіви матимуть мініатюри та метадані слайсера.`,fail:`Принтер повідомляє, що цей параметр вимкнено. Увімкніть «Зберігати надіслані файли в зовнішньому сховищі». У новіших версіях прошивки (P2S 01.02 / Bambu Studio 2.6+) перемикач розташований у налаштуваннях друку на принтері; у старіших — на вкладці «Пристрій» у Bambu Studio або OrcaSlicer. Без цього параметра в кожному архівованому друці будуть відсутні мініатюра та метадані слайсера.`,skip:`Не перевірено — потрібне активне MQTT-з’єднання. У старіших слайсерах, де цей параметр існує лише в самому слайсері, принтер його не повідомляє. Тому перевірка може бути успішною навіть за вимкненого параметра — перевірте крок установлення 4 вручну.`,skip_unsupported_model:`Ця модель має слот для SD-картки, але не дає змоги ввімкнути цей параметр: поточна прошивка принтерів серії P1 не показує перемикач у Bambu Studio, а сам принтер не має екрана. Виправляти нічого не потрібно; доки Bambu Lab не додасть підтримку в прошивці, в архівованих друках можуть бути відсутні мініатюри та метадані слайсера.`},port_rtsps:{title:`Порт камери ({{protocol}} {{port}})`,pass:`Доступно — потік камери працюватиме.`,warn:`Порт {{port}} недоступний. Перегляд з камери в реальному часі не працюватиме. Це не впливає на друк.`},network_mode:{title:`Мережевий режим Docker`,pass:`Працює в режимі хост-мережі.`,warn:`Bambuddy працює в мостовому мережевому режимі Docker. Для виявлення принтерів і роботи віртуального принтера потрібен режим мережі хоста — повторно створіть контейнер із параметром "network_mode: host".`,skip:`Не працює в Docker — не застосовується.`},subnet:{title:`Мережева підмережа`,pass:`Принтер і Bambuddy знаходяться в одній підмережі.`,warn:`Принтер ({{printer_ip}}) і Bambuddy ({{host_ip}}) перебувають у різних підмережах. Вони можуть не мати зв’язку між собою, якщо маршрутизацію між підмережами не налаштовано.`,skip:`Не вдалося визначити підмережу — пропущено.`},mqtt_auth:{title:`Облікові дані принтера`,pass:`Принтер прийняв підключення.`,fail:`Принтер доступний, але Bambuddy до нього не під’єднано. Найімовірніше, указано неправильний код доступу або серійний номер — код доступу змінюється після кожного перемикання режиму «Лише LAN» або режиму розробника, тож знову скопіюйте його з екрана принтера. Так само виглядає принтер, який перезавантажується або вже вичерпав ліміт одночасних з’єднань.`,fail_auth_rejected:`Принтер відхилив облікові дані Bambuddy. Код доступу або серійний номер неправильний — код доступу змінюється після кожного перемикання режиму «Лише LAN» або режиму розробника. Знову скопіюйте його з екрана принтера та збережіть у налаштуваннях принтера.`,skip:`Не позначено — принтер недоступний.`},developer_mode:{title:`Режим розробника LAN`,pass:`Режим розробника ввімкнено.`,fail:`Режим розробника на принтері ВИМКНЕНО. Увімкніть його в налаштуваннях LAN принтера й підтвердьте вибір кнопкою OK. Без цього друк не запускатиметься.`,skip:`Неможливо перевірити — потрібне живе підключення до принтера.`},printer_publishing:{title:`Принтер публікує дані про стан`,pass:`Принтер публікує оновлення статусу — AMS, філаменти та K-профілі правильно відображатимуться на слайсері.`,fail:`MQTT-брокер прийняв з’єднання, але принтер не опублікував жодного звіту про стан. Майже завжди причиною є неправильний серійний номер або неправильний регістр символів: тема device//report чутлива до регістру. Звірте серійний номер у налаштуваннях Bambuddy із номером на екрані принтера.`,skip:`Неможливо перевірити — потрібне живе підключення до принтера.`}}},systemHealth:{sectionTitle:`Стан системи`,sectionDescription:`Сканує останні журнали на наявність відомих проблем, які зазвичай можна вирішити самостійно, перш ніж вони перетворяться на запит у службу підтримки.`,rescan:`Пересканувати`,clean:`В останніх записах журналу {{times}} не знайдено відомих проблем.`,logUnavailable:`Журналування файлів вимкнено, тому журнали неможливо сканувати. Увімкніть журналювання файлів, щоб використовувати цю перевірку.`,learnMore:`Як виправити`,fixLabel:`Виправити:`,occurrences:`Виявлено {{times}} разів — востаннє о {{lastSeen}}`,category:{layer8:`Ви можете це виправити`,environment:`Середовище виконання`,bug:`Будь ласка, повідомте про це`},signature:{"ftp-auth-rejected":{name:`Принтер відхилив код доступу`,cause:`Принтер відмовився від входу для передавання файлів. Код доступу неправильний або він змінився після перемикання режиму розробника.`,fix:`Повторно скопіюйте код доступу з екрана принтера (налаштування LAN) і оновіть його в налаштуваннях принтера в Bambuddy.`},"ftp-connection-timeout":{name:`Час очікування з’єднання для передачі файлів минув`,cause:`Bambuddy не вдалося отримати доступ до порту передачі файлів принтера (FTPS 990). Порт заблоковано, або принтер вимкнено або знаходиться в іншій підмережі.`,fix:`Переконайтеся, що ніщо не блокує порт 990 між Bambuddy і принтером, і що обидва знаходяться в одній мережі.`},"ftp-ssl-error":{name:`Помилка захищеного з’єднання для передавання файлів`,cause:`Не вдалося виконати TLS-узгодження із сервером передавання файлів принтера. Частою причиною є брандмауер або застаріла прошивка принтера.`,fix:`Оновіть прошивку принтера та переконайтеся, що брандмауер або проксі-сервер не перехоплюють з’єднання через порт 990.`},"mqtt-connection-flapping":{name:`Підключення до принтера постійно падає`,cause:`Керуюче з’єднання (MQTT 8883) неодноразово роз’єднується та знову під’єднується — зазвичай через слабкий мережевий шлях або частково заблокований порт.`,fix:`Перевірте сигнал Wi-Fi на принтері, віддайте перевагу дротовому підключенню та переконайтеся, що порт 8883 надійно доступний.`},"camera-connection-refused":{name:`Потік з камери недоступний`,cause:`Не вдається отримати доступ до камери в прямому ефірі через порт RTSPS 322. Порт заблоковано, або на принтері вимкнено камеру або LAN liveview.`,fix:`Увімкніть камеру та LAN liveview на принтері та переконайтеся, що порт 322 не заблоковано. Це не впливає на друк.`},"database-locked":{name:`Конфлікт запису до бази даних`,cause:`Під навантаженням SQLite повертає помилки "database is locked". Це часто трапляється, коли одночасно працюють кілька принтерів.`,fix:`Переключіть Bambuddy на зовнішню базу даних PostgreSQL. Див. посібник PostgreSQL у документації.`}}},vpDiagnostic:{title:`Перевірка налаштувань — {{name}}`,runButton:`Запустити перевірку налаштувань`,running:`Виконується перевірка налаштувань...`,runFailed:`Не вдалося виконати перевірку налаштувань: {{error}}`,retry:`Запустити знову`,overall:{ok:`Усі перевірки пройшли — цей віртуальний принтер налаштовано правильно.`,warnings:`Віртуальний принтер має працювати, але деякі параметри потребують уваги.`,problems:`Знайдено проблеми, які пояснюють, чому слайсер не бачить або не використовує цей віртуальний принтер.`},check:{enabled:{title:`Віртуальний принтер увімкнено`,fail:`Цей віртуальний принтер вимкнено. Увімкніть його, щоб зробити його видимим.`},running:{title:`Служби запущені`,fail:`Віртуальний принтер увімкнено, але його служби не працюють. Перевірте журнал Bambuddy — зазвичай запуску заважає конфлікт IP-адреси прив’язки або помилка дозволів.`},bind_interface:{title:`Прив’язка мережевого інтерфейсу`,fail:`Інтерфейс прив’язки не встановлено або більше не існує на цьому хості. Виберіть поточний інтерфейс у спадному списку «Інтерфейс прив’язки».`},access_code:{title:`Код доступу встановлено`,fail:`Код доступу не встановлено. У слайсері потрібно вказати той самий 8-символьний код доступу, який задано тут.`},target_printer:{title:`Цільовий принтер`,fail:`Цільовий принтер не вибрано. У режимі проксі потрібен фізичний принтер, якому пересилатимуться завдання.`,warn:`Цільовий принтер наразі не в мережі — проксі-сервер відновиться після повторного підключення.`},port_ftps:{title:`Служба вивантаження файлів (порт {{port}})`,fail:`На порту {{port}} IP-адреси прив’язки немає служби, що приймає з’єднання, тому слайсер не може вивантажити файли. Зазвичай причиною є конфлікт порту на цьому інтерфейсі.`},port_mqtt:{title:`Служба керування (порт {{port}})`,fail:`На порту {{port}} IP-адреси прив’язки немає служби, що приймає з’єднання, тому слайсер не може підключитися або показати стан.`},port_bind:{title:`Служба виявлення (порт {{port}})`,fail:`На порту {{port}} IP-адреси прив’язки немає служби, що приймає з’єднання, тому слайсер не може завершити процедуру виявлення.`},certificate:{title:`Сертифікат TLS`,pass:`Сертифікат готовий. Переконайтеся, що наведений вище сертифікат центру сертифікації Bambuddy імпортовано до сховища довірених сертифікатів слайсера.`,fail:`Сертифікат TLS для цього віртуального принтера відсутній. Перевірте, чи доступний для запису каталог даних Bambuddy.`}}},bugReport:{title:`Повідомити про помилку`,description:`опис`,descriptionPlaceholder:`Що пішло не так? Будь ласка, опишіть проблему...`,email:`Електронна адреса (необов’язково)`,emailPlaceholder:`your@email.com`,emailPrivacy:`Якщо надано, вашу електронну адресу буде включено до згорнутого розділу проблеми GitHub, щоб спеціаліст із супроводу міг відслідковувати.`,screenshot:`Скріншот`,uploadOrPaste:`Вивантажити, вставити або перетягнути зображення`,dataCollectedSummary:`Які дані містяться у звіті?`,dataIncluded:`У комплекті:`,dataIncludedList:`Версія додатка, OS, архітектура, версія Python, статистика бази даних (лише для підрахунку), моделі принтерів, кількість сопел, версії прошивки, статус підключення, статус інтеграції (Spoolman, MQTT, HA), неконфіденційні налаштування, кількість мережевих інтерфейсів, Docker деталі, версії залежностей.`,dataNeverIncluded:`Ніколи не додаються:`,dataNeverIncludedList:`Назви принтерів, серійні номери, коди доступу, паролі, IP-адреси, адреси електронної пошти, ключі API, токени, URL вебхуків, імена хостів або користувачів.`,submit:`Надіслати`,startLogging:`Розпочати журнал налагодження`,stepEnableLogging:`Журнал налагодження ввімкнено`,stepReproduce:`Відтворіть проблему зараз`,stepStopLogging:`Зупинити та подати звіт`,stopAndSubmit:`Зупинити та надіслати`,maxDuration:`Автоматична зупинка через {{minutes}} хв`,stoppingLogs:`Збір журналів і надсилання...`,submitting:`Надсилання звіту про помилку...`,submittingStepConnection:`Запуск перевірки підключення принтера`,submittingStepVirtualPrinters:`Виконання перевірок налаштування віртуального принтера`,submittingStepLogScan:`Сканування останніх журналів на наявність відомих проблем`,submittingStepSubmit:`Надсилання звіту GitHub`,submitSuccess:`Звіт про помилку успішно надіслано!`,submitFailed:`Не вдалося надіслати звіт про помилку`,diagnosticChecking:`Перевірка підключень принтера...`,diagnosticHealthy:`Перевірку підключення пройдено — проблем із принтерами не виявлено.`,diagnosticSummary:`Проблеми з підключенням мають {{problems}} із {{total}} принтерів`,diagnosticIntro:`Один або кілька принтерів мають проблему з підключенням, яка може спричиняти описану несправність. Розгорніть запис принтера нижче, щоб переглянути спосіб виправлення. Усунення цієї проблеми може допомогти без створення звіту про помилку, але за потреби звіт усе одно можна надіслати нижче.`,logHealthSummary:`У ваших журналах знайдено відомі проблеми`,logHealthIntro:`Останні журнали відповідають відомим проблемам. Перегляньте наведені нижче виправлення — їх вирішення може вирішити вашу проблему без повідомлення про помилку. Ви все ще можете надіслати звіт нижче.`,thankYou:`дякую!`,submitted:`Ваш звіт про помилку надіслано.`,viewIssue:`Переглянути випуск`,unexpectedError:`Сталася неочікувана помилка`},failureDetection:{title:`Виявлення помилок за допомогою ШІ`,description:`Відстежуйте друк за допомогою самостійно розгорнутого Obico ML API та автоматично реагуйте на виявлені помилки.`,mlUrl:`URL Obico ML API`,mlUrlHint:`База URL вашого контейнера ml_api, розміщеного на власному хості Obico (наприклад, http://192.168.1.10:3333).`,mlToken:`Токен ML API (необов'язково)`,mlTokenPlaceholder:`Залиште порожнім, якщо сервер працює без ML_API_TOKEN`,mlTokenHint:`Має збігатися зі змінною середовища ML_API_TOKEN вашого контейнера Obico ml_api. Залиште порожнім, якщо контейнер працює без токена.`,test:`Тест`,testSuccess:`ML API доступний і працює належним чином.`,testSuccessTokenUnknown:`ML API доступний і працює належним чином. Не вдалося перевірити токен.`,testFailed:`Не вдалося підключитися до ML API.`,sensitivity:`Чутливість`,sensitivityLow:`Низький (менше помилкових спрацьовувань)`,sensitivityMedium:`Середній (збалансований)`,sensitivityHigh:`Високий (виявляти рано, більше помилкових спрацьовувань)`,sensitivityHint:`Налаштовує пороги впевненості, за яких формуються попередження та фіксуються помилки.`,action:`Дія в разі виявлення помилки`,actionNotify:`Лише сповіщати`,actionPause:`Призупинити друк`,actionPauseOff:`Призупинити друк і вимкнути живлення`,pollInterval:`Інтервал опитування (секунди)`,pollIntervalHint:`Як часто перевіряти кожен принтер під час друку. Мінімум 5 с, максимум 120 с.`,externalUrlMissing:`Зовнішній URL не встановлено.`,externalUrlHint:`ML API отримує знімок із камери за URL. Укажіть зовнішній URL у загальних налаштуваннях, щоб контейнер ML API міг підключитися до Bambuddy.`,perPrinterTitle:`Принтери під спостереженням`,perPrinterHint:`Виберіть, які принтери перевіряє служба виявлення.`,monitorAll:`Відстежувати всі підключені принтери`,statusTitle:`Статус`,serviceRunning:`Служба працює`,thresholds:`Нижній / верхній поріг`,activePrinters:`Активні завдання друку`,noActivePrints:`Зараз немає роздруківок.`,historyTitle:`Останні виявлення`,noHistory:`Виявлень ще немає.`},makerworld:{title:`MakerWorld`,description:`Вставте модель MakerWorld URL, щоб імпортувати та роздрукувати її безпосередньо з Bambuddy — не виходячи з програми Bambu Handy.`,pasteUrlHeader:`Імпортувати з MakerWorld`,pasteUrlPlaceholder:`https://makerworld.com/en/models/… або вставте будь-яке посилання MakerWorld.`,resolveButton:`Розв’язати`,signInRequiredTitle:`Для завантаження потрібно увійти в Bambu Cloud`,signInRequiredBody:`Ви можете переглядати деталі моделі анонімно, але для MakerWorld потрібен обліковий запис Bambu Cloud для завантаження файлів 3MF.`,signInExpiredTitle:`Термін входу в Bambu Cloud минув`,signInExpiredBody:`Ви все ще ввійшли в Bambuddy, але Bambu Lab більше не приймає збережений токен, тому завантаження не вдасться. Знову ввійдіть у Bambu Cloud.`,openCloudSettings:`Відкрити налаштування Cloud`,untitledModel:`Модель без назви`,byCreator:`від {{name}}`,downloadsCount:`{{count}} завантажень`,licensePrefix:`Ліцензія`,alreadyImported:`Вже в бібліотеці`,openOnMakerworld:`Відкрити MakerWorld`,alreadyInLibrary:`Ця модель уже є у вашій бібліотеці — знайдіть її в Менеджері файлів → MakerWorld`,importSuccess:`Імпортовано {{filename}} — збережено в менеджері файлів → MakerWorld`,platesHeader:`Пластини ({{count}})`,plateDefaultName:`Пластина {{n}}`,materialCount:`Філаментів: {{count}}`,amsRequired:`Потрібен AMS`,slicedFor:`Нарізано для {{printer}}`,alsoCompatible:`Також позначено як сумісний: {{printers}}`,importToLibrary:`Зберегти`,sliceIn:`Зберегти й нарізати в {{slicer}}`,disclaimer:`Інтеграція MakerWorld використовує кінцеві точки API, задокументовані спільнотою. Bambuddy не є філією та не підтримується MakerWorld або Bambu Lab.`,lastImportSuccess:`Імпортовано до вашої бібліотеки`,lastImportAlreadyInLibrary:`Уже у вашій бібліотеці`,viewInLibrary:`Переглянути в менеджері файлів`,openInBambuStudio:`Відкрити в Bambu Studio`,openInOrcaSlicer:`Відкрити в OrcaSlicer`,importTo:`Імпорт до файлового менеджера`,recentImportsHeader:`Недавній імпорт`,phaseResolving:`Розв’язування`,phaseDownloading:`Завантаження`,folderAuto:`MakerWorld (за замовчуванням)`,importAll:`Імпортувати все`,importAllProgress:`Імпорт {{current}}/{{total}}`,openGallery:`Відкрити галерею зображень`,galleryPrev:`Попереднє зображення`,galleryNext:`Наступне зображення`,deleteImport:`Видалити з бібліотеки`,importDeleting:`Видалення…`,importDeleted:`Видалено з бібліотеки`,confirmDelete:`Видалити {{filename}} з бібліотеки? Локальний файл буде видалено, але цю друкарську пластину можна буде повторно імпортувати з MakerWorld.`,errors:{resolveFailed:`Не вдалося вирішити MakerWorld URL.`,downloadFailed:`Помилка завантаження. Спробуйте ще раз.`,deleteFailed:`Не вдалося видалити файл із бібліотеки.`}},gcodeViewer:{back:`Назад`,backToArchives:`Назад до друку архівів`,backToFiles:`Назад до файлового менеджера`},libraryTrash:{title:`Кошик`,headerButton:`Кошик`,headerTooltip:`Переглянути файли, переміщені в кошик`,backToFiles:`Назад до файлового менеджера`,subtitleAdmin:`Видалені файли залишаються тут протягом {{days}} днів, а потім автоматично видаляються. У цьому режимі перегляду відображаються файли, видалені в кошик для всіх користувачів.`,subtitleUser:`Видалені файли залишаються тут протягом {{days}} днів, а потім автоматично видаляються.`,loading:`Завантаження кошика…`,loadError:`Не вдалося завантажити кошик.`,empty:`Кошик порожній.`,summary:`Файлів: {{count}} · {{size}}`,emptyTrash:`Очистити кошик`,restore:`Відновити`,purgeNow:`Видалити зараз`,autoPurgeIn:`Автоматичне видалення через {{when}}`,days:`днів`,retentionLabel:`Автоматичне видалення після`,selectAll:`Вибрати все`,selectOne:`Вибрати {{filename}}`,selectionCount:`Вибрано {{count}}.`,bulkRestore:`Відновити вибране`,bulkPurge:`Видалити вибране`,col:{filename:`Файл`,folder:`Папка`,size:`Розмір`,deleted:`Переміщено в кошик`,autoPurge:`Автоматичне видалення`,owner:`Власник`,actions:`Дії`},confirm:{purgeTitle:`Видалити остаточно?`,purgeBody:`{{filename}} буде видалено з диска та не підлягає відновленню.`,emptyTitle:`Очистити кошик?`,emptyBody:`З диска буде остаточно видалено всі файли ({{count}}). Цю дію неможливо скасувати.`,bulkPurgeTitle:`Видалити вибрані файли назавжди?`,bulkPurgeBody:`Вибрані файли ({{count}}) буде видалено з диска без можливості відновлення.`,cta:`Видалити остаточно`},toast:{restored:`Файл відновлено.`,restoreFailed:`Не вдалося відновити файл.`,purged:`Файл видалено остаточно.`,purgeFailed:`Не вдалося видалити файл.`,emptied:`Файлів остаточно видалено з кошика: {{count}}.`,emptyFailed:`Не вдалося очистити кошик.`,retentionSaved:`Для автоматичного видалення встановлено {{days}} днів.`,retentionFailed:`Не вдалося зберегти налаштування збереження.`,bulkRestored:`Відновлено файлів: {{count}}`,bulkPurged:`Файлів остаточно видалено: {{count}}.`}},libraryPurge:{title:`Очистити старі файли`,headerButton:`Очищення старого`,headerTooltip:`Масове переміщення старих файлів у кошик`,description:`Однією дією перемістіть старі файли з бібліотеки до кошика. Вік файлів з історією друку визначається за датою останнього друку, а файлів, які ще не друкувалися, — за датою вивантаження.`,ageLabel:`Перемістити файли, старші за`,days:`днів`,includeNeverPrinted:`Включати файли, які ніколи не друкувались`,effectsTitle:`Що відбудеться після натискання «Очистити»`,effect1:`Відповідні файли переміщуються в кошик — вони ще не видалені з диска.`,effect2:`Ви можете будь-коли відновити їх із кошика, доки не закінчиться період зберігання.`,effect3:`Після завершення строку зберігання служба очищення кошика остаточно видалить файли з диска.`,effect4:`Файли у зовнішніх (зв’язаних) папках пропускаються — Bambuddy ніколи не видаляє байти, які йому не належать.`,previewLoading:`Перевірка кількості файлів…`,previewFailed:`Не вдалося попередньо переглянути очищення.`,previewSummary:`Файли {{count}} · {{size}} буде переміщено до кошика`,andMore:`…і {{count}} більше`,warning:`Файли в кошику й надалі займають місце, доки не завершиться строк зберігання. Щоб звільнити місце на диску негайно, після цього очистьте кошик.`,confirmCta:`Перемістити до кошика ({{count}})`,purging:`Переміщення в кошик…`,toast:{success:`Переміщено до кошика файлів: {{count}}`,failed:`Не вдалося очистити файли.`}},libraryAutoPurge:{enableLabel:`Автоматичне очищення старих файлів`,enableDescription:`Запускає очищення адміністратора один раз на день. Файли спочатку потрапляють у кошик — вони не видаляються одразу.`,ageLabel:`Автоматичне очищення файлів, старших за`,ageDescription:`Мінімум 7 днів, максимум 10 років. Використовує те саме вікове правило, що й ручна кнопка очищення.`,days:`днів`,includeNeverPrinted:`Включати файли, які ніколи не друкувались`,saveFailed:`Не вдалося зберегти налаштування автоматичного очищення.`},archivePurge:{headerButton:`Очищення старого`,headerTooltip:`Масове видалення старих архівів`,title:`Очистити старі архіви`,description:`Очистити стару історію друку. Кожен архів старіє відповідно до останнього завершення друку — повторний друк архіву оновлює його вік, тому активна робота ніколи не очищається.`,ageLabel:`Видалити архіви, не надруковані в останньому`,days:`днів`,effectsTitle:`Що відбудеться після натискання «Очистити»`,effect1:`Кожен відповідний архів приховано зі списків, а його файли видалено з диска (3MF, ескіз, покадрова зйомка, вихідний 3MF, F3D файл дизайну, фотографії).`,effect2:`Запис архіву залишиться в базі даних, тому «Швидка статистика» й надалі враховуватиме філамент, час, вартість та енергію — як і за типового видалення окремого архіву.`,effect3:`Позначте нижче «Також видалити зі статистики», щоб вилучити внесок цих архівів зі «Швидкої статистики» — так само, як у відповідній опції видалення окремого архіву. Цю дію неможливо скасувати.`,effect4:`Повторний друк архіву оновлює його віковий годинник, тому архіви, якими ви все ще користуєтеся, залишаються в безпеці.`,purgeStatsLabel:`Також видалити зі статистики`,purgeStatsHint:`Вилучає внесок відповідних архівів зі «Швидкої статистики» — філамент, час, вартість та енергію. Якщо параметр вимкнено, статистичні дані зберігаються, а з диска видаляються лише файли.`,previewLoading:`Перевірка кількості архівів, що збігаються…`,previewFailed:`Не вдалося попередньо переглянути очищення.`,previewSummary:`Архіви {{count}} · {{size}} буде видалено`,andMore:`…і {{count}} більше`,warning:`Файли видаляються з диска і не можуть бути відновлені. Перш ніж продовжити, завантажте або додайте до вибраного все, що хочете зберегти.`,confirmCta:`Видалити архіви ({{count}})`,purging:`Видалення…`,toast:{success:`Видалено архівів: {{count}}`,failed:`Не вдалося очистити архіви.`}},archiveAutoPurge:{enableLabel:`Автоматичне очищення старих архівів`,enableDescription:`Один раз на день приховує архіви зі списків і видаляє їх файли з диска, якщо вони не були надруковані в межах порогу. Повторний друк архіву скидає годинник.`,ageLabel:`Автоматичне видалення архівів, не надрукованих в останньому`,ageDescription:`Мінімум 7 днів, максимум 10 років. На основі останнього завершення друку — повторний друк архіву оновлює його вік. Видаляє 3MF, мініатюру, покадрову зйомку, джерело 3MF, F3D і фотографії.`,days:`днів`,purgeStatsLabel:`Також видалити зі статистики`,purgeStatsDescription:`Якщо параметр увімкнено, щоденне очищення також вилучатиме внесок кожного видаленого архіву зі «Швидкої статистики» — філамент, час, вартість та енергію. Типово параметр вимкнено: статистичні дані зберігаються, а з диска видаляються лише файли.`,runNow:`Очистити архіви зараз`,saveFailed:`Не вдалося зберегти налаштування автоматичного очищення.`},cameraTokens:{scope:{camera_stream:`Потік камери`,camwall:`Панель камер`,overlay:`Потокове накладання`},title:`API-токени камери`,navTitle:`API-токени камери`,description:`Довгострокові токени для вбудовування потоку камери в Home Assistant, Frigate, кіоски або інші засоби, яким потрібен постійний URL. Під час створення виберіть область доступу; токен можна відкликати будь-коли.`,loading:`Завантаження…`,confirmRevoke:{title:`Відкликати цей токен?`,body:`Усі пристрої, що використовують «{{name}}», негайно втратять доступ. Цю дію неможливо скасувати.`,cancel:`Скасувати`,confirm:`Відкликати`},create:{scopeLabel:`Область застосування`,hintCameraStream:`Токен потоку камери дає змогу отримувати лише потоки з камер і знімки. Використовуйте його для Home Assistant, Frigate або іншого засобу, що вбудовує одну камеру.`,hintCamWall:`Токен Cam Wall відкриває /camwall на екрані без входу. Він може бачити назву та стан кожного принтера, а також потоки з камери. Він не може бачити імена файлів, адреси чи коди доступу.`,hintOverlay:`Токен потокового накладання відкриває /overlay/{printerId} на екрані без входу — для OBS або будь-якої прямої трансляції. Він дає змогу переглядати потік із камери одного принтера та стан друку в реальному часі, зокрема назву файлу, показану на екрані. Він не надає доступу до адрес чи кодів доступу.`,title:`Створити новий токен`,nameLabel:`Назва токена`,namePlaceholder:`напр. Home Assistant`,daysLabel:`Днів до закінчення терміну дії`,submit:`Створити`,hint:`Максимальний строк дії — 365 днів. Значення токена буде показано лише один раз під час створення — скопіюйте його зараз.`},created:{camWallUrlTitle:`Cam Wall URL для цього дисплея`,camWallUrlHint:`Відкрийте цей URL на потрібному екрані. Будь-хто, хто отримає URL, зможе переглядати панель камер, тому захищайте його як ключ доступу. Щоб негайно припинити доступ із цього екрана, відкличте токен.`,overlayUrlTitle:`Накладання URL для OBS`,overlayUrlHint:`Додайте цей URL в OBS як джерело браузера. Замініть число в /overlay/1 номером принтера з його URL на сторінці «Принтери». Будь-хто, хто отримає URL, зможе переглядати трансляцію, тому захищайте його як ключ доступу. Щоб негайно припинити доступ, відкличте токен.`,title:`Токен створено — скопіюйте його зараз`,warning:`Це єдиний раз, коли токен буде показано. Після закриття цього діалогового вікна переглянути його знову буде неможливо.`,copy:`Копіювати`,dismiss:`Я зберіг токен`},list:{scope:`Область застосування`,myTitle:`Мої токени`,allTitle:`Усі користувачі (перегляд адміністратора)`,empty:`Токенів ще немає.`,name:`Назва`,owner:`Власник`,prefix:`Префікс`,created:`Створено`,expires:`Термін дії закінчується`,lastUsed:`Останнє використання`,revoke:`Відкликати`,expired:`Термін дії минув`},toast:{created:`Токен створено`,createFailed:`Не вдалося створити токен`,revoked:`Токен відкликано`,revokeFailed:`Не вдалося відкликати токен`,loadFailed:`Не вдалося завантажити токени`,copied:`Скопійовано в буфер обміну`,copyFailed:`Не вдалося копіювати — виберіть і скопіюйте вручну`}},forecast:{title:`Прогноз`,noSpools:`Не знайдено активних котушок. Додайте котушки до свого інвентарю, щоб переглянути прогнозні дані.`,noUsageData:`Немає даних про використання — неможливо спроєктувати хронологію запасів.`,sku:`SKU`,material:`матеріал`,stock:`Запас`,dailyRate:`Добове споживання`,daysLeft:`Залишилося днів`,emptyBy:`Вичерпається до`,reorderBy:`Замовити до`,actions:`Дії`,trend:`Тренд`,estimated:`Приблизно`,noData:`Немає даних`,timeframe:`Період`,chartTitle:`Прогнозований запас — топ-5 матеріалів`,dashedLinesROP:`Пунктирні лінії — точки повторного замовлення`,stockLevel:`Рівень запасів`,reorderPoint:`Точка повторного замовлення`,safetyMargin:`Запас безпеки`,trendLegend:`Тенденція (на основі історії, рівень обслуговування 95%)`,estimatedLegend:`Розрахункова (дельта ваги)`,noDataLegend:`Немає даних`,ropLabel:`ROP`,ssLabel:`SS`,safetyStockLegend:`Страховий запас`,stockArrivalLegend:`Надходження запасів`,stockoutLegend:`Дефіцит`,alertCount_one:`Сповіщень: {{count}}`,alertCount_other:`Сповіщень: {{count}}`,order:`Замовлення`,save:`Зберегти`,cancel:`Скасувати`,settingsSaved:`Налаштування збережено`,failedSaveSettings:`Не вдалося зберегти налаштування`,globalLeadTimeSaved:`Загальний строк постачання збережено`,globalLeadTime:`Загальний строк постачання`,globalLeadTimeHint:`Мінімальний строк постачання для розрахунку точки повторного замовлення всіх SKU`,skuLeadTimeOverride:`Інший строк постачання`,skuLeadTimeHint:`0 — використовувати загальний строк. Установіть значення понад 0, щоб перевизначити його для цього SKU.`,safetyMarginLabel:`Запас безпеки`,effectiveLeadTime:`Розрахунковий строк постачання`,effectiveLeadTimeHint:`max(глобальний {{global}}d, SKU {{sku}}d)`,reorderPointHint:`d̄ × LT + страховий запас — замовляйте, коли запас досягне цього рівня`,safetyMarginHint:`Статистичний страховий запас (z=1,65 × σ × √LT) + визначений користувачем буфер`,safetyMarginHintDays:`Буфер додано поверх статистичного страхового запасу.{{approx}}`,safetyMarginHintDaysApprox:` ≈ {{g}} г за поточного рівня споживання.`,safetyMarginHintG:`Буфер фіксованої ваги, доданий поверх статистичного страхового запасу.{{approx}}`,safetyMarginHintGApprox:` ≈ {{days}} дн. за поточного рівня споживання.`,individualSpools:`Окремі котушки`,labelWeight:`Вага за етикеткою`,spoolCount_one:`Котушок: {{count}}`,spoolCount_other:`Котушок: {{count}}`,stockBreakRisk:`Ризик вичерпання запасу`,stockBreakDetail:`Залишилося {{days}} дн.; строк постачання — {{lt}} дн.`,stockBreakBefore:`Запас вичерпається до поповнення`,reorderNow:`Замовити зараз`,reorderTriggerPassed:`Дата замовлення {{date}} минула.`,shoppingList:`Список покупок`,shoppingListItems_one:`(позицій: {{count}})`,shoppingListItems_other:`(позицій: {{count}})`,shoppingListEmpty:`Список покупок порожній. Натисніть значок кошика в будь-якому рядку, щоб додати позиції.`,addToCart:`Додати до списку покупок`,alertsSnoozed:`Вимкнути сповіщення для цього SKU`,alertsEnabled:`Увімкнути сповіщення для цього SKU`,addedToCart:`Додано до списку покупок`,failedAddItem:`Не вдалося додати елемент`,listView:`Список`,logisticsView:`Логістика`,qty:`Кількість`,weight:`Вага`,leadTime:`Строк постачання`,expectedRestock:`Очікуване поповнення запасів`,status:`Статус`,note:`Примітка`,pending:`В очікуванні`,purchased:`Придбано`,received:`Отримано`,markPurchased:`Позначити як придбане`,markReceived:`Позначити як отримане — додає котушки до запасу`,resetToPending:`Скинути до очікування`,remove:`Видалити`,clearAll:`Очистити все`,downloadCsv:`CSV`,addToCartTitle:`Додати до списку покупок`,byQuantity:`За кількістю`,byDuration:`За тривалістю`,numberOfSpools:`Кількість котушок`,lastHowManyDays:`Скільки днів має тривати?`,noUsageQty:`Немає даних про використання — кількість встановлено на 1.`,noteOptional:`Примітка (необов’язково)`,notePlaceholder:`напр. для проєкту X, терміново…`,addNSpools_one:`Додати котушки ({{count}})`,addNSpools_other:`Додати котушки ({{count}})`,onArrival:`Після прибуття`,stockBreakIn:`Запас вичерпається через {{days}} дн.`,stockRunsOutBefore:`Запас закінчиться раніше, ніж мине строк постачання {{lt}} дн.`,atRate:`За споживання {{rate}} г/день потрібно`,moreSpools_one:`Додаткових котушок: {{count}}`,moreSpools_other:`Додаткових котушок: {{count}}`,bridgeGap:`щоб покрити нестачу.`,noReadAccess:`Ви не маєте дозволу переглядати прогнози запасів.`,noWriteAccess:`Ви не маєте дозволу змінювати налаштування прогнозу.`}}}},Tt=[`en`,`de`,`es`,`fr`,`ja`,`it`,`ko`,`pt-BR`,`ru`,`tr`,`uk`,`zh-CN`,`zh-TW`],Et=`bambuddy_appliance_locale_consumed`;De.use(Ct).use(Ke).init({resources:wt,fallbackLng:`en`,supportedLngs:Tt,detection:{order:[`localStorage`,`navigator`,`htmlTag`],lookupLocalStorage:`bambutrack_language`,caches:[`localStorage`]},interpolation:{escapeValue:!1},react:{useSuspense:!1}});function Dt(){if(typeof window>`u`||!window.localStorage)return;let e=window.localStorage;typeof e.getItem!=`function`||typeof e.setItem!=`function`||e.getItem(Et)||fetch(`/api/v1/system/appliance`).then(e=>e.ok?e.json():null).then(t=>{!t||typeof t.locale!=`string`||Tt.includes(t.locale)&&(De.changeLanguage(t.locale),e.setItem(Et,`1`))}).catch(()=>{})}Dt();var Ot=[{code:`en`,name:`English`,nativeName:`English`},{code:`de`,name:`German`,nativeName:`Deutsch`},{code:`es`,name:`Spanish`,nativeName:`Español`},{code:`fr`,name:`French`,nativeName:`Français`},{code:`ja`,name:`Japanese`,nativeName:`日本語`},{code:`it`,name:`Italian`,nativeName:`Italiano`},{code:`ko`,name:`Korean`,nativeName:`한국어`},{code:`pt-BR`,name:`Portuguese (Brazil)`,nativeName:`Português (Brasil)`},{code:`zh-CN`,name:`Chinese (Simplified)`,nativeName:`简体中文`},{code:`zh-TW`,name:`Chinese (Traditional)`,nativeName:`繁體中文`},{code:`tr`,name:`Turkish`,nativeName:`Türkçe`},{code:`ru`,name:`Russian`,nativeName:`Русский`},{code:`uk`,name:`Ukrainian`,nativeName:`Українська`}],kt=`modulepreload`,At=function(e){return`/`+e},jt={},Mt=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}r=o(t.map(t=>{if(t=At(t,n),t in jt)return;jt[t]=!0;let r=t.endsWith(`.css`),i=r?`[rel="stylesheet"]`:``;if(n)for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}else if(document.querySelector(`link[href="${t}"]${i}`))return;let o=document.createElement(`link`);if(o.rel=r?`stylesheet`:kt,r||(o.as=`script`),o.crossOrigin=``,o.href=t,a&&o.setAttribute(`nonce`,a),document.head.appendChild(o),r)return new Promise((e,n)=>{o.addEventListener(`load`,e),o.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},Nt=/^(?:[a-z][a-z0-9+.-]*:|[\\/]{2})/i,Pt=/^[\\/]{2}/;function Ft(e,t){return t+e.replace(/\\/g,`/`)}var It=`popstate`;function Lt(e){return typeof e==`object`&&!!e&&`pathname`in e&&`search`in e&&`hash`in e&&`state`in e&&`key`in e}function G(e={}){function t(e,t){let n=t.state?.masked,{pathname:r,search:i,hash:a}=n||e.location;return Ht(``,{pathname:r,search:i,hash:a},t.state&&t.state.usr||null,t.state&&t.state.key||`default`,n?{pathname:e.location.pathname,search:e.location.search,hash:e.location.hash}:void 0)}function n(e,t){return typeof t==`string`?t:Ut(t)}return Gt(t,n,null,e)}function Rt(e,t){if(e===!1||e==null)throw Error(t)}function zt(e,t){if(!e){typeof console<`u`&&console.warn(t);try{throw Error(t)}catch{}}}function Bt(){return Math.random().toString(36).substring(2,10)}function Vt(e,t){return{usr:e.state,key:e.key,idx:t,masked:e.mask?{pathname:e.pathname,search:e.search,hash:e.hash}:void 0}}function Ht(e,t,n=null,r,i){return{pathname:typeof e==`string`?e:e.pathname,search:``,hash:``,...typeof t==`string`?Wt(t):t,state:n,key:t&&t.key||r||Bt(),mask:i}}function Ut({pathname:e=`/`,search:t=``,hash:n=``}){return t&&t!==`?`&&(e+=t.charAt(0)===`?`?t:`?`+t),n&&n!==`#`&&(e+=n.charAt(0)===`#`?n:`#`+n),e}function Wt(e){let t={};if(e){let n=e.indexOf(`#`);n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf(`?`);r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function Gt(e,t,n,r={}){let{window:i=document.defaultView,v5Compat:a=!1}=r,o=i.history,s=`POP`,c=null,l=u();l??(l=0,o.replaceState({...o.state,idx:l},``));function u(){return(o.state||{idx:null}).idx}function d(){s=`POP`;let e=u(),t=e==null?null:e-l;l=e,c&&c({action:s,location:h.location,delta:t})}function f(e,t){s=`PUSH`;let r=Lt(e)?e:Ht(h.location,e,t);n&&n(r,e),l=u()+1;let d=Vt(r,l),f=h.createHref(r.mask||r);try{o.pushState(d,``,f)}catch(e){if(e instanceof DOMException&&e.name===`DataCloneError`)throw e;i.location.assign(f)}a&&c&&c({action:s,location:h.location,delta:1})}function p(e,t){s=`REPLACE`;let r=Lt(e)?e:Ht(h.location,e,t);n&&n(r,e),l=u();let i=Vt(r,l),d=h.createHref(r.mask||r);o.replaceState(i,``,d),a&&c&&c({action:s,location:h.location,delta:0})}function m(e){return Kt(i,e)}let h={get action(){return s},get location(){return e(i,o)},listen(e){if(c)throw Error(`A history only accepts one active listener`);return i.addEventListener(It,d),c=e,()=>{i.removeEventListener(It,d),c=null}},createHref(e){return t(i,e)},createURL:m,encodeLocation(e){let t=m(e);return{pathname:t.pathname,search:t.search,hash:t.hash}},push:f,replace:p,go(e){return o.go(e)}};return h}function Kt(e,t,n=!1){let r=`http://localhost`;e&&(r=e.location.origin===`null`?e.location.href:e.location.origin),Rt(r,`No window.location.(origin|href) available to create URL`);let i=typeof t==`string`?t:Ut(t);return i=i.replace(/ $/,`%20`),!n&&Pt.test(i)&&(i=r+i),new URL(i,r)}function qt(e,t,n=`/`){return Jt(e,t,n,!1)}function Jt(e,t,n,r,i){let a=hn((typeof t==`string`?Wt(t):t).pathname||`/`,n);if(a==null)return null;let o=i??Xt(e),s=null,c=mn(a);for(let e=0;s==null&&e{let c={relativePath:s===void 0?e.path||``:s,caseSensitive:e.caseSensitive===!0,childrenIndex:a,route:e};if(c.relativePath.startsWith(`/`)){if(!c.relativePath.startsWith(r)&&o)return;Rt(c.relativePath.startsWith(r),`Absolute route path "${c.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),c.relativePath=c.relativePath.slice(r.length)}let l=Cn([r,c.relativePath]),u=n.concat(c);e.children&&e.children.length>0&&(Rt(e.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${l}".`),Zt(e.children,t,u,l,o)),!(e.path==null&&!e.index)&&t.push({path:l,score:cn(l,e.index),routesMeta:u.map((e,t)=>{let[n,r]=pn(e.relativePath,e.caseSensitive,t===u.length-1);return{...e,matcher:n,compiledParams:r}})})};return e.forEach((e,t)=>{if(e.path===``||!e.path?.includes(`?`))a(e,t);else for(let n of Qt(e.path))a(e,t,!0,n)}),t}function Qt(e){let t=e.split(`/`);if(t.length===0)return[];let[n,...r]=t,i=n.endsWith(`?`),a=n.replace(/\?$/,``);if(r.length===0)return i?[a,``]:[a];let o=Qt(r.join(`/`)),s=[];return s.push(...o.map(e=>e===``?a:[a,e].join(`/`))),i&&s.push(...o),s.map(t=>e.startsWith(`/`)&&t===``?`/`:t)}function $t(e){e.sort((e,t)=>e.score===t.score?ln(e.routesMeta.map(e=>e.childrenIndex),t.routesMeta.map(e=>e.childrenIndex)):t.score-e.score)}var en=/^:[\w-]+$/,tn=3,nn=2,rn=1,an=10,on=-2,sn=e=>e===`*`;function cn(e,t){let n=e.split(`/`),r=n.length;return n.some(sn)&&(r+=on),t&&(r+=nn),n.filter(e=>!sn(e)).reduce((e,t)=>e+(en.test(t)?tn:t===``?rn:an),r)}function ln(e,t){return e.length===t.length&&e.slice(0,-1).every((e,n)=>e===t[n])?e[e.length-1]-t[t.length-1]:0}function un(e,t,n=!1){let{routesMeta:r}=e,i={},a=`/`,o=[];for(let e=0;e{if(t===`*`){let e=s[r]||``;o=a.slice(0,a.length-e.length).replace(/(.)\/+$/,`$1`)}let i=s[r];return n&&!i?e[t]=void 0:e[t]=(i||``).replace(/%2F/g,`/`),e},{}),pathname:a,pathnameBase:o,pattern:e}}function pn(e,t=!1,n=!0){zt(e===`*`||!e.endsWith(`*`)||e.endsWith(`/*`),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,`/*`)}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,`/*`)}".`);let r=[],i=`^`+e.replace(/\/*\*?$/,``).replace(/^\/*/,`/`).replace(/[\\.*+^${}|()[\]]/g,`\\$&`).replace(/\/:([\w-]+)(\?)?/g,(e,t,n,i,a)=>{if(r.push({paramName:t,isOptional:n!=null}),n){let t=a.charAt(i+e.length);return t&&t!==`/`?`/([^\\/]*)`:`(?:/([^\\/]*))?`}return`/([^\\/]+)`}).replace(/\/([\w-]+)\?(\/|$)/g,`(/$1)?$2`);return e.endsWith(`*`)?(r.push({paramName:`*`}),i+=e===`*`||e===`/*`?`(.*)$`:`(?:\\/(.+)|\\/*)$`):n?i+=`\\/*$`:e!==``&&e!==`/`&&(i+=`(?:(?=\\/|$))`),[new RegExp(i,t?void 0:`i`),r]}function mn(e){try{return e.split(`/`).map(e=>decodeURIComponent(e).replace(/\//g,`%2F`)).join(`/`)}catch(t){return zt(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function hn(e,t){if(t===`/`)return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith(`/`)?t.length-1:t.length,r=e.charAt(n);return r&&r!==`/`?null:e.slice(n)||`/`}function gn(e,t=`/`){let{pathname:n,search:r=``,hash:i=``}=typeof e==`string`?Wt(e):e,a;return n?(n=Sn(n),a=n.startsWith(`/`)?_n(n.substring(1),`/`):_n(n,t)):a=t,{pathname:a,search:En(r),hash:Dn(i)}}function _n(e,t){let n=wn(t).split(`/`);return e.split(`/`).forEach(e=>{e===`..`?n.length>1&&n.pop():e!==`.`&&n.push(e)}),n.length>1?n.join(`/`):`/`}function vn(e,t,n,r){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function yn(e){return e.filter((e,t)=>t===0||e.route.path&&e.route.path.length>0)}function bn(e){let t=yn(e);return t.map((e,n)=>n===t.length-1?e.pathname:e.pathnameBase)}function xn(e,t,n,r=!1){let i;typeof e==`string`?i=Wt(e):(i={...e},Rt(!i.pathname||!i.pathname.includes(`?`),vn(`?`,`pathname`,`search`,i)),Rt(!i.pathname||!i.pathname.includes(`#`),vn(`#`,`pathname`,`hash`,i)),Rt(!i.search||!i.search.includes(`#`),vn(`#`,`search`,`hash`,i)));let a=e===``||i.pathname===``,o=a?`/`:i.pathname,s;if(o==null)s=n;else{let e=t.length-1;if(!r&&o.startsWith(`..`)){let t=o.split(`/`);for(;t[0]===`..`;)t.shift(),--e;i.pathname=t.join(`/`)}s=e>=0?t[e]:`/`}let c=gn(i,s),l=o&&o!==`/`&&o.endsWith(`/`),u=(a||o===`.`)&&n.endsWith(`/`);return!c.pathname.endsWith(`/`)&&(l||u)&&(c.pathname+=`/`),c}var Sn=e=>e.replace(/[\\/]{2,}/g,`/`),Cn=e=>Sn(e.join(`/`)),wn=e=>e.replace(/\/+$/,``),Tn=e=>wn(e).replace(/^\/*/,`/`),En=e=>!e||e===`?`?``:e.startsWith(`?`)?e:`?`+e,Dn=e=>!e||e===`#`?``:e.startsWith(`#`)?e:`#`+e,On=class{constructor(e,t,n,r=!1){this.status=e,this.statusText=t||``,this.internal=r,n instanceof Error?(this.data=n.toString(),this.error=n):this.data=n}};function kn(e){return e!=null&&typeof e.status==`number`&&typeof e.statusText==`string`&&typeof e.internal==`boolean`&&`data`in e}function An(e){return Cn(e.map(e=>e.route.path).filter(Boolean))||`/`}var jn=typeof window<`u`&&window.document!==void 0&&window.document.createElement!==void 0;function Mn(e,t){let n=e;if(typeof n!=`string`||!Nt.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let r=n,i=!1;if(jn)try{let e=new URL(window.location.href),r=Pt.test(n)?new URL(Ft(n,e.protocol)):new URL(n),a=hn(r.pathname,t);r.origin===e.origin&&a!=null?n=a+r.search+r.hash:i=!0}catch{zt(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:r,isExternal:i,to:n}}Object.getOwnPropertyNames(Object.prototype).sort().join(`\0`);var Nn=[`POST`,`PUT`,`PATCH`,`DELETE`];new Set(Nn);var Pn=[`GET`,...Nn];new Set(Pn);var Fn=[`about:`,`blob:`,`chrome:`,`chrome-untrusted:`,`content:`,`data:`,`devtools:`,`file:`,`filesystem:`,`javascript:`];function In(e){try{return Fn.includes(new URL(e).protocol)}catch{return!1}}var Ln=y.createContext(null);Ln.displayName=`DataRouter`;var Rn=y.createContext(null);Rn.displayName=`DataRouterState`;var zn=y.createContext(!1);function Bn(){return y.useContext(zn)}var Vn=y.createContext({isTransitioning:!1});Vn.displayName=`ViewTransition`;var Hn=y.createContext(new Map);Hn.displayName=`Fetchers`;var Un=y.createContext(null);Un.displayName=`Await`;var Wn=y.createContext(null);Wn.displayName=`Navigation`;var Gn=y.createContext(null);Gn.displayName=`Location`;var Kn=y.createContext({outlet:null,matches:[],isDataRoute:!1});Kn.displayName=`Route`;var qn=y.createContext(null);qn.displayName=`RouteError`;var Jn=`REACT_ROUTER_ERROR`,Yn=`REDIRECT`,Xn=`ROUTE_ERROR_RESPONSE`;function Zn(e){if(e.startsWith(`${Jn}:${Yn}:{`))try{let t=JSON.parse(e.slice(28));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`&&typeof t.location==`string`&&typeof t.reloadDocument==`boolean`&&typeof t.replace==`boolean`)return t}catch{}}function Qn(e){if(e.startsWith(`${Jn}:${Xn}:{`))try{let t=JSON.parse(e.slice(40));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`)return new On(t.status,t.statusText,t.data)}catch{}}function $n(e,{relative:t}={}){Rt(er(),`useHref() may be used only in the context of a component.`);let{basename:n,navigator:r}=y.useContext(Wn),{hash:i,pathname:a,search:o}=ur(e,{relative:t}),s=a;return n!==`/`&&(s=a===`/`?n:Cn([n,a])),r.createHref({pathname:s,search:o,hash:i})}function er(){return y.useContext(Gn)!=null}function tr(){return Rt(er(),`useLocation() may be used only in the context of a component.`),y.useContext(Gn).location}var nr=`You should call navigate() in a React.useEffect(), not when your component is first rendered.`;function rr(e){y.useContext(Wn).static||y.useLayoutEffect(e)}function ir(){let{isDataRoute:e}=y.useContext(Kn);return e?kr():ar()}function ar(){Rt(er(),`useNavigate() may be used only in the context of a component.`);let e=y.useContext(Ln),{basename:t,navigator:n}=y.useContext(Wn),{matches:r}=y.useContext(Kn),{pathname:i}=tr(),a=JSON.stringify(bn(r)),o=y.useRef(!1);return rr(()=>{o.current=!0}),y.useCallback((r,s={})=>{if(zt(o.current,nr),!o.current)return;if(typeof r==`number`){n.go(r);return}let c=xn(r,JSON.parse(a),i,s.relative===`path`);e==null&&t!==`/`&&(c.pathname=c.pathname===`/`?t:Cn([t,c.pathname])),(s.replace?n.replace:n.push)(c,s.state,s)},[t,n,a,i,e])}var or=y.createContext(null);function sr(){return y.useContext(or)}function cr(e){let t=y.useContext(Kn).outlet;return y.useMemo(()=>t&&y.createElement(or.Provider,{value:e},t),[t,e])}function lr(){let{matches:e}=y.useContext(Kn);return e[e.length-1]?.params??{}}function ur(e,{relative:t}={}){let{matches:n}=y.useContext(Kn),{pathname:r}=tr(),i=JSON.stringify(bn(n));return y.useMemo(()=>xn(e,JSON.parse(i),r,t===`path`),[e,i,r,t])}function dr(e,t){return fr(e,t)}function fr(e,t,n){Rt(er(),`useRoutes() may be used only in the context of a component.`);let{navigator:r}=y.useContext(Wn),{matches:i}=y.useContext(Kn),a=i[i.length-1],o=a?a.params:{},s=a?a.pathname:`/`,c=a?a.pathnameBase:`/`,l=a&&a.route;{let e=l&&l.path||``;jr(s,!l||e.endsWith(`*`)||e.endsWith(`*?`),`You rendered descendant (or called \`useRoutes()\`) at "${s}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. +Значення «увімкнено»: точний рядок, що означає стан «увімкнено». Залиште поле порожнім для автоматичного визначення (ON, true, 1).`,restControl:`Керування`,restOnUrl:`Увімкнути URL`,restOffUrl:`Вимкнути URL`,restOnBody:`Тіло запиту ввімкнення`,restOffBody:`Тіло запиту вимкнення`,restMethod:`Метод HTTP`,restHeaders:`Спеціальні заголовки (JSON)`,restStatusUrl:`URL стану`,restStatusPath:`Шлях JSON до стану`,restStatusOnValue:`Значення «увімкнено»`,restPowerUrl:`URL даних про потужність`,restPowerPath:`Шлях JSON до потужності`,restPowerMultiplier:`Множник потужності`,restEnergyUrl:`URL даних про енергію`,restEnergyPath:`Шлях JSON до споживання за сьогодні`,restEnergyTotalPath:`Шлях JSON до загального споживання`,restEnergyTotalMultiplier:`Множник загального споживання`,restEnergyTotalPathHint:`наприклад, aenergy.total`,restEnergyTotalHint:`Багато розеток, зокрема всі моделі Shelly, повідомляють лише загальний лічильник споживання, який ніколи не скидається. Його слід указувати саме тут, а не в полі вище: якщо трактувати це значення як споживання за сьогодні, воно не скинеться опівночі, а показники «Учора» та «Усього» залишатимуться порожніми. Bambuddy сам обчислює показники за сьогодні й учора на основі цього лічильника; для їх появи потрібні один-два дні даних. Shelly передає значення у ват-годинах, тому використовуйте множник 0.001.`,restEnergyMultiplier:`Множник енергії`,restUrlRequired:`Для REST-розетки потрібно вказати принаймні один URL — для ввімкнення або вимкнення.`,restHeadersHint:`наприклад, {"Authorization": "Bearer your-token"}`,restBodyHint:`напр. ON, {"state": "on"}`,restStatusHint:`URL для опитування поточного стану`,restPathHint:`наприклад, state або data.power.status`,restPowerUrlHint:`Окремий URL для даних про потужність; якщо поле порожнє, використовується URL стану`,restEnergyUrlHint:`Окремий URL для даних про енергію; якщо поле порожнє, використовується URL стану`,restEnergyHint:`Для кожного значення можна використовувати окремий URL або URL стану як резервний. Для перетворення одиниць використовуйте множники, наприклад 0.001 для перетворення Wh у kWh.`,testConnection:`Тестове підключення`,connectionSuccess:`Підключення успішне`,noSwitchesInSwitchbar:`На панелі перемикачів немає розеток`,enableSwitchbarHint:`Увімкніть «Показувати на панелі перемикачів» у розділі «Налаштування → Розумні розетки».`},notifications:{providerTypes:{callmebot:`CallMeBot/WhatsApp`,ntfy:`ntfy`,pushover:`Pushover`,telegram:`Telegram`,email:`Електронна пошта`,discord:`Discord`,webhook:`Webhook`,homeassistant:`Home Assistant`,bark:`Bark`},providerDescriptions:{email:`Сповіщення електронною поштою SMTP`,telegram:`Сповіщення через бота Telegram.`,discord:`Надіслати на канал Discord через webhook`,ntfy:`Безкоштовні push-сповіщення з можливістю самостійного розгортання`,pushover:`Прості та надійні push-повідомлення`,callmebot:`Безкоштовні сповіщення WhatsApp через CallMeBot`,webhook:`Універсальний HTTP POST-запит на будь-який URL`,homeassistant:`Постійні сповіщення на інформаційній панелі Home Assistant.`,bark:`Push-сповіщення iOS через Bark із можливістю самостійного розгортання`},lastSuccess:`Останнє успішне надсилання: {{date}}`,error:`Помилка`,printer:`Принтер:`,allPrinters:`Всі принтери`,sendTestNotification:`Надіслати тестове сповіщення`,eventSettings:`Налаштування події`,enabled:`Увімкнено`,sendFromProvider:`Надсилати сповіщення від цього постачальника`,printEvents:`Події друку`,printerStatus:`Стан принтера`,amsAlarms:`Попередження AMS`,amsHtAlarms:`Попередження AMS-HT`,printQueue:`Черга друку`,start:`Початок`,plateCheck:`Перевірка пластини`,complete:`Завершено`,failed:`Помилка`,stopped:`Зупинено`,progress:`Прогрес`,offline:`Не в мережі`,lowFilament:`Закінчується філамент`,maintenance:`Технічне обслуговування`,amsHumidity:`AMS Вологість`,amsTemp:`AMS Темп`,amsHtHumidity:`AMS-HT Вологість`,amsHtTemp:`Температура AMS-HT`,bedCooled:`Стіл охолов`,firstLayer:`Перший шар`,quiet:`Тихо`,digest:`Дайджест {{time}}`,printStarted:`Друк розпочато`,plateNotEmpty:`Друкарська пластина не порожня`,plateNotEmptyDescription:`Перед друком виявлено об’єкти`,plateClearRequired:`Потрібно очистити пластину`,plateClearRequiredDescription:`Друк завершено, черга очікує підтвердження очищення пластини`,plateClear:`Очищення пластини`,printCompleted:`Друк завершено`,bedCooledLabel:`Стіл охолов`,bedCooledDescription:`Після друку стіл охолов нижче заданого порога`,firstLayerCompleteLabel:`Перший шар завершено`,firstLayerCompleteDescription:`Сповістити зі знімком після завершення першого шару`,missingSpoolAssignmentLabel:`Відсутнє призначення котушки`,missingSpoolAssignmentDescription:`Сповіщати, коли починається друк і для необхідних лотків не призначено котушку`,printFailed:`Помилка друку`,printStopped:`Друк зупинено`,progressMilestones:`Віхи прогресу`,progressMilestonesDescription:`Сповіщати на 25%, 50%, 75%`,printerOffline:`Принтер не в мережі`,printerError:`Помилка принтера`,aiFailureDetection:`Виявлення помилок за допомогою ШІ`,aiFailureDetectionDescription:`Сповіщати, коли ШІ Obico виявляє можливу помилку друку`,lowFilamentLabel:`Закінчується філамент`,maintenanceDue:`Настав час технічного обслуговування`,maintenanceDueDescription:`Повідомити, коли потрібне обслуговування`,amsHumidityHigh:`AMS Висока вологість`,amsHumidityHighDescription:`Звичайна AMS вологість перевищує порогове значення`,amsTemperatureHigh:`AMS Висока температура`,amsTemperatureHighDescription:`Звичайна AMS температура перевищує порогове значення`,amsHtHumidityHigh:`AMS-HT Висока вологість`,amsHtHumidityHighDescription:`AMS-HT вологість перевищує порогове значення`,amsHtTemperatureHigh:`Висока температура AMS-HT`,amsHtTemperatureHighDescription:`Температура AMS-HT перевищує порогове значення`,inventoryAlerts:`Сповіщення про запаси`,stockReorderAlert:`Сповіщення про необхідність поповнення`,stockReorderAlertDescription:`Запас SKU досяг точки повторного замовлення`,stockBreakAlert:`Сповіщення про ризик вичерпання запасу`,stockBreakAlertDescription:`Запас закінчиться до того, як надійде поповнення`,jobAdded:`Завдання додано`,jobAddedDescription:`Завдання додано до черги`,jobAssigned:`Завдання призначено`,jobAssignedDescription:`Завдання на основі моделі, призначене принтеру`,jobStarted:`Завдання розпочато`,jobStartedDescription:`Розпочато друк завдання черги`,jobWaiting:`Завдання очікує`,jobWaitingDescription:`Завдання очікує на філамент або принтер`,jobSkipped:`Завдання пропущено`,jobSkippedDescription:`Завдання пропущено (попереднє не вдалося)`,jobFailed:`Помилка завдання`,jobFailedDescription:`Не вдалося розпочати завдання`,queueComplete:`Черга завершена`,queueCompleteDescription:`Усі завдання черги завершено`,quietHours:`Тихі години`,noNotificationsDuring:`Жодних сповіщень у ці години`,editProviderToChangeQuietHours:`Змініть постачальника, щоб змінити години тиші`,dailyDigest:`Щоденний дайджест`,batchNotifications:`Групуйте сповіщення в єдиний щоденний підсумок`,sendAt:`Надсилати о {{time}}`,editProviderToChangeDigestTime:`Відредагуйте постачальника, щоб змінити час дайджесту`,edit:`Редагувати`,deleteProvider:`Видалити постачальника сповіщень`,deleteConfirm:`Видалити «{{name}}»? Цю дію неможливо скасувати.`,delete:`Видалити`,addTitle:`Додати постачальника сповіщень`,editTitle:`Редагувати постачальника сповіщень`,nameLabel:`Назва *`,namePlaceholder:`Мої сповіщення`,providerTypeLabel:`Тип постачальника *`,configuration:`Конфігурація`,testConfiguration:`Перевірити конфігурацію`,printerFilter:`Фільтр принтера`,onlyFromPrinter:`Надсилати лише сповіщення про події з цього принтера`,quietHoursDnd:`Тихі години (не турбувати)`,quietStart:`Початок`,quietEnd:`Кінець`,dailyDigestLabel:`Щоденний дайджест`,sendDigestAt:`Надсилати дайджест о`,digestCollected:`Події буде зібрано й надіслано в цей час одним зведенням`,notificationEvents:`Події сповіщень`,progressPercent:`(25%, 50%, 75%)`,bedCooledAfterPrint:`(після завершення друку)`,eventPriority:{sectionTitle:`Пріоритет ntfy`,helpNtfy:`Виберіть пріоритет для кожної ввімкненої події. ntfy використовує їх для ескалації сповіщень (звук, видимість, поведінка push). Для рівнів, які тут не встановлено, використовується сервер ntfy за замовчуванням.`,min:`Мін`,low:`Низький`,default:`За замовчуванням`,high:`Високий`,urgent:`Терміново`},cancel:`Скасувати`,save:`зберегти`,add:`додати`,nameRequired:`Необхідно вказати ім’я`,fieldRequired:`{{field}} — обов’язкове поле.`,haDataInvalid:`Поле «Дані» має містити дійсний об’єкт JSON, наприклад {"priority": "high", "ttl": 0}`,phoneNumber:`Номер телефону`,apiKey:`Ключ API`,serverUrl:`Сервер URL`,topic:`Тема`,authToken:`Токен авторизації`,userKey:`Ключ користувача`,appToken:`Токен застосунку`,priority:`Пріоритет`,pushoverRetry:`Інтервал повторення екстреного сповіщення (с)`,pushoverExpire:`Термін дії екстреного сповіщення (с)`,botToken:`Токен бота`,chatId:`Ідентифікатор чату`,telegramThreadId:`ID теми форуму`,telegramThreadIdHelp:`Необов'язково. Надсилає в конкретну тему форум-групи — останнє число у посиланні на тему (t.me/c/.../25). Залиште порожнім для теми General.`,telegramThreadIdInvalid:`ID теми форуму має бути числом.`,smtpServer:`Сервер SMTP`,smtpPort:`Порт SMTP`,security:`Безпека`,authentication:`Автентифікація`,username:`Ім’я користувача`,password:`Пароль`,fromEmail:`Адреса відправника`,toEmail:`Адреса одержувача`,webhookUrl:`Webhook URL`,payloadFormat:`Формат корисного навантаження`,authorization:`Авторизація`,titleFieldName:`Назва поля заголовка`,messageFieldName:`Назва поля повідомлення`,editTemplate:`Редагувати шаблон: {{name}}`,titleLabel:`Заголовок`,bodyLabel:`Текст`,titlePlaceholder:`Назва сповіщення...`,bodyPlaceholder:`Текст сповіщення...`,availableVariables:`Доступні змінні`,clickToInsert:`Натисніть, щоб вставити в текст у позиції курсора`,livePreview:`Попередній перегляд`,hide:`Сховати`,show:`Показати`,loadingPreview:`Завантаження попереднього перегляду...`,enterTemplateContent:`Введіть вміст шаблону, щоб побачити попередній перегляд`,titlePreview:`Назва:`,bodyPreview:`Текст:`,resetToDefault:`Відновити типові значення`,titleRequired:`Необхідно вказати назву`,bodyRequired:`Текст є обов’язковим`,notificationLog:`Журнал повідомлень`,showFailedOnly:`Лише невдалі`,last24Hours:`Останні 24 години`,last7Days:`Останні 7 днів`,last30Days:`Останні 30 днів`,last90Days:`Останні 90 днів`,justNow:`Щойно`,noFailedNotifications:`Немає невдалих сповіщень`,noNotificationsLogged:`Сповіщення не зареєстровано`,unknownProvider:`Невідомий постачальник`,logTitle:`Назва`,logMessage:`повідомлення`,logError:`Помилка`,logProvider:`Постачальник: {{type}}`,logTime:`Час: {{time}}`,refresh:`Оновити`,clearOld:`Очистити старі`,statsSummary:`За останні {{days}} дн.:`,statsNotifications:`сповіщення`,statsSent:`{{count}} надіслано`,statsFailed:`не вдалося надіслати: {{count}}`,eventTypes:{print_start:`Друк розпочато`,print_complete:`Друк завершено`,print_failed:`Помилка друку`,print_stopped:`Друк зупинено`,print_progress:`Прогрес`,printer_offline:`Принтер не в мережі`,printer_error:`Помилка принтера`,filament_low:`Закінчується філамент`,maintenance_due:`Технічне обслуговування`,test:`Тест`},userEmail:{title:`Сповіщення`,emailNotifications:`Сповіщення електронною поштою`,emailNotificationsDesc:`Отримуйте сповіщення електронною поштою про власні завдання друку. Електронні листи надсилаються за допомогою системних параметрів SMTP, налаштованих у розширеній автентифікації.`,sendingTo:`Сповіщення будуть надіслані на адресу`,noEmailWarning:`У вашому обліковому записі немає адреси електронної пошти. Зверніться до адміністратора, щоб її додати.`,printJobNotifications:`Повідомлення про завдання друку`,printJobNotificationsDesc:`Виберіть, які події викликають сповіщення електронною поштою про завдання друку, які ви надсилаєте.`,printJobStarts:`Початок завдання друку`,printJobStartsDesc:`Отримуйте сповіщення, коли розпочнеться ваше завдання друку.`,printJobFinishes:`Завершення завдання друку`,printJobFinishesDesc:`Отримуйте сповіщення, коли ваше завдання друку буде успішно завершено.`,printErrors:`Помилки друку`,printErrorsDesc:`Отримуйте сповіщення, якщо завдання друку завершується невдало або під час нього виникає помилка.`,printJobStops:`Зупинення завдання друку`,printJobStopsDesc:`Отримуйте сповіщення, коли ваше завдання друку скасовано або зупинено.`,saveSuccess:`Параметри сповіщень збережено.`,saveError:`Не вдалося зберегти налаштування сповіщень.`}},richTextEditor:{bold:`жирний`,italic:`Курсив`,underline:`Підкреслити`,bulletList:`Список маркерів`,numberedList:`Нумерований список`,alignLeft:`Вирівняти по лівому краю`,alignCenter:`Вирівняти по центру`,alignRight:`Вирівняти праворуч`,addLink:`Додати посилання`,removeLink:`Видалити посилання`},externalLinks:{title:`Посилання на бічній панелі`,sidebarLayout:`Бічна панель`,sidebarLayoutDescription:`Показуйте або приховуйте вбудовані сторінки, додавайте зовнішні посилання та перетягуйте елементи, щоб змінити порядок навігації на бічній панелі.`,systemPages:`Bambuddy сторінок`,externalLinks:`Зовнішні посилання`,visibleInSidebar:`Видно на бічній панелі`,hiddenFromSidebar:`Приховано від бічної панелі`,requiredInSidebar:`Обов’язково на бічній панелі`,hidePage:`Приховати сторінку`,showPage:`Показати сторінку`,settingsCannotBeHidden:`Налаштування не можна приховати`,noLinksConfigured:`Зовнішні посилання не налаштовано`,deleteLink:`Видалити посилання`,removeCustomIcon:`Видалити спеціальний значок`,openInNewTab:`Відкрити в новій вкладці`,placeholders:{linkName:`Моє посилання`}},keyboardShortcuts:{title:`Комбінації клавіш`,navigation:`Навігація`,archivesSection:`Архіви`,kProfilesSection:`K-профілі`,generalSection:`Загальний`,shortcuts:{goToPrinters:`Перейдіть до Принтери`,goToArchives:`Перейдіть до архіву`,goToQueue:`Перейдіть до черги`,goToStats:`Перейти до статистики`,goToProfiles:`Перейдіть до Cloud Profiles`,goToSettings:`Перейдіть до Налаштувань`,focusSearch:`Пошук по фокусу`,openUploadModal:`Відкрити вікно вивантаження`,clearSelection:`Очистити виділення / розмити введення`,contextMenu:`Контекстне меню на картках`,refreshProfiles:`Оновити профілі`,newProfile:`Новий профіль`,exitSelectionMode:`Вийти з режиму вибору`,showHelp:`Покажіть цю довідку`},footer:`Натисніть Esc або клацніть зовні, щоб закрити`},notificationLog:{title:`Журнал повідомлень`,events:{printStarted:`Друк розпочато`,printComplete:`Друк завершено`,printFailed:`Помилка друку`,printStopped:`Друк зупинено`,progress:`Прогрес`,printerOffline:`Принтер не в мережі`,printerError:`Помилка принтера`,lowFilament:`Закінчується філамент`,maintenanceDue:`Технічне обслуговування`,test:`Тест`},timeAgo:{justNow:`Просто зараз`,minutesAgo:`{{minutes}}хв тому`,hoursAgo:`{{hours}} год тому`}},restoreBackup:{title:`Відновити резервну копію`,restoring:`Відновлення...`,restoreComplete:`Відновлення завершено`,restoreFailed:`Не вдалося відновити`,importSettings:`Імпорт налаштувань із файлу резервної копії`,pleaseWait:`Зачекайте, поки ваші дані відновляться`,clickToSelect:`Натисніть, щоб вибрати файл резервної копії (.json або .zip)`,howDuplicateHandling:`Як працює обробка дублікатів:`,categories:{printers:`Принтери`,smartPlugs:`Розумні розетки`,notificationProviders:`Постачальники сповіщень`,filaments:`філаменти`,archives:`Архіви`,pendingUploads:`Вивантаження, що очікують`,settingsTemplates:`Налаштування та шаблони`},matchingInfo:{printers:`відповідає серійному номеру`,smartPlugs:`збігається з адресою IP.`,notificationProviders:`відповідність за назвою`,filaments:`відповідність за назвою + типом + брендом`,archives:`відповідає хешу вмісту`,pendingUploads:`відповідає імені файлу`,settingsTemplates:`завжди перезаписується`},replaceExisting:`Замінити існуючі дані`,keepExisting:`Зберегти наявні дані`,replaceDescription:`Замінити елементи, які вже існують, резервними копіями`,keepDescription:`Відновлюйте лише елементи, яких ще не існує`,caution:`Увага:`,cautionText:`Під час перезапису поточні конфігурації буде замінено даними з резервної копії. З міркувань безпеки коди доступу до принтерів ніколи не перезаписуються.`,itemsRestored:`Елементів відновлено`,itemsSkipped:`Елементи пропущені`,restored:`Відновлено`,skipped:`Пропущено (вже існує)`,filesLabel:`Файли (3MF, мініатюри тощо)`,newApiKeysGenerated:`Створено нові API ключі`,newApiKeysWarning:`Ці ключі буде показано лише один раз. Скопіюйте їх зараз!`,processingBackup:`Обробка файлу резервної копії...`,noDataFound:`У файлі резервної копії не знайдено даних для відновлення.`,failedToRestore:`Не вдалося відновити резервну копію. Будь ласка, перевірте формат файлу.`},backupExport:{title:`Експорт резервної копії`,selectData:`Вибрати дані для включення`,selectAll:`Вибрати усі`,selectNone:`Вибрати Немає`,categoryDescriptions:{settings:`Мова, тема, параметри оновлення`,notifications:`ntfy, Pushover, Discord тощо.`,templates:`Користувацькі шаблони повідомлень`,smartPlugs:`Конфігурації розетки Tasmota.`,externalLinks:`Посилання на бічній панелі на зовнішні служби`,printers:`Інформація про принтер (без кодів доступу)`,plateDetection:`Еталонні зображення порожньої пластини`,filaments:`Види та вартість філаменти`,maintenance:`Спеціальні графіки технічного обслуговування`,archives:`Усі дані для друку + файли (3MF, мініатюри, фотографії)`,projects:`Проєкти, елементи специфікації та вкладення`,pendingUploads:`Вивантаження на віртуальний принтер очікують на розгляд`,apiKeys:`Ключі Webhook API (нові ключі створюються під час імпорту)`},requiresPrinters:`Необхідно вибрати принтери`,zipFileWarning:`Буде створено файл ZIP.`,zipFileDescription:`До архіву ввійдуть усі файли 3MF, мініатюри, таймлапси та фотографії. Створення може тривати певний час, а отриманий файл може мати великий розмір.`,includeAccessCodes:`Додати коди доступу`,includeAccessCodesDescription:`Для перенесення на іншу машину`,includeAccessCodesWarning:`Коди доступу буде збережено у відкритому вигляді. Надійно захистіть файл резервної копії!`,categoriesSelected:`Вибрано категорії {{selectedCount}}.`},pendingUploads:{placeholders:{notes:`Додайте примітки щодо цього друку...`},discardUpload:`Відхилити вивантаження`,archiveAllUploads:`Архівувати всі вивантаження`,discardAllUploads:`Відхилити всі вивантаження`,archive:`Архів`,timeAgo:{justNow:`Просто зараз`,minutesAgo:`{{minutes}}хв тому`,hoursAgo:`{{hours}} год тому`,daysAgo:`{{days}} дн. тому`}},apiBrowser:{placeholders:{requestBody:`JSON тіло запиту...`,searchEndpoints:`Пошук кінцевих точок...`}},configureAmsSlot:{title:`Налаштувати слот AMS.`,slotConfigured:`Слот налаштовано!`,configuringSlot:`Налаштування слота:`,slotLabel:`{{ams}} Слот {{slot}}`,searchPresets:`Шукати профілі...`,colorPlaceholder:`Назва або шістнадцяткова назва кольору (наприклад, коричневий, FF8800)`,clearCustomColor:`Очистити спеціальний колір`,noCloudPresets:`Хмарних профілів немає. Увійдіть у Bambu Cloud для синхронізації.`,noPresetsAvailable:`Профілів немає. Увійдіть у Bambu Cloud або імпортуйте локальні профілі.`,noMatchingPresets:`Відповідних стилів не знайдено.`,custom:`Власний`,builtin:`Вбудований`,orcaCloud:`Orca Cloud`,bambuCloud:`Бамбукова хмара`,settingsSentToPrinter:`Налаштування надіслано на принтер`,filamentProfile:`Профіль філаменту`,kProfileLabel:`Профіль K (випередження тиску)`,filteringFor:`Фільтрування за: {{material}}`,noKProfile:`Немає профілю K (використовуйте значення за замовчуванням 0,020)`,noMatchingKProfiles:`Не знайдено відповідних K профілів. Використовуватиметься K=0,020 за замовчуванням.`,otherKProfiles:`Інші K-профілі на цьому принтері`,selectFilamentFirst:`Спочатку виберіть профіль філаменту`,kFromCalibration:`K={{value}} від калібрування принтера`,customColorLabel:`Власний колір (необов’язково)`,presetColors:`{{name}} кольори:`,showLessColors:`Показувати менше кольорів`,showMoreColors:`Показати більше кольорів`,clear:`Очистити`,hexLabel:`Шістнадцятковий: #{{hex}}`,resetting:`Скидання...`,resetSlot:`Скинути слот`,cancel:`Скасувати`,configuring:`Налаштування...`,configureSlot:`Налаштувати слот`},githubBackup:{title:`Резервне копіювання Git`,history:`історія`,downloadBackup:`Завантажити резервну копію`,restoreBackup:`Відновити резервну копію`,noBackupsYet:`Резервних копій ще немає`},emailSettings:{placeholders:{fromName:`BamBuddy`}},tagManagement:{searchTags:`Пошук тегів...`,renameTag:`Перейменувати тег`,deleteTag:`Видалити тег`},notificationTemplates:{placeholders:{title:`Назва сповіщення...`,body:`Текст сповіщення...`}},batchTag:{placeholders:{newTag:`Введіть новий тег...`}},photoGallery:{deletePhoto:`Видалити фото`},filamentHoverCard:{copySpoolUuid:`Копіювати UUID буфера`},kProfilesView:{hasNote:`Має примітку`,copyProfile:`Копіювати профіль`},layout:{openMenu:`Відкрити меню`,noPermissionSystemInfo:`У вас немає дозволу на перегляд системної інформації`},dashboard:{dragToReorder:`Перетягніть, щоб змінити порядок`,hideWidget:`Сховати віджет`},notificationProviderCard:{deleteNotificationProvider:`Видалити постачальника сповіщень`},fileManagerModal:{closeFileManager:`Закрити файловий менеджер`,sortFiles:`Сортування файлів`,goToParentFolder:`Перейти до батьківської папки`,threeView:`3D перегляд`},embeddedCameraViewer:{refreshStream:`Оновити потік`,close:`Закрити`,zoomOut:`Зменшити масштаб`,resetZoom:`Скинути масштаб`,zoomIn:`Збільшити`,dragToResize:`Перетягніть, щоб змінити розмір`},timelapseViewer:{skipBack5s:`Перейти на 5 секунд назад`,skipForward5s:`Перейти вперед на 5 с`},notificationProviders:{descriptions:{email:`Сповіщення електронною поштою SMTP`,telegram:`Сповіщення через бота Telegram.`,discord:`Надіслати на канал Discord через webhook`,ntfy:`Безкоштовні push-сповіщення з можливістю самостійного розгортання`,pushover:`Прості та надійні push-повідомлення`,callmebot:`Безкоштовні сповіщення WhatsApp через CallMeBot`,webhook:`Універсальний HTTP POST-запит на будь-який URL`}},logViewer:{searchPlaceholder:`Шукати повідомлення або назву реєстратора...`,noLogEntries:`Записів у журналі не знайдено`},switchbarPopover:{noSwitchesInSwitchbar:`На панелі перемикачів немає`},projectPageModal:{placeholders:{title:`Назва`,designer:`Дизайнер`,license:`Ліцензія`,description:`Введіть опис...`,profileTitle:`Назва профілю`,profileDescription:`Опис профілю...`}},spoolmanSettings:{},time:{unknown:`-`,waiting:`Очікування`,justNow:`Просто зараз`,now:`Зараз`,minsAgo:`{{count}}хв тому`,inMins:`в {{count}}м`,hoursAgo:`{{count}} год тому`,inHours:`в {{count}} год`,daysAgo:`{{count}} дн. тому`,inDays:`в {{count}}d`},spoolbuddy:{nav:{dashboard:`Приладова панель`,ams:`AMS`,inventory:`Інвентар`,writeTag:`Записати`,settings:`Налаштування`},status:{nfcReady:`NFC Готовий`,nfcOff:`NFC Вимк`,offline:`Не в мережі`,online:`Онлайн`,noPrinters:`Немає принтерів`,deviceOffline:`Пристрій не в мережі`,waitingConnection:`Очікування підключення пристрою...`,systemReady:`Система готова`,status:`Статус`},dashboard:{readyToScan:`Готовий до сканування`,idleMessage:`Покладіть котушку на ваги, щоб ідентифікувати її`,nfcHint:`Тег NFC буде прочитано автоматично`,device:`пристрій`,syncWeight:`Синхронізувати вагу`,weightSynced:`Синхронізовано!`,unknownTag:`Невідомий тег`,newTag:`Виявлено новий тег`,onScale:`на вагах`,linkSpool:`Прив’язати до котушки`,linkTagTitle:`Прив’язати тег до котушки`,linkTag:`Прив’язати тег`,selectSpool:`Виберіть котушку, до якої потрібно прив’язати цей тег:`,noUntagged:`Не знайдено котушок без тегів`,tagDetected:`Тег виявлено`,noTag:`Без тегу`,tagId:`Тег`,grossWeight:`Вага брутто`,spoolSize:`Розмір котушки`,close:`Закрити`,currentSpool:`Поточна котушка`,plateReady:`Пластина готова: {{name}}`,plateReadyLabel:`Пластини готові до очищення`,plateClearAction:`Очистити`,plateClearedToast:`Друкарська пластина позначена як очищена`,plateClearFailed:`Не вдалося позначити пластину як очищену`},modal:{spoolDetected:`Виявлено котушку`,assignToAms:`Призначити AMS`,syncWeight:`Синхронізувати вагу`,weightSynced:`Синхронізовано!`,syncing:`Синхронізація...`,newTagDetected:`Виявлено новий тег`,addToInventory:`Додати в інвентар`,assignToAmsTitle:`Призначити AMS`,selectSlot:`Вибрати слот`,assign:`Призначити`,assigning:`Призначення...`,assignSuccess:`Призначено!`,assignPendingInsert:`Призначений. Слот буде налаштовано, коли ви вставите котушку.`,assignError:`Не вдалося призначити котушку. Спробуйте ще раз.`,noPrinterSelected:`Виберіть принтер...`,noAmsDetected:`AMS не виявлено на цьому принтері`,slot:`Слот`},weight:{noReading:`Немає показань`,stable:`Стабільно`,measuring:`Вимірювання…`,tare:`Тарувати`,calibrate:`Відкалібрувати`},spool:{remaining:`Залишилося`,material:`матеріал`,brand:`Бренд`,color:`Колір`,coreWeight:`Сердечник`,labelWeight:`Етикетка`,scaleWeight:`Показання ваг`,netWeight:`Нетто`,lastUsed:`Останнє використання`},ams:{noData:`AMS не виявлено`,connectAms:`Підключіть AMS, щоб побачити слоти для філаментів`,noPrinter:`Принтер не вибрано`,selectPrinter:`Виберіть принтер у верхній панелі`,printerDisconnected:`Принтер відключений`,humidity:`Вологість`,level:`Рівень`,active:`Активний`,slot:`Слот`,empty:`Порожній`},inventory:{search:`Пошук котушок...`,empty:`Немає котушок в інвентарі`,noResults:`Немає відповідних котушок`,spools:`котушки`,addSpool:`Додати котушку`},settings:{tabDevice:`пристрій`,tabDisplay:`Дисплей`,tabScale:`Ваги`,tabUpdates:`Оновлення`,nfcReader:`NFC Читач`,type:`Тип`,connection:`Підключення`,notConnected:`Н/Д`,deviceInfo:`Інформація про пристрій`,hostname:`Хост`,uptime:`Час роботи`,systemConfig:`Серверна частина та автентифікація`,backendUrl:`Bambuddy Сервер URL`,apiToken:`API Токен`,apiTokenPlaceholder:`Введіть API-токен.`,saveConfig:`Зберегти конфігурацію`,systemQueued:`Конфігурацію в черзі.`,nfcDiagnostic:`NFC Діагностика`,scaleDiagnostic:`Діагностика ваг`,readTagDiagnostic:`Прочитайте діагностику тегів`,testNfc:`Тестовий читач`,testScale:`Перевірити точність`,testReadTag:`Прочитати тег`,systemFieldsRequired:`Потрібен бекенд URL.`,brightness:`Яскравість`,saved:`Збережено`,noBacklight:`Підсвічування DSI не виявлено. Для керування яскравістю потрібен дисплей DSI.`,screenBlank:`Час очікування порожнього екрана`,screenBlankDesc:`Екран вимикається після бездіяльності. Торкніться, щоб розбудити.`,displayNote:`Яскравість використовується як програмний фільтр.`,scaleCalibration:`Калібрування ваг`,currentWeight:`Поточна вага`,tareOffset:`Зміщення тари`,calFactor:`Коефіцієнт калібрування`,knownWeight:`Відома маса`,calStep1:`Приберіть усі предмети з ваг і натисніть «Установити нуль».`,calStep2:`Покладіть на ваги предмет відомої маси.`,setZero:`Встановити нуль`,calibrateNow:`Відкалібрувати`,calibrated:`Відкалібровано`,tareSet:`Надіслано команду тарування. Очікування пристрою...`,tareComplete:`Тарування завершено!`,tareTimedOut:`Час очікування тарування минув — чи запущено демон SpoolBuddy?`,tareFailed:`Не вдалося надіслати команду тарування`,zeroSet:`Нульову точку встановлено. Покладіть на ваги предмет відомої маси.`,calibrationDone:`Калібрування завершено!`,calibrationFailed:`Помилка калібрування`,lastCalibrated:`Останнє калібрування`,stable:`Стабільно`,settling:`Стабілізація…`,firmware:`Прошивка`,scale:`Ваги`,noDevice:`Пристрій SpoolBuddy не знайдено`,daemonVersion:`Демон версія`,currentVersion:`поточний`,versionPending:`В очікуванні демона...`,checking:`Перевірка...`,checkUpdates:`Перевірте наявність оновлень`,updateAvailable:`Доступне оновлення`,updateInstructions:`Оновлення через SSH: запустіть сценарій встановлення SpoolBuddy для оновлення.`,upToDate:`В актуальному стані`,includeBeta:`Включати бета-версії`},writeTag:{tabExisting:`Наявна котушка`,tabNew:`Нова котушка`,tabReplace:`Замінити тег`,searchPlaceholder:`Пошук за матеріалом, кольором, брендом...`,noUntaggedSpools:`Немає котушок без тегів`,noTaggedSpools:`Немає котушок із тегами`,selectSpool:`Виберіть котушку, а потім помістіть порожній NTAG на зчитувач`,placeTag:`Помістіть NTAG на зчитувач`,tagReady:`Тег виявлено — готовий до запису`,writeTag:`Записати тег`,replaceTag:`Замінити тег`,writing:`Записування тегу…`,waiting:`Очікування SpoolBuddy...`,writeSuccess:`Тег успішно записано!`,writeFailed:`Помилка запису`,queueFailed:`Не вдалося поставити команду запису в чергу`,tryAgain:`Спробуйте знову`,cancel:`Скасувати`,replaceWarning:`Старий тег буде від’єднано від котушки, а замість нього буде прив’язано новий.`,deviceOffline:`SpoolBuddy не в мережі`,material:`матеріал`,colorName:`Назва кольору`,color:`Колір`,brand:`Бренд`,weight:`Вага (г)`,createSpool:`Створити котушку`,creating:`Створення...`,spoolCreated:`Котушку створено! Можна записувати тег.`,createFailed:`Не вдалося створити котушку`,incompleteDataWarning:`Тег записано з неповними даними Spoolman.`},quickMenu:{printerPower:`Живлення принтера`,systemControls:`система`,restartDaemon:`Перезапустити демон`,restartBrowser:`Перезапустити браузер`,reboot:`Перезавантажити`,shutdown:`Вимкнути`,swipeToClose:`Проведіть пальцем вниз, щоб закрити`,confirmTitle:`Підтвердити`,confirmShutdown:`Вимкнути SpoolBuddy? Щоб увімкнути його знову, знадобиться фізичний доступ до пристрою.`,confirmReboot:`Перезавантажити SpoolBuddy?`,confirmRestartDaemon:`Перезапустити демон SpoolBuddy? NFC і ваги будуть тимчасово недоступні.`,confirmRestartBrowser:`Перезапустити веб-переглядач кіоску? Дисплей на короткий час погасне.`,confirm:`Підтвердити`,confirmPlugOn:`Увімкнути {{name}}?`,confirmPlugOff:`Вимкнути {{name}}?`,turnOn:`Увімкнути`,turnOff:`Вимкнути`}},diagnostic:{modalTitle:`Діагностика підключення — {{name}}`,running:`Виконується діагностика...`,runningElapsed:`Виконується діагностика… ({{elapsed}} с)`,waitingForReportHint:`Очікуємо, доки принтер опублікує звіт про стан — це може тривати до {{max}} с.`,runFailed:`Не вдалося запустити діагностику: {{error}}`,retry:`Запустити знову`,runButton:`Запустити діагностику`,sectionTitle:`Діагностика підключення`,sectionDescription:`Перевірте, чому принтер не підключається або не друкує — доступність порту, режим розробника LAN, режим мережі Docker та облікові дані.`,noPrinters:`Принтери не налаштовані.`,overall:{ok:`Проблем не виявлено — з’єднання принтера справне.`,warnings:`Принтер має працювати, але деякі параметри потребують уваги.`,problems:`Знайдено проблеми, які пояснюють, чому принтер не підключається або не друкує.`},check:{port_mqtt:{title:`Порт керування (MQTT 8883)`,pass:`Доступний — принтер приймає керівні з’єднання.`,fail:`Порт 8883 недоступний. Принтер може бути вимкнений, мати іншу IP-адресу або бути заблокований брандмауером. Перевірте IP-адресу принтера й переконайтеся, що порт 8883 не заблоковано.`},port_ftps:{title:`Порт передачі файлів (FTPS 990)`,pass:`Доступний — файли друку можна буде надсилати.`,warn:`Порт 990 недоступний. Моніторинг може й надалі працювати, але надсилання завдань друку на принтер завершуватиметься помилкою. Переконайтеся, що порт 990 не заблоковано.`},external_storage:{title:`Зберігання надісланих файлів у зовнішньому сховищі (крок установлення 4)`,pass:`Принтер повідомляє, що цю опцію ввімкнено — надіслані файли зберігатимуться на картці SD, а архіви матимуть мініатюри та метадані слайсера.`,fail:`Принтер повідомляє, що цей параметр вимкнено. Увімкніть «Зберігати надіслані файли в зовнішньому сховищі». У новіших версіях прошивки (P2S 01.02 / Bambu Studio 2.6+) перемикач розташований у налаштуваннях друку на принтері; у старіших — на вкладці «Пристрій» у Bambu Studio або OrcaSlicer. Без цього параметра в кожному архівованому друці будуть відсутні мініатюра та метадані слайсера.`,skip:`Не перевірено — потрібне активне MQTT-з’єднання. У старіших слайсерах, де цей параметр існує лише в самому слайсері, принтер його не повідомляє. Тому перевірка може бути успішною навіть за вимкненого параметра — перевірте крок установлення 4 вручну.`,skip_unsupported_model:`Ця модель має слот для SD-картки, але не дає змоги ввімкнути цей параметр: поточна прошивка принтерів серії P1 не показує перемикач у Bambu Studio, а сам принтер не має екрана. Виправляти нічого не потрібно; доки Bambu Lab не додасть підтримку в прошивці, в архівованих друках можуть бути відсутні мініатюри та метадані слайсера.`},port_rtsps:{title:`Порт камери ({{protocol}} {{port}})`,pass:`Доступно — потік камери працюватиме.`,warn:`Порт {{port}} недоступний. Перегляд з камери в реальному часі не працюватиме. Це не впливає на друк.`},network_mode:{title:`Мережевий режим Docker`,pass:`Працює в режимі хост-мережі.`,warn:`Bambuddy працює в мостовому мережевому режимі Docker. Для виявлення принтерів і роботи віртуального принтера потрібен режим мережі хоста — повторно створіть контейнер із параметром "network_mode: host".`,skip:`Не працює в Docker — не застосовується.`},subnet:{title:`Мережева підмережа`,pass:`Принтер і Bambuddy знаходяться в одній підмережі.`,warn:`Принтер ({{printer_ip}}) і Bambuddy ({{host_ip}}) перебувають у різних підмережах. Вони можуть не мати зв’язку між собою, якщо маршрутизацію між підмережами не налаштовано.`,skip:`Не вдалося визначити підмережу — пропущено.`},mqtt_auth:{title:`Облікові дані принтера`,pass:`Принтер прийняв підключення.`,fail:`Принтер доступний, але Bambuddy до нього не під’єднано. Найімовірніше, указано неправильний код доступу або серійний номер — код доступу змінюється після кожного перемикання режиму «Лише LAN» або режиму розробника, тож знову скопіюйте його з екрана принтера. Так само виглядає принтер, який перезавантажується або вже вичерпав ліміт одночасних з’єднань.`,fail_auth_rejected:`Принтер відхилив облікові дані Bambuddy. Код доступу або серійний номер неправильний — код доступу змінюється після кожного перемикання режиму «Лише LAN» або режиму розробника. Знову скопіюйте його з екрана принтера та збережіть у налаштуваннях принтера.`,skip:`Не позначено — принтер недоступний.`},developer_mode:{title:`Режим розробника LAN`,pass:`Режим розробника ввімкнено.`,fail:`Режим розробника на принтері ВИМКНЕНО. Увімкніть його в налаштуваннях LAN принтера й підтвердьте вибір кнопкою OK. Без цього друк не запускатиметься.`,skip:`Неможливо перевірити — потрібне живе підключення до принтера.`},printer_publishing:{title:`Принтер публікує дані про стан`,pass:`Принтер публікує оновлення статусу — AMS, філаменти та K-профілі правильно відображатимуться на слайсері.`,fail:`MQTT-брокер прийняв з’єднання, але принтер не опублікував жодного звіту про стан. Майже завжди причиною є неправильний серійний номер або неправильний регістр символів: тема device//report чутлива до регістру. Звірте серійний номер у налаштуваннях Bambuddy із номером на екрані принтера.`,skip:`Неможливо перевірити — потрібне живе підключення до принтера.`}}},systemHealth:{sectionTitle:`Стан системи`,sectionDescription:`Сканує останні журнали на наявність відомих проблем, які зазвичай можна вирішити самостійно, перш ніж вони перетворяться на запит у службу підтримки.`,rescan:`Пересканувати`,clean:`В останніх записах журналу {{times}} не знайдено відомих проблем.`,logUnavailable:`Журналування файлів вимкнено, тому журнали неможливо сканувати. Увімкніть журналювання файлів, щоб використовувати цю перевірку.`,learnMore:`Як виправити`,fixLabel:`Виправити:`,occurrences:`Виявлено {{times}} разів — востаннє о {{lastSeen}}`,category:{layer8:`Ви можете це виправити`,environment:`Середовище виконання`,bug:`Будь ласка, повідомте про це`},signature:{"ftp-auth-rejected":{name:`Принтер відхилив код доступу`,cause:`Принтер відмовився від входу для передавання файлів. Код доступу неправильний або він змінився після перемикання режиму розробника.`,fix:`Повторно скопіюйте код доступу з екрана принтера (налаштування LAN) і оновіть його в налаштуваннях принтера в Bambuddy.`},"ftp-connection-timeout":{name:`Час очікування з’єднання для передачі файлів минув`,cause:`Bambuddy не вдалося отримати доступ до порту передачі файлів принтера (FTPS 990). Порт заблоковано, або принтер вимкнено або знаходиться в іншій підмережі.`,fix:`Переконайтеся, що ніщо не блокує порт 990 між Bambuddy і принтером, і що обидва знаходяться в одній мережі.`},"ftp-ssl-error":{name:`Помилка захищеного з’єднання для передавання файлів`,cause:`Не вдалося виконати TLS-узгодження із сервером передавання файлів принтера. Частою причиною є брандмауер або застаріла прошивка принтера.`,fix:`Оновіть прошивку принтера та переконайтеся, що брандмауер або проксі-сервер не перехоплюють з’єднання через порт 990.`},"mqtt-connection-flapping":{name:`Підключення до принтера постійно падає`,cause:`Керуюче з’єднання (MQTT 8883) неодноразово роз’єднується та знову під’єднується — зазвичай через слабкий мережевий шлях або частково заблокований порт.`,fix:`Перевірте сигнал Wi-Fi на принтері, віддайте перевагу дротовому підключенню та переконайтеся, що порт 8883 надійно доступний.`},"camera-connection-refused":{name:`Потік з камери недоступний`,cause:`Не вдається отримати доступ до камери в прямому ефірі через порт RTSPS 322. Порт заблоковано, або на принтері вимкнено камеру або LAN liveview.`,fix:`Увімкніть камеру та LAN liveview на принтері та переконайтеся, що порт 322 не заблоковано. Це не впливає на друк.`},"database-locked":{name:`Конфлікт запису до бази даних`,cause:`Під навантаженням SQLite повертає помилки "database is locked". Це часто трапляється, коли одночасно працюють кілька принтерів.`,fix:`Переключіть Bambuddy на зовнішню базу даних PostgreSQL. Див. посібник PostgreSQL у документації.`}}},vpDiagnostic:{title:`Перевірка налаштувань — {{name}}`,runButton:`Запустити перевірку налаштувань`,running:`Виконується перевірка налаштувань...`,runFailed:`Не вдалося виконати перевірку налаштувань: {{error}}`,retry:`Запустити знову`,overall:{ok:`Усі перевірки пройшли — цей віртуальний принтер налаштовано правильно.`,warnings:`Віртуальний принтер має працювати, але деякі параметри потребують уваги.`,problems:`Знайдено проблеми, які пояснюють, чому слайсер не бачить або не використовує цей віртуальний принтер.`},check:{enabled:{title:`Віртуальний принтер увімкнено`,fail:`Цей віртуальний принтер вимкнено. Увімкніть його, щоб зробити його видимим.`},running:{title:`Служби запущені`,fail:`Віртуальний принтер увімкнено, але його служби не працюють. Перевірте журнал Bambuddy — зазвичай запуску заважає конфлікт IP-адреси прив’язки або помилка дозволів.`},bind_interface:{title:`Прив’язка мережевого інтерфейсу`,fail:`Інтерфейс прив’язки не встановлено або більше не існує на цьому хості. Виберіть поточний інтерфейс у спадному списку «Інтерфейс прив’язки».`},access_code:{title:`Код доступу встановлено`,fail:`Код доступу не встановлено. У слайсері потрібно вказати той самий 8-символьний код доступу, який задано тут.`},target_printer:{title:`Цільовий принтер`,fail:`Цільовий принтер не вибрано. У режимі проксі потрібен фізичний принтер, якому пересилатимуться завдання.`,warn:`Цільовий принтер наразі не в мережі — проксі-сервер відновиться після повторного підключення.`},port_ftps:{title:`Служба вивантаження файлів (порт {{port}})`,fail:`На порту {{port}} IP-адреси прив’язки немає служби, що приймає з’єднання, тому слайсер не може вивантажити файли. Зазвичай причиною є конфлікт порту на цьому інтерфейсі.`},port_mqtt:{title:`Служба керування (порт {{port}})`,fail:`На порту {{port}} IP-адреси прив’язки немає служби, що приймає з’єднання, тому слайсер не може підключитися або показати стан.`},port_bind:{title:`Служба виявлення (порт {{port}})`,fail:`На порту {{port}} IP-адреси прив’язки немає служби, що приймає з’єднання, тому слайсер не може завершити процедуру виявлення.`},certificate:{title:`Сертифікат TLS`,pass:`Сертифікат готовий. Переконайтеся, що наведений вище сертифікат центру сертифікації Bambuddy імпортовано до сховища довірених сертифікатів слайсера.`,fail:`Сертифікат TLS для цього віртуального принтера відсутній. Перевірте, чи доступний для запису каталог даних Bambuddy.`}}},bugReport:{title:`Повідомити про помилку`,description:`опис`,descriptionPlaceholder:`Що пішло не так? Будь ласка, опишіть проблему...`,email:`Електронна адреса (необов’язково)`,emailPlaceholder:`your@email.com`,emailPrivacy:`Якщо надано, вашу електронну адресу буде включено до згорнутого розділу проблеми GitHub, щоб спеціаліст із супроводу міг відслідковувати.`,screenshot:`Скріншот`,uploadOrPaste:`Вивантажити, вставити або перетягнути зображення`,dataCollectedSummary:`Які дані містяться у звіті?`,dataIncluded:`У комплекті:`,dataIncludedList:`Версія додатка, OS, архітектура, версія Python, статистика бази даних (лише для підрахунку), моделі принтерів, кількість сопел, версії прошивки, статус підключення, статус інтеграції (Spoolman, MQTT, HA), неконфіденційні налаштування, кількість мережевих інтерфейсів, Docker деталі, версії залежностей.`,dataNeverIncluded:`Ніколи не додаються:`,dataNeverIncludedList:`Назви принтерів, серійні номери, коди доступу, паролі, IP-адреси, адреси електронної пошти, ключі API, токени, URL вебхуків, імена хостів або користувачів.`,submit:`Надіслати`,startLogging:`Розпочати журнал налагодження`,stepEnableLogging:`Журнал налагодження ввімкнено`,stepReproduce:`Відтворіть проблему зараз`,stepStopLogging:`Зупинити та подати звіт`,stopAndSubmit:`Зупинити та надіслати`,maxDuration:`Автоматична зупинка через {{minutes}} хв`,stoppingLogs:`Збір журналів і надсилання...`,submitting:`Надсилання звіту про помилку...`,submittingStepConnection:`Запуск перевірки підключення принтера`,submittingStepVirtualPrinters:`Виконання перевірок налаштування віртуального принтера`,submittingStepLogScan:`Сканування останніх журналів на наявність відомих проблем`,submittingStepSubmit:`Надсилання звіту GitHub`,submitSuccess:`Звіт про помилку успішно надіслано!`,submitFailed:`Не вдалося надіслати звіт про помилку`,diagnosticChecking:`Перевірка підключень принтера...`,diagnosticHealthy:`Перевірку підключення пройдено — проблем із принтерами не виявлено.`,diagnosticSummary:`Проблеми з підключенням мають {{problems}} із {{total}} принтерів`,diagnosticIntro:`Один або кілька принтерів мають проблему з підключенням, яка може спричиняти описану несправність. Розгорніть запис принтера нижче, щоб переглянути спосіб виправлення. Усунення цієї проблеми може допомогти без створення звіту про помилку, але за потреби звіт усе одно можна надіслати нижче.`,logHealthSummary:`У ваших журналах знайдено відомі проблеми`,logHealthIntro:`Останні журнали відповідають відомим проблемам. Перегляньте наведені нижче виправлення — їх вирішення може вирішити вашу проблему без повідомлення про помилку. Ви все ще можете надіслати звіт нижче.`,thankYou:`дякую!`,submitted:`Ваш звіт про помилку надіслано.`,viewIssue:`Переглянути випуск`,unexpectedError:`Сталася неочікувана помилка`},failureDetection:{title:`Виявлення помилок за допомогою ШІ`,description:`Відстежуйте друк за допомогою самостійно розгорнутого Obico ML API та автоматично реагуйте на виявлені помилки.`,mlUrl:`URL Obico ML API`,mlUrlHint:`База URL вашого контейнера ml_api, розміщеного на власному хості Obico (наприклад, http://192.168.1.10:3333).`,mlToken:`Токен ML API (необов'язково)`,mlTokenPlaceholder:`Залиште порожнім, якщо сервер працює без ML_API_TOKEN`,mlTokenHint:`Має збігатися зі змінною середовища ML_API_TOKEN вашого контейнера Obico ml_api. Залиште порожнім, якщо контейнер працює без токена.`,test:`Тест`,testSuccess:`ML API доступний і працює належним чином.`,testSuccessTokenUnknown:`ML API доступний і працює належним чином. Не вдалося перевірити токен.`,testFailed:`Не вдалося підключитися до ML API.`,sensitivity:`Чутливість`,sensitivityLow:`Низький (менше помилкових спрацьовувань)`,sensitivityMedium:`Середній (збалансований)`,sensitivityHigh:`Високий (виявляти рано, більше помилкових спрацьовувань)`,sensitivityHint:`Налаштовує пороги впевненості, за яких формуються попередження та фіксуються помилки.`,action:`Дія в разі виявлення помилки`,actionNotify:`Лише сповіщати`,actionPause:`Призупинити друк`,actionPauseOff:`Призупинити друк і вимкнути живлення`,pollInterval:`Інтервал опитування (секунди)`,pollIntervalHint:`Як часто перевіряти кожен принтер під час друку. Мінімум 5 с, максимум 120 с.`,externalUrlMissing:`Зовнішній URL не встановлено.`,externalUrlHint:`ML API отримує знімок із камери за URL. Укажіть зовнішній URL у загальних налаштуваннях, щоб контейнер ML API міг підключитися до Bambuddy.`,perPrinterTitle:`Принтери під спостереженням`,perPrinterHint:`Виберіть, які принтери перевіряє служба виявлення.`,monitorAll:`Відстежувати всі підключені принтери`,statusTitle:`Статус`,serviceRunning:`Служба працює`,thresholds:`Нижній / верхній поріг`,activePrinters:`Активні завдання друку`,noActivePrints:`Зараз немає роздруківок.`,historyTitle:`Останні виявлення`,noHistory:`Виявлень ще немає.`},makerworld:{title:`MakerWorld`,description:`Вставте модель MakerWorld URL, щоб імпортувати та роздрукувати її безпосередньо з Bambuddy — не виходячи з програми Bambu Handy.`,pasteUrlHeader:`Імпортувати з MakerWorld`,pasteUrlPlaceholder:`https://makerworld.com/en/models/… або вставте будь-яке посилання MakerWorld.`,resolveButton:`Розв’язати`,signInRequiredTitle:`Для завантаження потрібно увійти в Bambu Cloud`,signInRequiredBody:`Ви можете переглядати деталі моделі анонімно, але для MakerWorld потрібен обліковий запис Bambu Cloud для завантаження файлів 3MF.`,signInExpiredTitle:`Термін входу в Bambu Cloud минув`,signInExpiredBody:`Ви все ще ввійшли в Bambuddy, але Bambu Lab більше не приймає збережений токен, тому завантаження не вдасться. Знову ввійдіть у Bambu Cloud.`,openCloudSettings:`Відкрити налаштування Cloud`,untitledModel:`Модель без назви`,byCreator:`від {{name}}`,downloadsCount:`{{count}} завантажень`,licensePrefix:`Ліцензія`,alreadyImported:`Вже в бібліотеці`,openOnMakerworld:`Відкрити MakerWorld`,alreadyInLibrary:`Ця модель уже є у вашій бібліотеці — знайдіть її в Менеджері файлів → MakerWorld`,importSuccess:`Імпортовано {{filename}} — збережено в менеджері файлів → MakerWorld`,platesHeader:`Пластини ({{count}})`,plateDefaultName:`Пластина {{n}}`,materialCount:`Філаментів: {{count}}`,amsRequired:`Потрібен AMS`,slicedFor:`Нарізано для {{printer}}`,alsoCompatible:`Також позначено як сумісний: {{printers}}`,importToLibrary:`Зберегти`,sliceIn:`Зберегти й нарізати в {{slicer}}`,disclaimer:`Інтеграція MakerWorld використовує кінцеві точки API, задокументовані спільнотою. Bambuddy не є філією та не підтримується MakerWorld або Bambu Lab.`,lastImportSuccess:`Імпортовано до вашої бібліотеки`,lastImportAlreadyInLibrary:`Уже у вашій бібліотеці`,viewInLibrary:`Переглянути в менеджері файлів`,openInBambuStudio:`Відкрити в Bambu Studio`,openInOrcaSlicer:`Відкрити в OrcaSlicer`,importTo:`Імпорт до файлового менеджера`,recentImportsHeader:`Недавній імпорт`,phaseResolving:`Розв’язування`,phaseDownloading:`Завантаження`,folderAuto:`MakerWorld (за замовчуванням)`,importAll:`Імпортувати все`,importAllProgress:`Імпорт {{current}}/{{total}}`,openGallery:`Відкрити галерею зображень`,galleryPrev:`Попереднє зображення`,galleryNext:`Наступне зображення`,deleteImport:`Видалити з бібліотеки`,importDeleting:`Видалення…`,importDeleted:`Видалено з бібліотеки`,confirmDelete:`Видалити {{filename}} з бібліотеки? Локальний файл буде видалено, але цю друкарську пластину можна буде повторно імпортувати з MakerWorld.`,errors:{resolveFailed:`Не вдалося вирішити MakerWorld URL.`,downloadFailed:`Помилка завантаження. Спробуйте ще раз.`,deleteFailed:`Не вдалося видалити файл із бібліотеки.`}},gcodeViewer:{back:`Назад`,backToArchives:`Назад до друку архівів`,backToFiles:`Назад до файлового менеджера`},libraryTrash:{title:`Кошик`,headerButton:`Кошик`,headerTooltip:`Переглянути файли, переміщені в кошик`,backToFiles:`Назад до файлового менеджера`,subtitleAdmin:`Видалені файли залишаються тут протягом {{days}} днів, а потім автоматично видаляються. У цьому режимі перегляду відображаються файли, видалені в кошик для всіх користувачів.`,subtitleUser:`Видалені файли залишаються тут протягом {{days}} днів, а потім автоматично видаляються.`,loading:`Завантаження кошика…`,loadError:`Не вдалося завантажити кошик.`,empty:`Кошик порожній.`,summary:`Файлів: {{count}} · {{size}}`,emptyTrash:`Очистити кошик`,restore:`Відновити`,purgeNow:`Видалити зараз`,autoPurgeIn:`Автоматичне видалення через {{when}}`,days:`днів`,retentionLabel:`Автоматичне видалення після`,selectAll:`Вибрати все`,selectOne:`Вибрати {{filename}}`,selectionCount:`Вибрано {{count}}.`,bulkRestore:`Відновити вибране`,bulkPurge:`Видалити вибране`,col:{filename:`Файл`,folder:`Папка`,size:`Розмір`,deleted:`Переміщено в кошик`,autoPurge:`Автоматичне видалення`,owner:`Власник`,actions:`Дії`},confirm:{purgeTitle:`Видалити остаточно?`,purgeBody:`{{filename}} буде видалено з диска та не підлягає відновленню.`,emptyTitle:`Очистити кошик?`,emptyBody:`З диска буде остаточно видалено всі файли ({{count}}). Цю дію неможливо скасувати.`,bulkPurgeTitle:`Видалити вибрані файли назавжди?`,bulkPurgeBody:`Вибрані файли ({{count}}) буде видалено з диска без можливості відновлення.`,cta:`Видалити остаточно`},toast:{restored:`Файл відновлено.`,restoreFailed:`Не вдалося відновити файл.`,purged:`Файл видалено остаточно.`,purgeFailed:`Не вдалося видалити файл.`,emptied:`Файлів остаточно видалено з кошика: {{count}}.`,emptyFailed:`Не вдалося очистити кошик.`,retentionSaved:`Для автоматичного видалення встановлено {{days}} днів.`,retentionFailed:`Не вдалося зберегти налаштування збереження.`,bulkRestored:`Відновлено файлів: {{count}}`,bulkPurged:`Файлів остаточно видалено: {{count}}.`}},libraryPurge:{title:`Очистити старі файли`,headerButton:`Очищення старого`,headerTooltip:`Масове переміщення старих файлів у кошик`,description:`Однією дією перемістіть старі файли з бібліотеки до кошика. Вік файлів з історією друку визначається за датою останнього друку, а файлів, які ще не друкувалися, — за датою вивантаження.`,ageLabel:`Перемістити файли, старші за`,days:`днів`,includeNeverPrinted:`Включати файли, які ніколи не друкувались`,effectsTitle:`Що відбудеться після натискання «Очистити»`,effect1:`Відповідні файли переміщуються в кошик — вони ще не видалені з диска.`,effect2:`Ви можете будь-коли відновити їх із кошика, доки не закінчиться період зберігання.`,effect3:`Після завершення строку зберігання служба очищення кошика остаточно видалить файли з диска.`,effect4:`Файли у зовнішніх (зв’язаних) папках пропускаються — Bambuddy ніколи не видаляє байти, які йому не належать.`,previewLoading:`Перевірка кількості файлів…`,previewFailed:`Не вдалося попередньо переглянути очищення.`,previewSummary:`Файли {{count}} · {{size}} буде переміщено до кошика`,andMore:`…і {{count}} більше`,warning:`Файли в кошику й надалі займають місце, доки не завершиться строк зберігання. Щоб звільнити місце на диску негайно, після цього очистьте кошик.`,confirmCta:`Перемістити до кошика ({{count}})`,purging:`Переміщення в кошик…`,toast:{success:`Переміщено до кошика файлів: {{count}}`,failed:`Не вдалося очистити файли.`}},libraryAutoPurge:{enableLabel:`Автоматичне очищення старих файлів`,enableDescription:`Запускає очищення адміністратора один раз на день. Файли спочатку потрапляють у кошик — вони не видаляються одразу.`,ageLabel:`Автоматичне очищення файлів, старших за`,ageDescription:`Мінімум 7 днів, максимум 10 років. Використовує те саме вікове правило, що й ручна кнопка очищення.`,days:`днів`,includeNeverPrinted:`Включати файли, які ніколи не друкувались`,saveFailed:`Не вдалося зберегти налаштування автоматичного очищення.`},archivePurge:{headerButton:`Очищення старого`,headerTooltip:`Масове видалення старих архівів`,title:`Очистити старі архіви`,description:`Очистити стару історію друку. Кожен архів старіє відповідно до останнього завершення друку — повторний друк архіву оновлює його вік, тому активна робота ніколи не очищається.`,ageLabel:`Видалити архіви, не надруковані в останньому`,days:`днів`,effectsTitle:`Що відбудеться після натискання «Очистити»`,effect1:`Кожен відповідний архів приховано зі списків, а його файли видалено з диска (3MF, ескіз, покадрова зйомка, вихідний 3MF, F3D файл дизайну, фотографії).`,effect2:`Запис архіву залишиться в базі даних, тому «Швидка статистика» й надалі враховуватиме філамент, час, вартість та енергію — як і за типового видалення окремого архіву.`,effect3:`Позначте нижче «Також видалити зі статистики», щоб вилучити внесок цих архівів зі «Швидкої статистики» — так само, як у відповідній опції видалення окремого архіву. Цю дію неможливо скасувати.`,effect4:`Повторний друк архіву оновлює його віковий годинник, тому архіви, якими ви все ще користуєтеся, залишаються в безпеці.`,purgeStatsLabel:`Також видалити зі статистики`,purgeStatsHint:`Вилучає внесок відповідних архівів зі «Швидкої статистики» — філамент, час, вартість та енергію. Якщо параметр вимкнено, статистичні дані зберігаються, а з диска видаляються лише файли.`,previewLoading:`Перевірка кількості архівів, що збігаються…`,previewFailed:`Не вдалося попередньо переглянути очищення.`,previewSummary:`Архіви {{count}} · {{size}} буде видалено`,andMore:`…і {{count}} більше`,warning:`Файли видаляються з диска і не можуть бути відновлені. Перш ніж продовжити, завантажте або додайте до вибраного все, що хочете зберегти.`,confirmCta:`Видалити архіви ({{count}})`,purging:`Видалення…`,toast:{success:`Видалено архівів: {{count}}`,failed:`Не вдалося очистити архіви.`}},archiveAutoPurge:{enableLabel:`Автоматичне очищення старих архівів`,enableDescription:`Один раз на день приховує архіви зі списків і видаляє їх файли з диска, якщо вони не були надруковані в межах порогу. Повторний друк архіву скидає годинник.`,ageLabel:`Автоматичне видалення архівів, не надрукованих в останньому`,ageDescription:`Мінімум 7 днів, максимум 10 років. На основі останнього завершення друку — повторний друк архіву оновлює його вік. Видаляє 3MF, мініатюру, покадрову зйомку, джерело 3MF, F3D і фотографії.`,days:`днів`,purgeStatsLabel:`Також видалити зі статистики`,purgeStatsDescription:`Якщо параметр увімкнено, щоденне очищення також вилучатиме внесок кожного видаленого архіву зі «Швидкої статистики» — філамент, час, вартість та енергію. Типово параметр вимкнено: статистичні дані зберігаються, а з диска видаляються лише файли.`,runNow:`Очистити архіви зараз`,saveFailed:`Не вдалося зберегти налаштування автоматичного очищення.`},cameraTokens:{scope:{camera_stream:`Потік камери`,camwall:`Панель камер`,overlay:`Потокове накладання`},title:`API-токени камери`,navTitle:`API-токени камери`,description:`Довгострокові токени для вбудовування потоку камери в Home Assistant, Frigate, кіоски або інші засоби, яким потрібен постійний URL. Під час створення виберіть область доступу; токен можна відкликати будь-коли.`,loading:`Завантаження…`,confirmRevoke:{title:`Відкликати цей токен?`,body:`Усі пристрої, що використовують «{{name}}», негайно втратять доступ. Цю дію неможливо скасувати.`,cancel:`Скасувати`,confirm:`Відкликати`},create:{scopeLabel:`Область застосування`,hintCameraStream:`Токен потоку камери дає змогу отримувати лише потоки з камер і знімки. Використовуйте його для Home Assistant, Frigate або іншого засобу, що вбудовує одну камеру.`,hintCamWall:`Токен Cam Wall відкриває /camwall на екрані без входу. Він може бачити назву та стан кожного принтера, а також потоки з камери. Він не може бачити імена файлів, адреси чи коди доступу.`,hintOverlay:`Токен потокового накладання відкриває /overlay/{printerId} на екрані без входу — для OBS або будь-якої прямої трансляції. Він дає змогу переглядати потік із камери одного принтера та стан друку в реальному часі, зокрема назву файлу, показану на екрані. Він не надає доступу до адрес чи кодів доступу.`,title:`Створити новий токен`,nameLabel:`Назва токена`,namePlaceholder:`напр. Home Assistant`,daysLabel:`Днів до закінчення терміну дії`,submit:`Створити`,hint:`Максимальний строк дії — 365 днів. Значення токена буде показано лише один раз під час створення — скопіюйте його зараз.`},created:{camWallUrlTitle:`Cam Wall URL для цього дисплея`,camWallUrlHint:`Відкрийте цей URL на потрібному екрані. Будь-хто, хто отримає URL, зможе переглядати панель камер, тому захищайте його як ключ доступу. Щоб негайно припинити доступ із цього екрана, відкличте токен.`,overlayUrlTitle:`Накладання URL для OBS`,overlayUrlHint:`Додайте цей URL в OBS як джерело браузера. Замініть число в /overlay/1 номером принтера з його URL на сторінці «Принтери». Будь-хто, хто отримає URL, зможе переглядати трансляцію, тому захищайте його як ключ доступу. Щоб негайно припинити доступ, відкличте токен.`,title:`Токен створено — скопіюйте його зараз`,warning:`Це єдиний раз, коли токен буде показано. Після закриття цього діалогового вікна переглянути його знову буде неможливо.`,copy:`Копіювати`,dismiss:`Я зберіг токен`},list:{scope:`Область застосування`,myTitle:`Мої токени`,allTitle:`Усі користувачі (перегляд адміністратора)`,empty:`Токенів ще немає.`,name:`Назва`,owner:`Власник`,prefix:`Префікс`,created:`Створено`,expires:`Термін дії закінчується`,lastUsed:`Останнє використання`,revoke:`Відкликати`,expired:`Термін дії минув`},toast:{created:`Токен створено`,createFailed:`Не вдалося створити токен`,revoked:`Токен відкликано`,revokeFailed:`Не вдалося відкликати токен`,loadFailed:`Не вдалося завантажити токени`,copied:`Скопійовано в буфер обміну`,copyFailed:`Не вдалося копіювати — виберіть і скопіюйте вручну`}},forecast:{title:`Прогноз`,noSpools:`Не знайдено активних котушок. Додайте котушки до свого інвентарю, щоб переглянути прогнозні дані.`,noUsageData:`Немає даних про використання — неможливо спроєктувати хронологію запасів.`,sku:`SKU`,material:`матеріал`,stock:`Запас`,dailyRate:`Добове споживання`,daysLeft:`Залишилося днів`,emptyBy:`Вичерпається до`,reorderBy:`Замовити до`,actions:`Дії`,trend:`Тренд`,estimated:`Приблизно`,noData:`Немає даних`,timeframe:`Період`,chartTitle:`Прогнозований запас — топ-5 матеріалів`,dashedLinesROP:`Пунктирні лінії — точки повторного замовлення`,stockLevel:`Рівень запасів`,reorderPoint:`Точка повторного замовлення`,safetyMargin:`Запас безпеки`,trendLegend:`Тенденція (на основі історії, рівень обслуговування 95%)`,estimatedLegend:`Розрахункова (дельта ваги)`,noDataLegend:`Немає даних`,ropLabel:`ROP`,ssLabel:`SS`,safetyStockLegend:`Страховий запас`,stockArrivalLegend:`Надходження запасів`,stockoutLegend:`Дефіцит`,alertCount_one:`Сповіщень: {{count}}`,alertCount_other:`Сповіщень: {{count}}`,order:`Замовлення`,save:`Зберегти`,cancel:`Скасувати`,settingsSaved:`Налаштування збережено`,failedSaveSettings:`Не вдалося зберегти налаштування`,globalLeadTimeSaved:`Загальний строк постачання збережено`,globalLeadTime:`Загальний строк постачання`,globalLeadTimeHint:`Мінімальний строк постачання для розрахунку точки повторного замовлення всіх SKU`,skuLeadTimeOverride:`Інший строк постачання`,skuLeadTimeHint:`0 — використовувати загальний строк. Установіть значення понад 0, щоб перевизначити його для цього SKU.`,safetyMarginLabel:`Запас безпеки`,effectiveLeadTime:`Розрахунковий строк постачання`,effectiveLeadTimeHint:`max(глобальний {{global}}d, SKU {{sku}}d)`,reorderPointHint:`d̄ × LT + страховий запас — замовляйте, коли запас досягне цього рівня`,safetyMarginHint:`Статистичний страховий запас (z=1,65 × σ × √LT) + визначений користувачем буфер`,safetyMarginHintDays:`Буфер додано поверх статистичного страхового запасу.{{approx}}`,safetyMarginHintDaysApprox:` ≈ {{g}} г за поточного рівня споживання.`,safetyMarginHintG:`Буфер фіксованої ваги, доданий поверх статистичного страхового запасу.{{approx}}`,safetyMarginHintGApprox:` ≈ {{days}} дн. за поточного рівня споживання.`,individualSpools:`Окремі котушки`,labelWeight:`Вага за етикеткою`,spoolCount_one:`Котушок: {{count}}`,spoolCount_other:`Котушок: {{count}}`,stockBreakRisk:`Ризик вичерпання запасу`,stockBreakDetail:`Залишилося {{days}} дн.; строк постачання — {{lt}} дн.`,stockBreakBefore:`Запас вичерпається до поповнення`,reorderNow:`Замовити зараз`,reorderTriggerPassed:`Дата замовлення {{date}} минула.`,shoppingList:`Список покупок`,shoppingListItems_one:`(позицій: {{count}})`,shoppingListItems_other:`(позицій: {{count}})`,shoppingListEmpty:`Список покупок порожній. Натисніть значок кошика в будь-якому рядку, щоб додати позиції.`,addToCart:`Додати до списку покупок`,alertsSnoozed:`Вимкнути сповіщення для цього SKU`,alertsEnabled:`Увімкнути сповіщення для цього SKU`,addedToCart:`Додано до списку покупок`,failedAddItem:`Не вдалося додати елемент`,listView:`Список`,logisticsView:`Логістика`,qty:`Кількість`,weight:`Вага`,leadTime:`Строк постачання`,expectedRestock:`Очікуване поповнення запасів`,status:`Статус`,note:`Примітка`,pending:`В очікуванні`,purchased:`Придбано`,received:`Отримано`,markPurchased:`Позначити як придбане`,markReceived:`Позначити як отримане — додає котушки до запасу`,resetToPending:`Скинути до очікування`,remove:`Видалити`,clearAll:`Очистити все`,downloadCsv:`CSV`,addToCartTitle:`Додати до списку покупок`,byQuantity:`За кількістю`,byDuration:`За тривалістю`,numberOfSpools:`Кількість котушок`,lastHowManyDays:`Скільки днів має тривати?`,noUsageQty:`Немає даних про використання — кількість встановлено на 1.`,noteOptional:`Примітка (необов’язково)`,notePlaceholder:`напр. для проєкту X, терміново…`,addNSpools_one:`Додати котушки ({{count}})`,addNSpools_other:`Додати котушки ({{count}})`,onArrival:`Після прибуття`,stockBreakIn:`Запас вичерпається через {{days}} дн.`,stockRunsOutBefore:`Запас закінчиться раніше, ніж мине строк постачання {{lt}} дн.`,atRate:`За споживання {{rate}} г/день потрібно`,moreSpools_one:`Додаткових котушок: {{count}}`,moreSpools_other:`Додаткових котушок: {{count}}`,bridgeGap:`щоб покрити нестачу.`,noReadAccess:`Ви не маєте дозволу переглядати прогнози запасів.`,noWriteAccess:`Ви не маєте дозволу змінювати налаштування прогнозу.`}}}},Tt=[`en`,`de`,`es`,`fr`,`ja`,`it`,`ko`,`pt-BR`,`ru`,`tr`,`uk`,`zh-CN`,`zh-TW`],Et=`bambuddy_appliance_locale_consumed`;Ee.use(Ct).use(Ge).init({resources:wt,fallbackLng:`en`,supportedLngs:Tt,detection:{order:[`localStorage`,`navigator`,`htmlTag`],lookupLocalStorage:`bambutrack_language`,caches:[`localStorage`]},interpolation:{escapeValue:!1},react:{useSuspense:!1}});function Dt(){if(typeof window>`u`||!window.localStorage)return;let e=window.localStorage;typeof e.getItem!=`function`||typeof e.setItem!=`function`||e.getItem(Et)||fetch(`/api/v1/system/appliance`).then(e=>e.ok?e.json():null).then(t=>{!t||typeof t.locale!=`string`||Tt.includes(t.locale)&&(Ee.changeLanguage(t.locale),e.setItem(Et,`1`))}).catch(()=>{})}Dt();var Ot=[{code:`en`,name:`English`,nativeName:`English`},{code:`de`,name:`German`,nativeName:`Deutsch`},{code:`es`,name:`Spanish`,nativeName:`Español`},{code:`fr`,name:`French`,nativeName:`Français`},{code:`ja`,name:`Japanese`,nativeName:`日本語`},{code:`it`,name:`Italian`,nativeName:`Italiano`},{code:`ko`,name:`Korean`,nativeName:`한국어`},{code:`pt-BR`,name:`Portuguese (Brazil)`,nativeName:`Português (Brasil)`},{code:`zh-CN`,name:`Chinese (Simplified)`,nativeName:`简体中文`},{code:`zh-TW`,name:`Chinese (Traditional)`,nativeName:`繁體中文`},{code:`tr`,name:`Turkish`,nativeName:`Türkçe`},{code:`ru`,name:`Russian`,nativeName:`Русский`},{code:`uk`,name:`Ukrainian`,nativeName:`Українська`}],kt=`modulepreload`,At=function(e){return`/`+e},jt={},Mt=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}r=o(t.map(t=>{if(t=At(t,n),t in jt)return;jt[t]=!0;let r=t.endsWith(`.css`),i=r?`[rel="stylesheet"]`:``;if(n)for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}else if(document.querySelector(`link[href="${t}"]${i}`))return;let o=document.createElement(`link`);if(o.rel=r?`stylesheet`:kt,r||(o.as=`script`),o.crossOrigin=``,o.href=t,a&&o.setAttribute(`nonce`,a),document.head.appendChild(o),r)return new Promise((e,n)=>{o.addEventListener(`load`,e),o.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},Nt=/^(?:[a-z][a-z0-9+.-]*:|[\\/]{2})/i,Pt=/^[\\/]{2}/;function Ft(e,t){return t+e.replace(/\\/g,`/`)}var It=`popstate`;function Lt(e){return typeof e==`object`&&!!e&&`pathname`in e&&`search`in e&&`hash`in e&&`state`in e&&`key`in e}function G(e={}){function t(e,t){let n=t.state?.masked,{pathname:r,search:i,hash:a}=n||e.location;return Ht(``,{pathname:r,search:i,hash:a},t.state&&t.state.usr||null,t.state&&t.state.key||`default`,n?{pathname:e.location.pathname,search:e.location.search,hash:e.location.hash}:void 0)}function n(e,t){return typeof t==`string`?t:Ut(t)}return Gt(t,n,null,e)}function Rt(e,t){if(e===!1||e==null)throw Error(t)}function zt(e,t){if(!e){typeof console<`u`&&console.warn(t);try{throw Error(t)}catch{}}}function Bt(){return Math.random().toString(36).substring(2,10)}function Vt(e,t){return{usr:e.state,key:e.key,idx:t,masked:e.mask?{pathname:e.pathname,search:e.search,hash:e.hash}:void 0}}function Ht(e,t,n=null,r,i){return{pathname:typeof e==`string`?e:e.pathname,search:``,hash:``,...typeof t==`string`?Wt(t):t,state:n,key:t&&t.key||r||Bt(),mask:i}}function Ut({pathname:e=`/`,search:t=``,hash:n=``}){return t&&t!==`?`&&(e+=t.charAt(0)===`?`?t:`?`+t),n&&n!==`#`&&(e+=n.charAt(0)===`#`?n:`#`+n),e}function Wt(e){let t={};if(e){let n=e.indexOf(`#`);n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf(`?`);r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function Gt(e,t,n,r={}){let{window:i=document.defaultView,v5Compat:a=!1}=r,o=i.history,s=`POP`,c=null,l=u();l??(l=0,o.replaceState({...o.state,idx:l},``));function u(){return(o.state||{idx:null}).idx}function d(){s=`POP`;let e=u(),t=e==null?null:e-l;l=e,c&&c({action:s,location:h.location,delta:t})}function f(e,t){s=`PUSH`;let r=Lt(e)?e:Ht(h.location,e,t);n&&n(r,e),l=u()+1;let d=Vt(r,l),f=h.createHref(r.mask||r);try{o.pushState(d,``,f)}catch(e){if(e instanceof DOMException&&e.name===`DataCloneError`)throw e;i.location.assign(f)}a&&c&&c({action:s,location:h.location,delta:1})}function p(e,t){s=`REPLACE`;let r=Lt(e)?e:Ht(h.location,e,t);n&&n(r,e),l=u();let i=Vt(r,l),d=h.createHref(r.mask||r);o.replaceState(i,``,d),a&&c&&c({action:s,location:h.location,delta:0})}function m(e){return Kt(i,e)}let h={get action(){return s},get location(){return e(i,o)},listen(e){if(c)throw Error(`A history only accepts one active listener`);return i.addEventListener(It,d),c=e,()=>{i.removeEventListener(It,d),c=null}},createHref(e){return t(i,e)},createURL:m,encodeLocation(e){let t=m(e);return{pathname:t.pathname,search:t.search,hash:t.hash}},push:f,replace:p,go(e){return o.go(e)}};return h}function Kt(e,t,n=!1){let r=`http://localhost`;e&&(r=e.location.origin===`null`?e.location.href:e.location.origin),Rt(r,`No window.location.(origin|href) available to create URL`);let i=typeof t==`string`?t:Ut(t);return i=i.replace(/ $/,`%20`),!n&&Pt.test(i)&&(i=r+i),new URL(i,r)}function qt(e,t,n=`/`){return Jt(e,t,n,!1)}function Jt(e,t,n,r,i){let a=hn((typeof t==`string`?Wt(t):t).pathname||`/`,n);if(a==null)return null;let o=i??Xt(e),s=null,c=mn(a);for(let e=0;s==null&&e{let c={relativePath:s===void 0?e.path||``:s,caseSensitive:e.caseSensitive===!0,childrenIndex:a,route:e};if(c.relativePath.startsWith(`/`)){if(!c.relativePath.startsWith(r)&&o)return;Rt(c.relativePath.startsWith(r),`Absolute route path "${c.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),c.relativePath=c.relativePath.slice(r.length)}let l=Cn([r,c.relativePath]),u=n.concat(c);e.children&&e.children.length>0&&(Rt(e.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${l}".`),Zt(e.children,t,u,l,o)),!(e.path==null&&!e.index)&&t.push({path:l,score:cn(l,e.index),routesMeta:u.map((e,t)=>{let[n,r]=pn(e.relativePath,e.caseSensitive,t===u.length-1);return{...e,matcher:n,compiledParams:r}})})};return e.forEach((e,t)=>{if(e.path===``||!e.path?.includes(`?`))a(e,t);else for(let n of Qt(e.path))a(e,t,!0,n)}),t}function Qt(e){let t=e.split(`/`);if(t.length===0)return[];let[n,...r]=t,i=n.endsWith(`?`),a=n.replace(/\?$/,``);if(r.length===0)return i?[a,``]:[a];let o=Qt(r.join(`/`)),s=[];return s.push(...o.map(e=>e===``?a:[a,e].join(`/`))),i&&s.push(...o),s.map(t=>e.startsWith(`/`)&&t===``?`/`:t)}function $t(e){e.sort((e,t)=>e.score===t.score?ln(e.routesMeta.map(e=>e.childrenIndex),t.routesMeta.map(e=>e.childrenIndex)):t.score-e.score)}var en=/^:[\w-]+$/,tn=3,nn=2,rn=1,an=10,on=-2,sn=e=>e===`*`;function cn(e,t){let n=e.split(`/`),r=n.length;return n.some(sn)&&(r+=on),t&&(r+=nn),n.filter(e=>!sn(e)).reduce((e,t)=>e+(en.test(t)?tn:t===``?rn:an),r)}function ln(e,t){return e.length===t.length&&e.slice(0,-1).every((e,n)=>e===t[n])?e[e.length-1]-t[t.length-1]:0}function un(e,t,n=!1){let{routesMeta:r}=e,i={},a=`/`,o=[];for(let e=0;e{if(t===`*`){let e=s[r]||``;o=a.slice(0,a.length-e.length).replace(/(.)\/+$/,`$1`)}let i=s[r];return n&&!i?e[t]=void 0:e[t]=(i||``).replace(/%2F/g,`/`),e},{}),pathname:a,pathnameBase:o,pattern:e}}function pn(e,t=!1,n=!0){zt(e===`*`||!e.endsWith(`*`)||e.endsWith(`/*`),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,`/*`)}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,`/*`)}".`);let r=[],i=`^`+e.replace(/\/*\*?$/,``).replace(/^\/*/,`/`).replace(/[\\.*+^${}|()[\]]/g,`\\$&`).replace(/\/:([\w-]+)(\?)?/g,(e,t,n,i,a)=>{if(r.push({paramName:t,isOptional:n!=null}),n){let t=a.charAt(i+e.length);return t&&t!==`/`?`/([^\\/]*)`:`(?:/([^\\/]*))?`}return`/([^\\/]+)`}).replace(/\/([\w-]+)\?(\/|$)/g,`(/$1)?$2`);return e.endsWith(`*`)?(r.push({paramName:`*`}),i+=e===`*`||e===`/*`?`(.*)$`:`(?:\\/(.+)|\\/*)$`):n?i+=`\\/*$`:e!==``&&e!==`/`&&(i+=`(?:(?=\\/|$))`),[new RegExp(i,t?void 0:`i`),r]}function mn(e){try{return e.split(`/`).map(e=>decodeURIComponent(e).replace(/\//g,`%2F`)).join(`/`)}catch(t){return zt(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function hn(e,t){if(t===`/`)return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith(`/`)?t.length-1:t.length,r=e.charAt(n);return r&&r!==`/`?null:e.slice(n)||`/`}function gn(e,t=`/`){let{pathname:n,search:r=``,hash:i=``}=typeof e==`string`?Wt(e):e,a;return n?(n=Sn(n),a=n.startsWith(`/`)?_n(n.substring(1),`/`):_n(n,t)):a=t,{pathname:a,search:En(r),hash:Dn(i)}}function _n(e,t){let n=wn(t).split(`/`);return e.split(`/`).forEach(e=>{e===`..`?n.length>1&&n.pop():e!==`.`&&n.push(e)}),n.length>1?n.join(`/`):`/`}function vn(e,t,n,r){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function yn(e){return e.filter((e,t)=>t===0||e.route.path&&e.route.path.length>0)}function bn(e){let t=yn(e);return t.map((e,n)=>n===t.length-1?e.pathname:e.pathnameBase)}function xn(e,t,n,r=!1){let i;typeof e==`string`?i=Wt(e):(i={...e},Rt(!i.pathname||!i.pathname.includes(`?`),vn(`?`,`pathname`,`search`,i)),Rt(!i.pathname||!i.pathname.includes(`#`),vn(`#`,`pathname`,`hash`,i)),Rt(!i.search||!i.search.includes(`#`),vn(`#`,`search`,`hash`,i)));let a=e===``||i.pathname===``,o=a?`/`:i.pathname,s;if(o==null)s=n;else{let e=t.length-1;if(!r&&o.startsWith(`..`)){let t=o.split(`/`);for(;t[0]===`..`;)t.shift(),--e;i.pathname=t.join(`/`)}s=e>=0?t[e]:`/`}let c=gn(i,s),l=o&&o!==`/`&&o.endsWith(`/`),u=(a||o===`.`)&&n.endsWith(`/`);return!c.pathname.endsWith(`/`)&&(l||u)&&(c.pathname+=`/`),c}var Sn=e=>e.replace(/[\\/]{2,}/g,`/`),Cn=e=>Sn(e.join(`/`)),wn=e=>e.replace(/\/+$/,``),Tn=e=>wn(e).replace(/^\/*/,`/`),En=e=>!e||e===`?`?``:e.startsWith(`?`)?e:`?`+e,Dn=e=>!e||e===`#`?``:e.startsWith(`#`)?e:`#`+e,On=class{constructor(e,t,n,r=!1){this.status=e,this.statusText=t||``,this.internal=r,n instanceof Error?(this.data=n.toString(),this.error=n):this.data=n}};function kn(e){return e!=null&&typeof e.status==`number`&&typeof e.statusText==`string`&&typeof e.internal==`boolean`&&`data`in e}function An(e){return Cn(e.map(e=>e.route.path).filter(Boolean))||`/`}var jn=typeof window<`u`&&window.document!==void 0&&window.document.createElement!==void 0;function Mn(e,t){let n=e;if(typeof n!=`string`||!Nt.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let r=n,i=!1;if(jn)try{let e=new URL(window.location.href),r=Pt.test(n)?new URL(Ft(n,e.protocol)):new URL(n),a=hn(r.pathname,t);r.origin===e.origin&&a!=null?n=a+r.search+r.hash:i=!0}catch{zt(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:r,isExternal:i,to:n}}Object.getOwnPropertyNames(Object.prototype).sort().join(`\0`);var Nn=[`POST`,`PUT`,`PATCH`,`DELETE`];new Set(Nn);var Pn=[`GET`,...Nn];new Set(Pn);var Fn=[`about:`,`blob:`,`chrome:`,`chrome-untrusted:`,`content:`,`data:`,`devtools:`,`file:`,`filesystem:`,`javascript:`];function In(e){try{return Fn.includes(new URL(e).protocol)}catch{return!1}}var Ln=y.createContext(null);Ln.displayName=`DataRouter`;var Rn=y.createContext(null);Rn.displayName=`DataRouterState`;var zn=y.createContext(!1);function Bn(){return y.useContext(zn)}var Vn=y.createContext({isTransitioning:!1});Vn.displayName=`ViewTransition`;var Hn=y.createContext(new Map);Hn.displayName=`Fetchers`;var Un=y.createContext(null);Un.displayName=`Await`;var Wn=y.createContext(null);Wn.displayName=`Navigation`;var Gn=y.createContext(null);Gn.displayName=`Location`;var Kn=y.createContext({outlet:null,matches:[],isDataRoute:!1});Kn.displayName=`Route`;var qn=y.createContext(null);qn.displayName=`RouteError`;var Jn=`REACT_ROUTER_ERROR`,Yn=`REDIRECT`,Xn=`ROUTE_ERROR_RESPONSE`;function Zn(e){if(e.startsWith(`${Jn}:${Yn}:{`))try{let t=JSON.parse(e.slice(28));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`&&typeof t.location==`string`&&typeof t.reloadDocument==`boolean`&&typeof t.replace==`boolean`)return t}catch{}}function Qn(e){if(e.startsWith(`${Jn}:${Xn}:{`))try{let t=JSON.parse(e.slice(40));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`)return new On(t.status,t.statusText,t.data)}catch{}}function $n(e,{relative:t}={}){Rt(er(),`useHref() may be used only in the context of a component.`);let{basename:n,navigator:r}=y.useContext(Wn),{hash:i,pathname:a,search:o}=ur(e,{relative:t}),s=a;return n!==`/`&&(s=a===`/`?n:Cn([n,a])),r.createHref({pathname:s,search:o,hash:i})}function er(){return y.useContext(Gn)!=null}function tr(){return Rt(er(),`useLocation() may be used only in the context of a component.`),y.useContext(Gn).location}var nr=`You should call navigate() in a React.useEffect(), not when your component is first rendered.`;function rr(e){y.useContext(Wn).static||y.useLayoutEffect(e)}function ir(){let{isDataRoute:e}=y.useContext(Kn);return e?kr():ar()}function ar(){Rt(er(),`useNavigate() may be used only in the context of a component.`);let e=y.useContext(Ln),{basename:t,navigator:n}=y.useContext(Wn),{matches:r}=y.useContext(Kn),{pathname:i}=tr(),a=JSON.stringify(bn(r)),o=y.useRef(!1);return rr(()=>{o.current=!0}),y.useCallback((r,s={})=>{if(zt(o.current,nr),!o.current)return;if(typeof r==`number`){n.go(r);return}let c=xn(r,JSON.parse(a),i,s.relative===`path`);e==null&&t!==`/`&&(c.pathname=c.pathname===`/`?t:Cn([t,c.pathname])),(s.replace?n.replace:n.push)(c,s.state,s)},[t,n,a,i,e])}var or=y.createContext(null);function sr(){return y.useContext(or)}function cr(e){let t=y.useContext(Kn).outlet;return y.useMemo(()=>t&&y.createElement(or.Provider,{value:e},t),[t,e])}function lr(){let{matches:e}=y.useContext(Kn);return e[e.length-1]?.params??{}}function ur(e,{relative:t}={}){let{matches:n}=y.useContext(Kn),{pathname:r}=tr(),i=JSON.stringify(bn(n));return y.useMemo(()=>xn(e,JSON.parse(i),r,t===`path`),[e,i,r,t])}function dr(e,t){return fr(e,t)}function fr(e,t,n){Rt(er(),`useRoutes() may be used only in the context of a component.`);let{navigator:r}=y.useContext(Wn),{matches:i}=y.useContext(Kn),a=i[i.length-1],o=a?a.params:{},s=a?a.pathname:`/`,c=a?a.pathnameBase:`/`,l=a&&a.route;{let e=l&&l.path||``;jr(s,!l||e.endsWith(`*`)||e.endsWith(`*?`),`You rendered descendant (or called \`useRoutes()\`) at "${s}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. -Please change the parent to .`)}let u=tr(),d;if(t){let e=typeof t==`string`?Wt(t):t;Rt(c===`/`||e.pathname?.startsWith(c),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${c}" but pathname "${e.pathname}" was given in the \`location\` prop.`),d=e}else d=u;let f=d.pathname||`/`,p=f;if(c!==`/`){let e=c.replace(/^\//,``).split(`/`);p=`/`+f.replace(/^\//,``).split(`/`).slice(e.length).join(`/`)}let m=n&&n.state.matches.length?n.state.matches.map(e=>Object.assign(e,{route:n.manifest[e.route.id]||e.route})):qt(e,{pathname:p});zt(l||m!=null,`No routes matched location "${d.pathname}${d.search}${d.hash}" `),zt(m==null||m[m.length-1].route.element!==void 0||m[m.length-1].route.Component!==void 0||m[m.length-1].route.lazy!==void 0,`Matched leaf route at location "${d.pathname}${d.search}${d.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let h=yr(m&&m.map(e=>Object.assign({},e,{params:Object.assign({},o,e.params),pathname:Cn([c,r.encodeLocation?r.encodeLocation(e.pathname.replace(/%/g,`%25`).replace(/\?/g,`%3F`).replace(/#/g,`%23`)).pathname:e.pathname]),pathnameBase:e.pathnameBase===`/`?c:Cn([c,r.encodeLocation?r.encodeLocation(e.pathnameBase.replace(/%/g,`%25`).replace(/\?/g,`%3F`).replace(/#/g,`%23`)).pathname:e.pathnameBase])})),i,n);return t&&h?y.createElement(Gn.Provider,{value:{location:{pathname:`/`,search:``,hash:``,state:null,key:`default`,mask:void 0,...d},navigationType:`POP`}},h):h}function pr(){let e=Or(),t=kn(e)?`${e.status} ${e.statusText}`:e instanceof Error?e.message:JSON.stringify(e),n=e instanceof Error?e.stack:null,r=`rgba(200,200,200, 0.5)`,i={padding:`0.5rem`,backgroundColor:r},a={padding:`2px 4px`,backgroundColor:r},o=null;return console.error(`Error handled by React Router default ErrorBoundary:`,e),o=y.createElement(y.Fragment,null,y.createElement(`p`,null,`💿 Hey developer 👋`),y.createElement(`p`,null,`You can provide a way better UX than this when your app throws errors by providing your own `,y.createElement(`code`,{style:a},`ErrorBoundary`),` or`,` `,y.createElement(`code`,{style:a},`errorElement`),` prop on your route.`)),y.createElement(y.Fragment,null,y.createElement(`h2`,null,`Unexpected Application Error!`),y.createElement(`h3`,{style:{fontStyle:`italic`}},t),n?y.createElement(`pre`,{style:i},n):null,o)}var mr=y.createElement(pr,null),hr=class extends y.Component{constructor(e){super(e),this.state={location:e.location,revalidation:e.revalidation,error:e.error}}static getDerivedStateFromError(e){return{error:e}}static getDerivedStateFromProps(e,t){return t.location!==e.location||t.revalidation!==`idle`&&e.revalidation===`idle`?{error:e.error,location:e.location,revalidation:e.revalidation}:{error:e.error===void 0?t.error:e.error,location:t.location,revalidation:e.revalidation||t.revalidation}}componentDidCatch(e,t){this.props.onError?this.props.onError(e,t):console.error(`React Router caught the following error during render`,e)}render(){let e=this.state.error;if(this.context&&typeof e==`object`&&e&&`digest`in e&&typeof e.digest==`string`){let t=Qn(e.digest);t&&(e=t)}let t=e===void 0?this.props.children:y.createElement(Kn.Provider,{value:this.props.routeContext},y.createElement(qn.Provider,{value:e,children:this.props.component}));return this.context?y.createElement(_r,{error:e},t):t}};hr.contextType=zn;var gr=new WeakMap;function _r({children:e,error:t}){let{basename:n}=y.useContext(Wn);if(typeof t==`object`&&t&&`digest`in t&&typeof t.digest==`string`){let e=Zn(t.digest);if(e){let r=gr.get(t);if(r)throw r;let i=Mn(e.location,n),a=i.absoluteURL||i.to;if(In(a))throw Error(`Invalid redirect location`);if(jn&&!gr.get(t))if(i.isExternal||e.reloadDocument)window.location.href=a;else{let n=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(i.to,{replace:e.replace}));throw gr.set(t,n),n}return y.createElement(`meta`,{httpEquiv:`refresh`,content:`0;url=${a}`})}}return e}function vr({routeContext:e,match:t,children:n}){let r=y.useContext(Ln);return r&&r.static&&r.staticContext&&(t.route.errorElement||t.route.ErrorBoundary)&&(r.staticContext._deepestRenderedBoundaryId=t.route.id),y.createElement(Kn.Provider,{value:e},n)}function yr(e,t=[],n){let r=n?.state;if(e==null){if(!r)return null;if(r.errors)e=r.matches;else if(t.length===0&&!r.initialized&&r.matches.length>0)e=r.matches;else return null}let i=e,a=r?.errors;if(a!=null){let e=i.findIndex(e=>e.route.id&&a?.[e.route.id]!==void 0);Rt(e>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(a).join(`,`)}`),i=i.slice(0,Math.min(i.length,e+1))}let o=!1,s=-1;if(n&&r){o=r.renderFallback;for(let e=0;e=0?i.slice(0,s+1):[i[0]];break}}}}let c=n?.onError,l=r&&c?(e,t)=>{c(e,{location:r.location,params:r.matches?.[0]?.params??{},pattern:An(r.matches),errorInfo:t})}:void 0;return i.reduceRight((e,n,c)=>{let u,d=!1,f=null,p=null;r&&(u=a&&n.route.id?a[n.route.id]:void 0,f=n.route.errorElement||mr,o&&(s<0&&c===0?(jr(`route-fallback`,!1,"No `HydrateFallback` element provided to render during initial hydration"),d=!0,p=null):s===c&&(d=!0,p=n.route.hydrateFallbackElement||null)));let m=t.concat(i.slice(0,c+1)),h=()=>{let t;return t=u?f:d?p:n.route.Component?y.createElement(n.route.Component,null):n.route.element?n.route.element:e,y.createElement(vr,{match:n,routeContext:{outlet:e,matches:m,isDataRoute:r!=null},children:t})};return r&&(n.route.ErrorBoundary||n.route.errorElement||c===0)?y.createElement(hr,{location:r.location,revalidation:r.revalidation,component:f,error:u,children:h(),routeContext:{outlet:null,matches:m,isDataRoute:!0},onError:l}):h()},null)}function br(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function xr(e){let t=y.useContext(Ln);return Rt(t,br(e)),t}function Sr(e){let t=y.useContext(Rn);return Rt(t,br(e)),t}function Cr(e){let t=y.useContext(Kn);return Rt(t,br(e)),t}function wr(e){let t=Cr(e),n=t.matches[t.matches.length-1];return Rt(n.route.id,`${e} can only be used on routes that contain a unique "id"`),n.route.id}function Tr(){return wr(`useRouteId`)}function Er(){let e=Sr(`useNavigation`);return y.useMemo(()=>{let{matches:t,historyAction:n,...r}=e.navigation;return r},[e.navigation])}function Dr(){let{matches:e,loaderData:t}=Sr(`useMatches`);return y.useMemo(()=>e.map(e=>Yt(e,t)),[e,t])}function Or(){let e=y.useContext(qn),t=Sr(`useRouteError`),n=wr(`useRouteError`);return e===void 0?t.errors?.[n]:e}function kr(){let{router:e}=xr(`useNavigate`),t=wr(`useNavigate`),n=y.useRef(!1);return rr(()=>{n.current=!0}),y.useCallback(async(r,i={})=>{zt(n.current,nr),n.current&&(typeof r==`number`?await e.navigate(r):await e.navigate(r,{fromRouteId:t,...i}))},[e,t])}var Ar={};function jr(e,t,n){!t&&!Ar[e]&&(Ar[e]=!0,zt(!1,n))}y.memo(Mr);function Mr({routes:e,manifest:t,future:n,state:r,isStatic:i,onError:a}){return fr(e,void 0,{manifest:t,state:r,isStatic:i,onError:a,future:n})}function Nr({to:e,replace:t,state:n,relative:r}){Rt(er(),` may be used only in the context of a component.`);let{static:i}=y.useContext(Wn);zt(!i,` must not be used on the initial render in a . This is a no-op, but you should modify your code so the is only ever rendered in response to some user interaction or state change.`);let{matches:a}=y.useContext(Kn),{pathname:o}=tr(),s=ir(),c=xn(e,bn(a),o,r===`path`),l=JSON.stringify(c);return y.useEffect(()=>{s(JSON.parse(l),{replace:t,state:n,relative:r})},[s,l,r,t,n]),null}function Pr(e){return cr(e.context)}function Fr(e){Rt(!1,`A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .`)}function Ir({basename:e=`/`,children:t=null,location:n,navigationType:r=`POP`,navigator:i,static:a=!1,useTransitions:o}){Rt(!er(),`You cannot render a inside another . You should never have more than one in your app.`);let s=e.replace(/^\/*/,`/`),c=y.useMemo(()=>({basename:s,navigator:i,static:a,useTransitions:o,future:{}}),[s,i,a,o]);typeof n==`string`&&(n=Wt(n));let{pathname:l=`/`,search:u=``,hash:d=``,state:f=null,key:p=`default`,mask:m}=n,h=y.useMemo(()=>{let e=hn(l,s);return e==null?null:{location:{pathname:e,search:u,hash:d,state:f,key:p,mask:m},navigationType:r}},[s,l,u,d,f,p,r,m]);return zt(h!=null,` is not able to match the URL "${l}${u}${d}" because it does not start with the basename, so the won't render anything.`),h==null?null:y.createElement(Wn.Provider,{value:c},y.createElement(Gn.Provider,{children:t,value:h}))}function Lr({children:e,location:t}){return dr(Rr(e),t)}y.Component;function Rr(e,t=[]){let n=[];return y.Children.forEach(e,(e,r)=>{if(!y.isValidElement(e))return;let i=[...t,r];if(e.type===y.Fragment){n.push.apply(n,Rr(e.props.children,i));return}Rt(e.type===Fr,`[${typeof e.type==`string`?e.type:e.type.name}] is not a component. All component children of must be a or `),Rt(!e.props.index||!e.props.children,`An index route cannot have child routes.`);let a={id:e.props.id||i.join(`-`),caseSensitive:e.props.caseSensitive,element:e.props.element,Component:e.props.Component,index:e.props.index,path:e.props.path,middleware:e.props.middleware,loader:e.props.loader,action:e.props.action,hydrateFallbackElement:e.props.hydrateFallbackElement,HydrateFallback:e.props.HydrateFallback,errorElement:e.props.errorElement,ErrorBoundary:e.props.ErrorBoundary,hasErrorBoundary:e.props.hasErrorBoundary===!0||e.props.ErrorBoundary!=null||e.props.errorElement!=null,shouldRevalidate:e.props.shouldRevalidate,handle:e.props.handle,lazy:e.props.lazy};e.props.children&&(a.children=Rr(e.props.children,i)),n.push(a)}),n}var zr=`get`,Br=`application/x-www-form-urlencoded`;function Vr(e){return typeof HTMLElement<`u`&&e instanceof HTMLElement}function Hr(e){return Vr(e)&&e.tagName.toLowerCase()===`button`}function Ur(e){return Vr(e)&&e.tagName.toLowerCase()===`form`}function Wr(e){return Vr(e)&&e.tagName.toLowerCase()===`input`}function Gr(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function Kr(e,t){return e.button===0&&(!t||t===`_self`)&&!Gr(e)}function qr(e=``){return new URLSearchParams(typeof e==`string`||Array.isArray(e)||e instanceof URLSearchParams?e:Object.keys(e).reduce((t,n)=>{let r=e[n];return t.concat(Array.isArray(r)?r.map(e=>[n,e]):[[n,r]])},[]))}function Jr(e,t){let n=qr(e);return t&&t.forEach((e,r)=>{n.has(r)||t.getAll(r).forEach(e=>{n.append(r,e)})}),n}var Yr=null;function Xr(){if(Yr===null)try{new FormData(document.createElement(`form`),0),Yr=!1}catch{Yr=!0}return Yr}var Zr=new Set([`application/x-www-form-urlencoded`,`multipart/form-data`,`text/plain`]);function Qr(e){return e!=null&&!Zr.has(e)?(zt(!1,`"${e}" is not a valid \`encType\` for \`
\`/\`\` and will default to "${Br}"`),null):e}function $r(e,t){let n,r,i,a,o;if(Ur(e)){let o=e.getAttribute(`action`);r=o?hn(o,t):null,n=e.getAttribute(`method`)||zr,i=Qr(e.getAttribute(`enctype`))||Br,a=new FormData(e)}else if(Hr(e)||Wr(e)&&(e.type===`submit`||e.type===`image`)){let o=e.form;if(o==null)throw Error(`Cannot submit a