{const be=N&&fe!==x?fe:ie;this.options.missingKeyHandler?this.options.missingKeyHandler(W,d,ne,be,J,i):this.backendConnector?.saveMissing&&this.backendConnector.saveMissing(W,d,ne,be,J,i),this.emit("missingKey",W,d,ne,x)};this.options.saveMissing&&(this.options.saveMissingPlurals&&P?ce.forEach(W=>{const ne=this.pluralResolver.getSuffixes(W,i);F&&i[`defaultValue${this.options.pluralSeparator}zero`]&&ne.indexOf(`${this.options.pluralSeparator}zero`)<0&&ne.push(`${this.options.pluralSeparator}zero`),ne.forEach(fe=>{le([W],l+fe,i[`defaultValue${fe}`]||k)})}):le(ce,l,k))}x=this.extendTranslation(x,e,i,f,r),L&&x===l&&this.options.appendNamespaceToMissingKey&&(x=`${d}${u}${l}`),(L||X)&&this.options.parseMissingKeyHandler&&(x=this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey?`${d}${u}${l}`:l,X?x:void 0,i))}return s?(f.res=x,f.usedParams=this.getUsedParamsDetails(i),f):x}extendTranslation(e,n,r,i,s){if(this.i18nFormat?.parse)e=this.i18nFormat.parse(e,{...this.options.interpolation.defaultVariables,...r},r.lng||this.language||i.usedLng,i.usedNS,i.usedKey,{resolved:i});else if(!r.skipInterpolation){r.interpolation&&this.interpolator.init({...r,interpolation:{...this.options.interpolation,...r.interpolation}});const c=Hn(e)&&(r?.interpolation?.skipOnVariables!==void 0?r.interpolation.skipOnVariables:this.options.interpolation.skipOnVariables);let d;if(c){const m=e.match(this.interpolator.nestingRegexp);d=m&&m.length}let u=r.replace&&!Hn(r.replace)?r.replace:r;if(this.options.interpolation.defaultVariables&&(u={...this.options.interpolation.defaultVariables,...u}),e=this.interpolator.interpolate(e,u,r.lng||this.language||i.usedLng,r),c){const m=e.match(this.interpolator.nestingRegexp),p=m&&m.length;ds?.[0]===m[0]&&!r.context?(this.logger.warn(`It seems you are nesting recursively key: ${m[0]} in key: ${n[0]}`),null):this.translate(...m,n),r)),r.interpolation&&this.interpolator.reset()}const o=r.postProcess||this.options.postProcess,l=Hn(o)?[o]:o;return e!=null&&l?.length&&r.applyPostProcessor!==!1&&(e=IY.handle(l,e,n,this.options&&this.options.postProcessPassResolved?{i18nResolved:{...i,usedParams:this.getUsedParamsDetails(r)},...r}:r,this)),e}resolve(e,n={}){let r,i,s,o,l;return Hn(e)&&(e=[e]),e.forEach(c=>{if(this.isValidLookup(r))return;const d=this.extractFromKey(c,n),u=d.key;i=u;let m=d.namespaces;this.options.fallbackNS&&(m=m.concat(this.options.fallbackNS));const p=n.count!==void 0&&!Hn(n.count),f=p&&!n.ordinal&&n.count===0,x=n.context!==void 0&&(Hn(n.context)||typeof n.context=="number")&&n.context!=="",v=n.lngs?n.lngs:this.languageUtils.toResolveHierarchy(n.lng||this.language,n.fallbackLng);m.forEach(b=>{this.isValidLookup(r)||(l=b,!U8[`${v[0]}-${b}`]&&this.utils?.hasLoadedNamespace&&!this.utils?.hasLoadedNamespace(l)&&(U8[`${v[0]}-${b}`]=!0,this.logger.warn(`key "${i}" for languages "${v.join(", ")}" won't get resolved as namespace "${l}" 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!!!")),v.forEach(g=>{if(this.isValidLookup(r))return;o=g;const _=[u];if(this.i18nFormat?.addLookupKeys)this.i18nFormat.addLookupKeys(_,u,g,b,n);else{let P;p&&(P=this.pluralResolver.getSuffix(g,n.count,n));const N=`${this.options.pluralSeparator}zero`,A=`${this.options.pluralSeparator}ordinal${this.options.pluralSeparator}`;if(p&&(n.ordinal&&P.indexOf(A)===0&&_.push(u+P.replace(A,this.options.pluralSeparator)),_.push(u+P),f&&_.push(u+N)),x){const T=`${u}${this.options.contextSeparator||"_"}${n.context}`;_.push(T),p&&(n.ordinal&&P.indexOf(A)===0&&_.push(T+P.replace(A,this.options.pluralSeparator)),_.push(T+P),f&&_.push(T+N))}}let C;for(;C=_.pop();)this.isValidLookup(r)||(s=C,r=this.getResource(g,b,C,n))}))})}),{res:r,usedKey:i,exactUsedKey:s,usedLng:o,usedNS:l}}isValidLookup(e){return e!==void 0&&!(!this.options.returnNull&&e===null)&&!(!this.options.returnEmptyString&&e==="")}getResource(e,n,r,i={}){return this.i18nFormat?.getResource?this.i18nFormat.getResource(e,n,r,i):this.resourceStore.getResource(e,n,r,i)}getUsedParamsDetails(e={}){const n=["defaultValue","ordinal","context","replace","lng","lngs","fallbackLng","ns","keySeparator","nsSeparator","returnObjects","returnDetails","joinArrays","postProcess","interpolation"],r=e.replace&&!Hn(e.replace);let i=r?e.replace:e;if(r&&typeof e.count<"u"&&(i.count=e.count),this.options.interpolation.defaultVariables&&(i={...this.options.interpolation.defaultVariables,...i}),!r){i={...i};for(const s of n)delete i[s]}return i}static hasDefaultValue(e){const n="defaultValue";for(const r in e)if(Object.prototype.hasOwnProperty.call(e,r)&&n===r.substring(0,n.length)&&e[r]!==void 0)return!0;return!1}}class B8{constructor(e){this.options=e,this.supportedLngs=this.options.supportedLngs||!1,this.logger=Cd.create("languageUtils")}getScriptPartFromCode(e){if(e=G0(e),!e||e.indexOf("-")<0)return null;const n=e.split("-");return n.length===2||(n.pop(),n[n.length-1].toLowerCase()==="x")?null:this.formatLanguageCode(n.join("-"))}getLanguagePartFromCode(e){if(e=G0(e),!e||e.indexOf("-")<0)return e;const n=e.split("-");return this.formatLanguageCode(n[0])}formatLanguageCode(e){if(Hn(e)&&e.indexOf("-")>-1){let n;try{n=Intl.getCanonicalLocales(e)[0]}catch{}return n&&this.options.lowerCaseLng&&(n=n.toLowerCase()),n||(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 n;return e.forEach(r=>{if(n)return;const i=this.formatLanguageCode(r);(!this.options.supportedLngs||this.isSupportedCode(i))&&(n=i)}),!n&&this.options.supportedLngs&&e.forEach(r=>{if(n)return;const i=this.getScriptPartFromCode(r);if(this.isSupportedCode(i))return n=i;const s=this.getLanguagePartFromCode(r);if(this.isSupportedCode(s))return n=s;n=this.options.supportedLngs.find(o=>{if(o===s)return o;if(!(o.indexOf("-")<0&&s.indexOf("-")<0)&&(o.indexOf("-")>0&&s.indexOf("-")<0&&o.substring(0,o.indexOf("-"))===s||o.indexOf(s)===0&&s.length>1))return o})}),n||(n=this.getFallbackCodes(this.options.fallbackLng)[0]),n}getFallbackCodes(e,n){if(!e)return[];if(typeof e=="function"&&(e=e(n)),Hn(e)&&(e=[e]),Array.isArray(e))return e;if(!n)return e.default||[];let r=e[n];return r||(r=e[this.getScriptPartFromCode(n)]),r||(r=e[this.formatLanguageCode(n)]),r||(r=e[this.getLanguagePartFromCode(n)]),r||(r=e.default),r||[]}toResolveHierarchy(e,n){const r=this.getFallbackCodes((n===!1?[]:n)||this.options.fallbackLng||[],e),i=[],s=o=>{o&&(this.isSupportedCode(o)?i.push(o):this.logger.warn(`rejecting language code not found in supportedLngs: ${o}`))};return Hn(e)&&(e.indexOf("-")>-1||e.indexOf("_")>-1)?(this.options.load!=="languageOnly"&&s(this.formatLanguageCode(e)),this.options.load!=="languageOnly"&&this.options.load!=="currentOnly"&&s(this.getScriptPartFromCode(e)),this.options.load!=="currentOnly"&&s(this.getLanguagePartFromCode(e))):Hn(e)&&s(this.formatLanguageCode(e)),r.forEach(o=>{i.indexOf(o)<0&&s(this.formatLanguageCode(o))}),i}}const H8={zero:0,one:1,two:2,few:3,many:4,other:5},q8={select:t=>t===1?"one":"other",resolvedOptions:()=>({pluralCategories:["one","other"]})};class nue{constructor(e,n={}){this.languageUtils=e,this.options=n,this.logger=Cd.create("pluralResolver"),this.pluralRulesCache={}}addRule(e,n){this.rules[e]=n}clearCache(){this.pluralRulesCache={}}getRule(e,n={}){const r=G0(e==="dev"?"en":e),i=n.ordinal?"ordinal":"cardinal",s=JSON.stringify({cleanedCode:r,type:i});if(s in this.pluralRulesCache)return this.pluralRulesCache[s];let o;try{o=new Intl.PluralRules(r,{type:i})}catch{if(!Intl)return this.logger.error("No Intl support, please use an Intl polyfill!"),q8;if(!e.match(/-|_/))return q8;const c=this.languageUtils.getLanguagePartFromCode(e);o=this.getRule(c,n)}return this.pluralRulesCache[s]=o,o}needsPlural(e,n={}){let r=this.getRule(e,n);return r||(r=this.getRule("dev",n)),r?.resolvedOptions().pluralCategories.length>1}getPluralFormsOfKey(e,n,r={}){return this.getSuffixes(e,r).map(i=>`${n}${i}`)}getSuffixes(e,n={}){let r=this.getRule(e,n);return r||(r=this.getRule("dev",n)),r?r.resolvedOptions().pluralCategories.sort((i,s)=>H8[i]-H8[s]).map(i=>`${this.options.prepend}${n.ordinal?`ordinal${this.options.prepend}`:""}${i}`):[]}getSuffix(e,n,r={}){const i=this.getRule(e,r);return i?`${this.options.prepend}${r.ordinal?`ordinal${this.options.prepend}`:""}${i.select(n)}`:(this.logger.warn(`no plural rule found for: ${e}`),this.getSuffix("dev",n,r))}}const $8=(t,e,n,r=".",i=!0)=>{let s=Wde(t,e,n);return!s&&i&&Hn(n)&&(s=R3(t,n,r),s===void 0&&(s=R3(e,n,r))),s},gM=t=>t.replace(/\$/g,"$$$$");class rue{constructor(e={}){this.logger=Cd.create("interpolator"),this.options=e,this.format=e?.interpolation?.format||(n=>n),this.init(e)}init(e={}){e.interpolation||(e.interpolation={escapeValue:!0});const{escape:n,escapeValue:r,useRawValueToEscape:i,prefix:s,prefixEscaped:o,suffix:l,suffixEscaped:c,formatSeparator:d,unescapeSuffix:u,unescapePrefix:m,nestingPrefix:p,nestingPrefixEscaped:f,nestingSuffix:x,nestingSuffixEscaped:v,nestingOptionsSeparator:b,maxReplaces:g,alwaysFormat:_}=e.interpolation;this.escape=n!==void 0?n:Xde,this.escapeValue=r!==void 0?r:!0,this.useRawValueToEscape=i!==void 0?i:!1,this.prefix=s?ub(s):o||"{{",this.suffix=l?ub(l):c||"}}",this.formatSeparator=d||",",this.unescapePrefix=u?"":m||"-",this.unescapeSuffix=this.unescapePrefix?"":u||"",this.nestingPrefix=p?ub(p):f||ub("$t("),this.nestingSuffix=x?ub(x):v||ub(")"),this.nestingOptionsSeparator=b||",",this.maxReplaces=g||1e3,this.alwaysFormat=_!==void 0?_:!1,this.resetRegExp()}reset(){this.options&&this.init(this.options)}resetRegExp(){const e=(n,r)=>n?.source===r?(n.lastIndex=0,n):new RegExp(r,"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,n,r,i){let s,o,l;const c=this.options&&this.options.interpolation&&this.options.interpolation.defaultVariables||{},d=f=>{if(f.indexOf(this.formatSeparator)<0){const g=$8(n,c,f,this.options.keySeparator,this.options.ignoreJSONStructure);return this.alwaysFormat?this.format(g,void 0,r,{...i,...n,interpolationkey:f}):g}const x=f.split(this.formatSeparator),v=x.shift().trim(),b=x.join(this.formatSeparator).trim();return this.format($8(n,c,v,this.options.keySeparator,this.options.ignoreJSONStructure),b,r,{...i,...n,interpolationkey:v})};this.resetRegExp();const u=i?.missingInterpolationHandler||this.options.missingInterpolationHandler,m=i?.interpolation?.skipOnVariables!==void 0?i.interpolation.skipOnVariables:this.options.interpolation.skipOnVariables;return[{regex:this.regexpUnescape,safeValue:f=>gM(f)},{regex:this.regexp,safeValue:f=>this.escapeValue?gM(this.escape(f)):gM(f)}].forEach(f=>{for(l=0;s=f.regex.exec(e);){const x=s[1].trim();if(o=d(x),o===void 0)if(typeof u=="function"){const b=u(e,s,i);o=Hn(b)?b:""}else if(i&&Object.prototype.hasOwnProperty.call(i,x))o="";else if(m){o=s[0];continue}else this.logger.warn(`missed to pass in variable ${x} for interpolating ${e}`),o="";else!Hn(o)&&!this.useRawValueToEscape&&(o=R8(o));const v=f.safeValue(o);if(e=e.replace(s[0],v),m?(f.regex.lastIndex+=o.length,f.regex.lastIndex-=s[0].length):f.regex.lastIndex=0,l++,l>=this.maxReplaces)break}}),e}nest(e,n,r={}){let i,s,o;const l=(c,d)=>{const u=this.nestingOptionsSeparator;if(c.indexOf(u)<0)return c;const m=c.split(new RegExp(`${u}[ ]*{`));let p=`{${m[1]}`;c=m[0],p=this.interpolate(p,o);const f=p.match(/'/g),x=p.match(/"/g);((f?.length??0)%2===0&&!x||x.length%2!==0)&&(p=p.replace(/'/g,'"'));try{o=JSON.parse(p),d&&(o={...d,...o})}catch(v){return this.logger.warn(`failed parsing options string in nesting for key ${c}`,v),`${c}${u}${p}`}return o.defaultValue&&o.defaultValue.indexOf(this.prefix)>-1&&delete o.defaultValue,c};for(;i=this.nestingRegexp.exec(e);){let c=[];o={...r},o=o.replace&&!Hn(o.replace)?o.replace:o,o.applyPostProcessor=!1,delete o.defaultValue;const d=/{.*}/.test(i[1])?i[1].lastIndexOf("}")+1:i[1].indexOf(this.formatSeparator);if(d!==-1&&(c=i[1].slice(d).split(this.formatSeparator).map(u=>u.trim()).filter(Boolean),i[1]=i[1].slice(0,d)),s=n(l.call(this,i[1].trim(),o),o),s&&i[0]===e&&!Hn(s))return s;Hn(s)||(s=R8(s)),s||(this.logger.warn(`missed to resolve ${i[1]} for nesting ${e}`),s=""),c.length&&(s=c.reduce((u,m)=>this.format(u,m,r.lng,{...r,interpolationkey:i[1].trim()}),s.trim())),e=e.replace(i[0],s),this.regexp.lastIndex=0}return e}}const aue=t=>{let e=t.toLowerCase().trim();const n={};if(t.indexOf("(")>-1){const r=t.split("(");e=r[0].toLowerCase().trim();const i=r[1].substring(0,r[1].length-1);e==="currency"&&i.indexOf(":")<0?n.currency||(n.currency=i.trim()):e==="relativetime"&&i.indexOf(":")<0?n.range||(n.range=i.trim()):i.split(";").forEach(o=>{if(o){const[l,...c]=o.split(":"),d=c.join(":").trim().replace(/^'+|'+$/g,""),u=l.trim();n[u]||(n[u]=d),d==="false"&&(n[u]=!1),d==="true"&&(n[u]=!0),isNaN(d)||(n[u]=parseInt(d,10))}})}return{formatName:e,formatOptions:n}},V8=t=>{const e={};return(n,r,i)=>{let s=i;i&&i.interpolationkey&&i.formatParams&&i.formatParams[i.interpolationkey]&&i[i.interpolationkey]&&(s={...s,[i.interpolationkey]:void 0});const o=r+JSON.stringify(s);let l=e[o];return l||(l=t(G0(r),i),e[o]=l),l(n)}},iue=t=>(e,n,r)=>t(G0(n),r)(e);class sue{constructor(e={}){this.logger=Cd.create("formatter"),this.options=e,this.init(e)}init(e,n={interpolation:{}}){this.formatSeparator=n.interpolation.formatSeparator||",";const r=n.cacheInBuiltFormats?V8:iue;this.formats={number:r((i,s)=>{const o=new Intl.NumberFormat(i,{...s});return l=>o.format(l)}),currency:r((i,s)=>{const o=new Intl.NumberFormat(i,{...s,style:"currency"});return l=>o.format(l)}),datetime:r((i,s)=>{const o=new Intl.DateTimeFormat(i,{...s});return l=>o.format(l)}),relativetime:r((i,s)=>{const o=new Intl.RelativeTimeFormat(i,{...s});return l=>o.format(l,s.range||"day")}),list:r((i,s)=>{const o=new Intl.ListFormat(i,{...s});return l=>o.format(l)})}}add(e,n){this.formats[e.toLowerCase().trim()]=n}addCached(e,n){this.formats[e.toLowerCase().trim()]=V8(n)}format(e,n,r,i={}){const s=n.split(this.formatSeparator);if(s.length>1&&s[0].indexOf("(")>1&&s[0].indexOf(")")<0&&s.find(l=>l.indexOf(")")>-1)){const l=s.findIndex(c=>c.indexOf(")")>-1);s[0]=[s[0],...s.splice(1,l)].join(this.formatSeparator)}return s.reduce((l,c)=>{const{formatName:d,formatOptions:u}=aue(c);if(this.formats[d]){let m=l;try{const p=i?.formatParams?.[i.interpolationkey]||{},f=p.locale||p.lng||i.locale||i.lng||r;m=this.formats[d](l,f,{...u,...i,...p})}catch(p){this.logger.warn(p)}return m}else this.logger.warn(`there was no format function for ${d}`);return l},e)}}const oue=(t,e)=>{t.pending[e]!==void 0&&(delete t.pending[e],t.pendingCount--)};class lue extends EP{constructor(e,n,r,i={}){super(),this.backend=e,this.store=n,this.services=r,this.languageUtils=r.languageUtils,this.options=i,this.logger=Cd.create("backendConnector"),this.waitingReads=[],this.maxParallelReads=i.maxParallelReads||10,this.readingCalls=0,this.maxRetries=i.maxRetries>=0?i.maxRetries:5,this.retryTimeout=i.retryTimeout>=1?i.retryTimeout:350,this.state={},this.queue=[],this.backend?.init?.(r,i.backend,i)}queueLoad(e,n,r,i){const s={},o={},l={},c={};return e.forEach(d=>{let u=!0;n.forEach(m=>{const p=`${d}|${m}`;!r.reload&&this.store.hasResourceBundle(d,m)?this.state[p]=2:this.state[p]<0||(this.state[p]===1?o[p]===void 0&&(o[p]=!0):(this.state[p]=1,u=!1,o[p]===void 0&&(o[p]=!0),s[p]===void 0&&(s[p]=!0),c[m]===void 0&&(c[m]=!0)))}),u||(l[d]=!0)}),(Object.keys(s).length||Object.keys(o).length)&&this.queue.push({pending:o,pendingCount:Object.keys(o).length,loaded:{},errors:[],callback:i}),{toLoad:Object.keys(s),pending:Object.keys(o),toLoadLanguages:Object.keys(l),toLoadNamespaces:Object.keys(c)}}loaded(e,n,r){const i=e.split("|"),s=i[0],o=i[1];n&&this.emit("failedLoading",s,o,n),!n&&r&&this.store.addResourceBundle(s,o,r,void 0,void 0,{skipCopy:!0}),this.state[e]=n?-1:2,n&&r&&(this.state[e]=0);const l={};this.queue.forEach(c=>{Gde(c.loaded,[s],o),oue(c,e),n&&c.errors.push(n),c.pendingCount===0&&!c.done&&(Object.keys(c.loaded).forEach(d=>{l[d]||(l[d]={});const u=c.loaded[d];u.length&&u.forEach(m=>{l[d][m]===void 0&&(l[d][m]=!0)})}),c.done=!0,c.errors.length?c.callback(c.errors):c.callback())}),this.emit("loaded",l),this.queue=this.queue.filter(c=>!c.done)}read(e,n,r,i=0,s=this.retryTimeout,o){if(!e.length)return o(null,{});if(this.readingCalls>=this.maxParallelReads){this.waitingReads.push({lng:e,ns:n,fcName:r,tried:i,wait:s,callback:o});return}this.readingCalls++;const l=(d,u)=>{if(this.readingCalls--,this.waitingReads.length>0){const m=this.waitingReads.shift();this.read(m.lng,m.ns,m.fcName,m.tried,m.wait,m.callback)}if(d&&u&&i{this.read.call(this,e,n,r,i+1,s*2,o)},s);return}o(d,u)},c=this.backend[r].bind(this.backend);if(c.length===2){try{const d=c(e,n);d&&typeof d.then=="function"?d.then(u=>l(null,u)).catch(l):l(null,d)}catch(d){l(d)}return}return c(e,n,l)}prepareLoading(e,n,r={},i){if(!this.backend)return this.logger.warn("No backend was added via i18next.use. Will not load resources."),i&&i();Hn(e)&&(e=this.languageUtils.toResolveHierarchy(e)),Hn(n)&&(n=[n]);const s=this.queueLoad(e,n,r,i);if(!s.toLoad.length)return s.pending.length||i(),null;s.toLoad.forEach(o=>{this.loadOne(o)})}load(e,n,r){this.prepareLoading(e,n,{},r)}reload(e,n,r){this.prepareLoading(e,n,{reload:!0},r)}loadOne(e,n=""){const r=e.split("|"),i=r[0],s=r[1];this.read(i,s,"read",void 0,void 0,(o,l)=>{o&&this.logger.warn(`${n}loading namespace ${s} for language ${i} failed`,o),!o&&l&&this.logger.log(`${n}loaded namespace ${s} for language ${i}`,l),this.loaded(e,o,l)})}saveMissing(e,n,r,i,s,o={},l=()=>{}){if(this.services?.utils?.hasLoadedNamespace&&!this.services?.utils?.hasLoadedNamespace(n)){this.logger.warn(`did not save key "${r}" as the namespace "${n}" 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(!(r==null||r==="")){if(this.backend?.create){const c={...o,isUpdate:s},d=this.backend.create.bind(this.backend);if(d.length<6)try{let u;d.length===5?u=d(e,n,r,i,c):u=d(e,n,r,i),u&&typeof u.then=="function"?u.then(m=>l(null,m)).catch(l):l(null,u)}catch(u){l(u)}else d(e,n,r,i,l,c)}!e||!e[0]||this.store.addResource(e[0],n,r,i)}}}const G8=()=>({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:t=>{let e={};if(typeof t[1]=="object"&&(e=t[1]),Hn(t[1])&&(e.defaultValue=t[1]),Hn(t[2])&&(e.tDescription=t[2]),typeof t[2]=="object"||typeof t[3]=="object"){const n=t[3]||t[2];Object.keys(n).forEach(r=>{e[r]=n[r]})}return e},interpolation:{escapeValue:!0,format:t=>t,prefix:"{{",suffix:"}}",formatSeparator:",",unescapePrefix:"-",nestingPrefix:"$t(",nestingSuffix:")",nestingOptionsSeparator:",",maxReplaces:1e3,skipOnVariables:!0},cacheInBuiltFormats:!0}),W8=t=>(Hn(t.ns)&&(t.ns=[t.ns]),Hn(t.fallbackLng)&&(t.fallbackLng=[t.fallbackLng]),Hn(t.fallbackNS)&&(t.fallbackNS=[t.fallbackNS]),t.supportedLngs?.indexOf?.("cimode")<0&&(t.supportedLngs=t.supportedLngs.concat(["cimode"])),typeof t.initImmediate=="boolean"&&(t.initAsync=t.initImmediate),t),B_=()=>{},cue=t=>{Object.getOwnPropertyNames(Object.getPrototypeOf(t)).forEach(n=>{typeof t[n]=="function"&&(t[n]=t[n].bind(t))})};class v0 extends EP{constructor(e={},n){if(super(),this.options=W8(e),this.services={},this.logger=Cd,this.modules={external:[]},cue(this),n&&!this.isInitialized&&!e.isClone){if(!this.options.initAsync)return this.init(e,n),this;setTimeout(()=>{this.init(e,n)},0)}}init(e={},n){this.isInitializing=!0,typeof e=="function"&&(n=e,e={}),e.defaultNS==null&&e.ns&&(Hn(e.ns)?e.defaultNS=e.ns:e.ns.indexOf("translation")<0&&(e.defaultNS=e.ns[0]));const r=G8();this.options={...r,...this.options,...W8(e)},this.options.interpolation={...r.interpolation,...this.options.interpolation},e.keySeparator!==void 0&&(this.options.userDefinedKeySeparator=e.keySeparator),e.nsSeparator!==void 0&&(this.options.userDefinedNsSeparator=e.nsSeparator);const i=d=>d?typeof d=="function"?new d:d:null;if(!this.options.isClone){this.modules.logger?Cd.init(i(this.modules.logger),this.options):Cd.init(null,this.options);let d;this.modules.formatter?d=this.modules.formatter:d=sue;const u=new B8(this.options);this.store=new z8(this.options.resources,this.options);const m=this.services;m.logger=Cd,m.resourceStore=this.store,m.languageUtils=u,m.pluralResolver=new nue(u,{prepend:this.options.pluralSeparator,simplifyPluralSuffix:this.options.simplifyPluralSuffix}),this.options.interpolation.format&&this.options.interpolation.format!==r.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"),d&&(!this.options.interpolation.format||this.options.interpolation.format===r.interpolation.format)&&(m.formatter=i(d),m.formatter.init&&m.formatter.init(m,this.options),this.options.interpolation.format=m.formatter.format.bind(m.formatter)),m.interpolator=new rue(this.options),m.utils={hasLoadedNamespace:this.hasLoadedNamespace.bind(this)},m.backendConnector=new lue(i(this.modules.backend),m.resourceStore,m,this.options),m.backendConnector.on("*",(f,...x)=>{this.emit(f,...x)}),this.modules.languageDetector&&(m.languageDetector=i(this.modules.languageDetector),m.languageDetector.init&&m.languageDetector.init(m,this.options.detection,this.options)),this.modules.i18nFormat&&(m.i18nFormat=i(this.modules.i18nFormat),m.i18nFormat.init&&m.i18nFormat.init(this)),this.translator=new lN(this.services,this.options),this.translator.on("*",(f,...x)=>{this.emit(f,...x)}),this.modules.external.forEach(f=>{f.init&&f.init(this)})}if(this.format=this.options.interpolation.format,n||(n=B_),this.options.fallbackLng&&!this.services.languageDetector&&!this.options.lng){const d=this.services.languageUtils.getFallbackCodes(this.options.fallbackLng);d.length>0&&d[0]!=="dev"&&(this.options.lng=d[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(d=>{this[d]=(...u)=>this.store[d](...u)}),["addResource","addResources","addResourceBundle","removeResourceBundle"].forEach(d=>{this[d]=(...u)=>(this.store[d](...u),this)});const l=Sv(),c=()=>{const d=(u,m)=>{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),l.resolve(m),n(u,m)};if(this.languages&&!this.isInitialized)return d(null,this.t.bind(this));this.changeLanguage(this.options.lng,d)};return this.options.resources||!this.options.initAsync?c():setTimeout(c,0),l}loadResources(e,n=B_){let r=n;const i=Hn(e)?e:this.language;if(typeof e=="function"&&(r=e),!this.options.resources||this.options.partialBundledLanguages){if(i?.toLowerCase()==="cimode"&&(!this.options.preload||this.options.preload.length===0))return r();const s=[],o=l=>{if(!l||l==="cimode")return;this.services.languageUtils.toResolveHierarchy(l).forEach(d=>{d!=="cimode"&&s.indexOf(d)<0&&s.push(d)})};i?o(i):this.services.languageUtils.getFallbackCodes(this.options.fallbackLng).forEach(c=>o(c)),this.options.preload?.forEach?.(l=>o(l)),this.services.backendConnector.load(s,this.options.ns,l=>{!l&&!this.resolvedLanguage&&this.language&&this.setResolvedLanguage(this.language),r(l)})}else r(null)}reloadResources(e,n,r){const i=Sv();return typeof e=="function"&&(r=e,e=void 0),typeof n=="function"&&(r=n,n=void 0),e||(e=this.languages),n||(n=this.options.ns),r||(r=B_),this.services.backendConnector.reload(e,n,s=>{i.resolve(),r(s)}),i}use(e){if(!e)throw new Error("You are passing an undefined module! Please check the object you are passing to i18next.use()");if(!e.type)throw new 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"&&IY.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 n=0;n-1)&&this.store.hasLanguageSomeTranslations(r)){this.resolvedLanguage=r;break}}!this.resolvedLanguage&&this.languages.indexOf(e)<0&&this.store.hasLanguageSomeTranslations(e)&&(this.resolvedLanguage=e,this.languages.unshift(e))}}changeLanguage(e,n){this.isLanguageChangingTo=e;const r=Sv();this.emit("languageChanging",e);const i=l=>{this.language=l,this.languages=this.services.languageUtils.toResolveHierarchy(l),this.resolvedLanguage=void 0,this.setResolvedLanguage(l)},s=(l,c)=>{c?this.isLanguageChangingTo===e&&(i(c),this.translator.changeLanguage(c),this.isLanguageChangingTo=void 0,this.emit("languageChanged",c),this.logger.log("languageChanged",c)):this.isLanguageChangingTo=void 0,r.resolve((...d)=>this.t(...d)),n&&n(l,(...d)=>this.t(...d))},o=l=>{!e&&!l&&this.services.languageDetector&&(l=[]);const c=Hn(l)?l:l&&l[0],d=this.store.hasLanguageSomeTranslations(c)?c:this.services.languageUtils.getBestMatchFromCodes(Hn(l)?[l]:l);d&&(this.language||i(d),this.translator.language||this.translator.changeLanguage(d),this.services.languageDetector?.cacheUserLanguage?.(d)),this.loadResources(d,u=>{s(u,d)})};return!e&&this.services.languageDetector&&!this.services.languageDetector.async?o(this.services.languageDetector.detect()):!e&&this.services.languageDetector&&this.services.languageDetector.async?this.services.languageDetector.detect.length===0?this.services.languageDetector.detect().then(o):this.services.languageDetector.detect(o):o(e),r}getFixedT(e,n,r){const i=(s,o,...l)=>{let c;typeof o!="object"?c=this.options.overloadTranslationOptionHandler([s,o].concat(l)):c={...o},c.lng=c.lng||i.lng,c.lngs=c.lngs||i.lngs,c.ns=c.ns||i.ns,c.keyPrefix!==""&&(c.keyPrefix=c.keyPrefix||r||i.keyPrefix);const d=this.options.keySeparator||".";let u;return c.keyPrefix&&Array.isArray(s)?u=s.map(m=>(typeof m=="function"&&(m=L3(m,{...this.options,...o})),`${c.keyPrefix}${d}${m}`)):(typeof s=="function"&&(s=L3(s,{...this.options,...o})),u=c.keyPrefix?`${c.keyPrefix}${d}${s}`:s),this.t(u,c)};return Hn(e)?i.lng=e:i.lngs=e,i.ns=n,i.keyPrefix=r,i}t(...e){return this.translator?.translate(...e)}exists(...e){return this.translator?.exists(...e)}setDefaultNamespace(e){this.options.defaultNS=e}hasLoadedNamespace(e,n={}){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;const r=n.lng||this.resolvedLanguage||this.languages[0],i=this.options?this.options.fallbackLng:!1,s=this.languages[this.languages.length-1];if(r.toLowerCase()==="cimode")return!0;const o=(l,c)=>{const d=this.services.backendConnector.state[`${l}|${c}`];return d===-1||d===0||d===2};if(n.precheck){const l=n.precheck(this,o);if(l!==void 0)return l}return!!(this.hasResourceBundle(r,e)||!this.services.backendConnector.backend||this.options.resources&&!this.options.partialBundledLanguages||o(r,e)&&(!i||o(s,e)))}loadNamespaces(e,n){const r=Sv();return this.options.ns?(Hn(e)&&(e=[e]),e.forEach(i=>{this.options.ns.indexOf(i)<0&&this.options.ns.push(i)}),this.loadResources(i=>{r.resolve(),n&&n(i)}),r):(n&&n(),Promise.resolve())}loadLanguages(e,n){const r=Sv();Hn(e)&&(e=[e]);const i=this.options.preload||[],s=e.filter(o=>i.indexOf(o)<0&&this.services.languageUtils.isSupportedCode(o));return s.length?(this.options.preload=i.concat(s),this.loadResources(o=>{r.resolve(),n&&n(o)}),r):(n&&n(),Promise.resolve())}dir(e){if(e||(e=this.resolvedLanguage||(this.languages?.length>0?this.languages[0]:this.language)),!e)return"rtl";try{const i=new Intl.Locale(e);if(i&&i.getTextInfo){const s=i.getTextInfo();if(s&&s.direction)return s.direction}}catch{}const n=["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"],r=this.services?.languageUtils||new B8(G8());return e.toLowerCase().indexOf("-latn")>1?"ltr":n.indexOf(r.getLanguagePartFromCode(e))>-1||e.toLowerCase().indexOf("-arab")>1?"rtl":"ltr"}static createInstance(e={},n){const r=new v0(e,n);return r.createInstance=v0.createInstance,r}cloneInstance(e={},n=B_){const r=e.forkResourceStore;r&&delete e.forkResourceStore;const i={...this.options,...e,isClone:!0},s=new v0(i);if((e.debug!==void 0||e.prefix!==void 0)&&(s.logger=s.logger.clone(e)),["store","services","language"].forEach(l=>{s[l]=this[l]}),s.services={...this.services},s.services.utils={hasLoadedNamespace:s.hasLoadedNamespace.bind(s)},r){const l=Object.keys(this.store.data).reduce((c,d)=>(c[d]={...this.store.data[d]},c[d]=Object.keys(c[d]).reduce((u,m)=>(u[m]={...c[d][m]},u),c[d]),c),{});s.store=new z8(l,i),s.services.resourceStore=s.store}return s.translator=new lN(s.services,i),s.translator.on("*",(l,...c)=>{s.emit(l,...c)}),s.init(i,n),s.translator.options=i,s.translator.backendConnector.services.utils={hasLoadedNamespace:s.hasLoadedNamespace.bind(s)},s}toJSON(){return{options:this.options,store:this.store,language:this.language,languages:this.languages,resolvedLanguage:this.resolvedLanguage}}}const uo=v0.createInstance();uo.createInstance;uo.dir;uo.init;uo.loadResources;uo.reloadResources;uo.use;uo.changeLanguage;uo.getFixedT;uo.t;uo.exists;uo.setDefaultNamespace;uo.hasLoadedNamespace;uo.loadNamespaces;uo.loadLanguages;const due=(t,e,n,r)=>{const i=[n,{code:e,...r||{}}];if(t?.services?.logger?.forward)return t.services.logger.forward(i,"warn","react-i18next::",!0);Xf(i[0])&&(i[0]=`react-i18next:: ${i[0]}`),t?.services?.logger?.warn?t.services.logger.warn(...i):console?.warn&&console.warn(...i)},K8={},UY=(t,e,n,r)=>{Xf(n)&&K8[n]||(Xf(n)&&(K8[n]=new Date),due(t,e,n,r))},BY=(t,e)=>()=>{if(t.isInitialized)e();else{const n=()=>{setTimeout(()=>{t.off("initialized",n)},0),e()};t.on("initialized",n)}},O3=(t,e,n)=>{t.loadNamespaces(e,BY(t,n))},X8=(t,e,n,r)=>{if(Xf(n)&&(n=[n]),t.options.preload&&t.options.preload.indexOf(e)>-1)return O3(t,n,r);n.forEach(i=>{t.options.ns.indexOf(i)<0&&t.options.ns.push(i)}),t.loadLanguages(e,BY(t,r))},uue=(t,e,n={})=>!e.languages||!e.languages.length?(UY(e,"NO_LANGUAGES","i18n.languages were undefined or empty",{languages:e.languages}),!0):e.hasLoadedNamespace(t,{lng:n.lng,precheck:(r,i)=>{if(n.bindI18n&&n.bindI18n.indexOf("languageChanging")>-1&&r.services.backendConnector.backend&&r.isLanguageChangingTo&&!i(r.isLanguageChangingTo,t))return!1}}),Xf=t=>typeof t=="string",mue=t=>typeof t=="object"&&t!==null,hue=/&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34|nbsp|#160|copy|#169|reg|#174|hellip|#8230|#x2F|#47);/g,pue={"&":"&","&":"&","<":"<","<":"<",">":">",">":">","'":"'","'":"'",""":'"',""":'"'," ":" "," ":" ","©":"©","©":"©","®":"®","®":"®","…":"…","…":"…","/":"/","/":"/"},fue=t=>pue[t],gue=t=>t.replace(hue,fue);let I3={bindI18n:"languageChanged",bindI18nStore:"",transEmptyNodeValue:"",transSupportBasicHtmlNodes:!0,transWrapTextNodes:"",transKeepBasicHtmlNodesFor:["br","strong","i","p"],useSuspense:!0,unescape:gue,transDefaultProps:void 0};const bue=(t={})=>{I3={...I3,...t}},xue=()=>I3;let HY;const yue=t=>{HY=t},vue=()=>HY,wue={type:"3rdParty",init(t){bue(t.options.react),yue(t)}},Sue=w.createContext();class _ue{constructor(){this.usedNamespaces={}}addUsedNamespaces(e){e.forEach(n=>{this.usedNamespaces[n]||(this.usedNamespaces[n]=!0)})}getUsedNamespaces(){return Object.keys(this.usedNamespaces)}}var bM={exports:{}},xM={};var Y8;function kue(){if(Y8)return xM;Y8=1;var t=_g();function e(m,p){return m===p&&(m!==0||1/m===1/p)||m!==m&&p!==p}var n=typeof Object.is=="function"?Object.is:e,r=t.useState,i=t.useEffect,s=t.useLayoutEffect,o=t.useDebugValue;function l(m,p){var f=p(),x=r({inst:{value:f,getSnapshot:p}}),v=x[0].inst,b=x[1];return s(function(){v.value=f,v.getSnapshot=p,c(v)&&b({inst:v})},[m,f,p]),i(function(){return c(v)&&b({inst:v}),m(function(){c(v)&&b({inst:v})})},[m]),o(f),f}function c(m){var p=m.getSnapshot;m=m.value;try{var f=p();return!n(m,f)}catch{return!0}}function d(m,p){return p()}var u=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?d:l;return xM.useSyncExternalStore=t.useSyncExternalStore!==void 0?t.useSyncExternalStore:u,xM}var Q8;function qY(){return Q8||(Q8=1,bM.exports=kue()),bM.exports}var sO=qY();const Nue=(t,e)=>Xf(e)?e:mue(e)&&Xf(e.defaultValue)?e.defaultValue:Array.isArray(t)?t[t.length-1]:t,Cue={t:Nue,ready:!1},Pue=()=>()=>{},Ft=(t,e={})=>{const{i18n:n}=e,{i18n:r,defaultNS:i}=w.useContext(Sue)||{},s=n||r||vue();s&&!s.reportNamespaces&&(s.reportNamespaces=new _ue),s||UY(s,"NO_I18NEXT_INSTANCE","useTranslation: You will need to pass in an i18next instance by using initReactI18next");const o=w.useMemo(()=>({...xue(),...s?.options?.react,...e}),[s,e]),{useSuspense:l,keyPrefix:c}=o,d=i||s?.options?.defaultNS,u=Xf(d)?[d]:d||["translation"],m=w.useMemo(()=>u,u);s?.reportNamespaces?.addUsedNamespaces?.(m);const p=w.useRef(0),f=w.useCallback(k=>{if(!s)return Pue;const{bindI18n:D,bindI18nStore:H}=o,z=()=>{p.current+=1,k()};return D&&s.on(D,z),H&&s.store.on(H,z),()=>{D&&D.split(" ").forEach(X=>s.off(X,z)),H&&H.split(" ").forEach(X=>s.store.off(X,z))}},[s,o]),x=w.useRef(),v=w.useCallback(()=>{if(!s)return Cue;const k=!!(s.isInitialized||s.initializedStoreOnce)&&m.every(te=>uue(te,s,o)),D=e.lng||s.language,H=p.current,z=x.current;if(z&&z.ready===k&&z.lng===D&&z.keyPrefix===c&&z.revision===H)return z;const L={t:s.getFixedT(D,o.nsMode==="fallback"?m:m[0],c),ready:k,lng:D,keyPrefix:c,revision:H};return x.current=L,L},[s,m,c,o,e.lng]),[b,g]=w.useState(0),{t:_,ready:C}=sO.useSyncExternalStore(f,v,v);w.useEffect(()=>{if(s&&!C&&!l){const k=()=>g(D=>D+1);e.lng?X8(s,e.lng,m,k):O3(s,m,k)}},[s,e.lng,m,C,l,b]);const P=s||{},N=w.useRef(null),A=w.useRef(),T=k=>{const D=Object.getOwnPropertyDescriptors(k);D.__original&&delete D.__original;const H=Object.create(Object.getPrototypeOf(k),D);if(!Object.prototype.hasOwnProperty.call(H,"__original"))try{Object.defineProperty(H,"__original",{value:k,writable:!1,enumerable:!1,configurable:!1})}catch{}return H},F=w.useMemo(()=>{const k=P,D=k?.language;let H=k;k&&(N.current&&N.current.__original===k?A.current!==D?(H=T(k),N.current=H,A.current=D):H=N.current:(H=T(k),N.current=H,A.current=D));const z=[_,H,C];return z.t=_,z.i18n=H,z.ready=C,z},[_,P,C,P.resolvedLanguage,P.language,P.languages]);if(s&&l&&!C)throw new Promise(k=>{const D=()=>k();e.lng?X8(s,e.lng,m,D):O3(s,m,D)});return F},{slice:Tue,forEach:Aue}=[];function jue(t){return Aue.call(Tue.call(arguments,1),e=>{if(e)for(const n in e)t[n]===void 0&&(t[n]=e[n])}),t}function Mue(t){return typeof t!="string"?!1:[/<\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(n=>n.test(t))}const Z8=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/,Eue=function(t,e){const r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{path:"/"},i=encodeURIComponent(e);let s=`${t}=${i}`;if(r.maxAge>0){const o=r.maxAge-0;if(Number.isNaN(o))throw new Error("maxAge should be a Number");s+=`; Max-Age=${Math.floor(o)}`}if(r.domain){if(!Z8.test(r.domain))throw new TypeError("option domain is invalid");s+=`; Domain=${r.domain}`}if(r.path){if(!Z8.test(r.path))throw new TypeError("option path is invalid");s+=`; Path=${r.path}`}if(r.expires){if(typeof r.expires.toUTCString!="function")throw new TypeError("option expires is invalid");s+=`; Expires=${r.expires.toUTCString()}`}if(r.httpOnly&&(s+="; HttpOnly"),r.secure&&(s+="; Secure"),r.sameSite)switch(typeof r.sameSite=="string"?r.sameSite.toLowerCase():r.sameSite){case!0:s+="; SameSite=Strict";break;case"lax":s+="; SameSite=Lax";break;case"strict":s+="; SameSite=Strict";break;case"none":s+="; SameSite=None";break;default:throw new TypeError("option sameSite is invalid")}return r.partitioned&&(s+="; Partitioned"),s},J8={create(t,e,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=Eue(t,e,i)},read(t){const e=`${t}=`,n=document.cookie.split(";");for(let r=0;r-1&&(r=window.location.hash.substring(window.location.hash.indexOf("?")));const s=r.substring(1).split("&");for(let o=0;o0&&s[o].substring(0,l)===e&&(n=s[o].substring(l+1))}}return n}},Rue={name:"hash",lookup(t){let{lookupHash:e,lookupFromHashIndex:n}=t,r;if(typeof window<"u"){const{hash:i}=window.location;if(i&&i.length>2){const s=i.substring(1);if(e){const o=s.split("&");for(let l=0;l0&&o[l].substring(0,c)===e&&(r=o[l].substring(c+1))}}if(r)return r;if(!r&&n>-1){const o=i.match(/\/([a-zA-Z-]*)/g);return Array.isArray(o)?o[typeof n=="number"?n:0]?.replace("/",""):void 0}}}return r}};let mb=null;const eH=()=>{if(mb!==null)return mb;try{if(mb=typeof window<"u"&&window.localStorage!==null,!mb)return!1;const t="i18next.translate.boo";window.localStorage.setItem(t,"foo"),window.localStorage.removeItem(t)}catch{mb=!1}return mb};var Lue={name:"localStorage",lookup(t){let{lookupLocalStorage:e}=t;if(e&&eH())return window.localStorage.getItem(e)||void 0},cacheUserLanguage(t,e){let{lookupLocalStorage:n}=e;n&&eH()&&window.localStorage.setItem(n,t)}};let hb=null;const tH=()=>{if(hb!==null)return hb;try{if(hb=typeof window<"u"&&window.sessionStorage!==null,!hb)return!1;const t="i18next.translate.boo";window.sessionStorage.setItem(t,"foo"),window.sessionStorage.removeItem(t)}catch{hb=!1}return hb};var Oue={name:"sessionStorage",lookup(t){let{lookupSessionStorage:e}=t;if(e&&tH())return window.sessionStorage.getItem(e)||void 0},cacheUserLanguage(t,e){let{lookupSessionStorage:n}=e;n&&tH()&&window.sessionStorage.setItem(n,t)}},Iue={name:"navigator",lookup(t){const e=[];if(typeof navigator<"u"){const{languages:n,userLanguage:r,language:i}=navigator;if(n)for(let s=0;s0?e:void 0}},zue={name:"htmlTag",lookup(t){let{htmlTag:e}=t,n;const r=e||(typeof document<"u"?document.documentElement:null);return r&&typeof r.getAttribute=="function"&&(n=r.getAttribute("lang")),n}},Uue={name:"path",lookup(t){let{lookupFromPathIndex:e}=t;if(typeof window>"u")return;const n=window.location.pathname.match(/\/([a-zA-Z-]*)/g);return Array.isArray(n)?n[typeof e=="number"?e:0]?.replace("/",""):void 0}},Bue={name:"subdomain",lookup(t){let{lookupFromSubdomainIndex:e}=t;const n=typeof e=="number"?e+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]}};let $Y=!1;try{document.cookie,$Y=!0}catch{}const VY=["querystring","cookie","localStorage","sessionStorage","navigator","htmlTag"];$Y||VY.splice(1,1);const Hue=()=>({order:VY,lookupQuerystring:"lng",lookupCookie:"i18next",lookupLocalStorage:"i18nextLng",lookupSessionStorage:"i18nextLng",caches:["localStorage"],excludeCacheFor:["cimode"],convertDetectedLanguage:t=>t});class GY{constructor(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};this.type="languageDetector",this.detectors={},this.init(e,n)}init(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{languageUtils:{}},n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};this.services=e,this.options=jue(n,this.options||{},Hue()),typeof this.options.convertDetectedLanguage=="string"&&this.options.convertDetectedLanguage.indexOf("15897")>-1&&(this.options.convertDetectedLanguage=i=>i.replace("-","_")),this.options.lookupFromUrlIndex&&(this.options.lookupFromPathIndex=this.options.lookupFromUrlIndex),this.i18nOptions=r,this.addDetector(Due),this.addDetector(Fue),this.addDetector(Lue),this.addDetector(Oue),this.addDetector(Iue),this.addDetector(zue),this.addDetector(Uue),this.addDetector(Bue),this.addDetector(Rue)}addDetector(e){return this.detectors[e.name]=e,this}detect(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:this.options.order,n=[];return e.forEach(r=>{if(this.detectors[r]){let i=this.detectors[r].lookup(this.options);i&&typeof i=="string"&&(i=[i]),i&&(n=n.concat(i))}}),n=n.filter(r=>r!=null&&!Mue(r)).map(r=>this.options.convertDetectedLanguage(r)),this.services&&this.services.languageUtils&&this.services.languageUtils.getBestMatchFromCodes?n:n.length>0?n[0]:null}cacheUserLanguage(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:this.options.caches;n&&(this.options.excludeCacheFor&&this.options.excludeCacheFor.indexOf(e)>-1||n.forEach(r=>{this.detectors[r]&&this.detectors[r].cacheUserLanguage(e,this.options)}))}}GY.type="languageDetector";const que={nav:{printers:"Printers",archives:"Archives",queue:"Queue",stats:"Statistics",profiles:"Profiles",maintenance:"Maintenance",projects:"Projects",inventory:"Filament",files:"File Manager",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",smartSwitches:"Smart Switches",logout:"Logout"},common:{save:"Save",saving:"Saving...",cancel:"Cancel",delete:"Delete",edit:"Edit",add:"Add",close:"Close",confirm:"Confirm",loading:"Loading...",error:"Error",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",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",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"},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",ascending:"Sort ascending",descending:"Sort descending"},cardSize:{small:"Small cards",medium:"Medium cards",large:"Large cards",extraLarge:"Extra large cards"},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"},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",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}}",printerAdded:"Printer added",printerUpdated:"Printer updated",failedToDelete:"Failed to delete printer",failedToAdd:"Failed to add printer",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"},connection:{connected:"Connected",offline:"Offline"},queue:{inQueue:"{{count}} print in queue",inQueue_plural:"{{count}} prints in queue"},controls:"Controls",rfid:{reread:"Re-read RFID"},bedJog:{title:"Move build plate",bed:"Bed",step:"Step (mm)",up:"Move plate up",down:"Move plate down",disabledWhilePrinting:"Disabled while printing",notHomedTitle:"Printer is not homed",notHomedMessage:"The Z axis has not been homed since the last print. Home Z first for safe positioning, or move anyway — soft endstops will be bypassed.",homeZ:"Home Z",moveAnyway:"Move anyway",homingStarted:"Homing Z axis…"},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.'},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"},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"},drying:{start:"Start Drying",stop:"Stop Drying",temperature:"Temperature",duration:"Duration",hours:"hours",timeRemaining:"{{time}} left",active:"Drying",notSupported:"Drying not supported",powerRequired:"Connect AMS power adapter to enable drying",startingDrying:"Starting drying...",stoppingDrying:"Stopping drying...",rotateTray:"Rotate spool during drying"},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",chamber:"Chamber Fan"},clickToViewHmsErrors:"Click to view HMS errors",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",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",reprint:"Reprint",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",schedule:"Schedule",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",goToProject:"Go to Project: {{name}}",addToProject:"Add to Project",removeFromProject:"Remove from Project",loading:"Loading...",noProjectsAvailable:"No projects available",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",noCreate:"You do not have permission to create archives"},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}}",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",noPermissionEdit:"You do not have permission to edit archives",noPermissionDelete:"You do not have permission to delete archives",reprint:"Reprint",schedulePrint:"Schedule Print",schedule:"Schedule",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"},modal:{deleteArchive:"Delete Archive",deleteConfirm:'Are you sure you want to delete "{{name}}"? This action cannot be undone.',deleteButton:"Delete",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"}},queue:{title:"Print Queue",subtitle:"Schedule and manage your print jobs",addToQueue:"Add to Queue",print:"Print",reprint:"Re-print",schedulePrint:"Schedule Print",editQueueItem:"Edit Queue Item",printToPrinters:"Print to {{count}} Printers",queueToPrinters:"Queue to {{count}} Printers",queueSelectedPlates:"Queue {{count}} Plates",selectAllPlates:"Select All {{count}} Plates",deselectAll:"Deselect All",printQueued:"Print queued",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",clearPlate:"Clear Plate & Start Next",clearPlateSuccess:"Plate cleared — ready for next print",plateReady:"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:"Batch",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:{asap:"ASAP",overdue:"Overdue",now:"Now",lessThanMinute:"In less than a minute",inMinutes:"In {{count}} min",inHours:"In {{count}} hours"},actions:{stopPrint:"Stop Print",startPrint:"Start 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",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"},timeline:{listView:"List",timelineView:"Timeline",unassigned:"Unassigned",noData:"No scheduled prints for this day",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"}},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"}},backgroundDispatch:{unknownFile:"Unknown file",unknownPrinter:"Unknown printer",startingPrints:"Starting prints",progressSummary:"{{complete}}/{{total}} complete • Dispatched: {{dispatched}} • Processing: {{processing}}",expandDetails:"Expand dispatch details",collapseDetails:"Collapse dispatch details",dismissToast:"Dismiss dispatch toast",cancelDispatchJob:"Cancel dispatch job",cancel:"Cancel",cancelling:"Cancelling…",status:{dispatched:"Dispatched",processing:"Processing",completed:"Completed",failed:"Failed",cancelled:"Cancelled"},toast:{cancellingUpload:"Cancelling upload...",cancelled:"Dispatch cancelled",cancelFailed:"Failed to cancel dispatch",completeWithFailures:"Background dispatch complete: {{completed}} succeeded, {{failed}} failed",completeSuccess:"Background dispatch complete: {{completed}} succeeded",printStartedRemaining:"{{completed}} print(s) started, {{remaining}} more sending..."}},stats:{title:"Dashboard",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:",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",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",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"},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",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.",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.",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",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",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",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",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",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",staggeredStart:"Staggered Start",staggeredStartDescription:"Default group size and interval when staggering multi-printer batch starts. Can be overridden per batch in the print modal.",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. Disable for farm workflows where plates are verified physically.",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.",dryingPresets:"Drying Presets",dryingPresetsDescription:"Temperature and duration per filament type. AMS 2 Pro uses lower temps, AMS-HT supports higher temps.",dryingFilament:"Filament",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 (min 6 characters)",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:"Choose which slicer application to open files with",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 6 characters",enterGroupName:"Please enter a group name",settingsSaved:"Settings saved",cameraSettingsSaved:"Camera settings saved",enterCameraUrl:"Please enter a camera URL",passwordChanged:"Password changed successfully",connectionFailed:"Connection failed",testFailed:"Test failed",cameraConnected:"Camera connected{{resolution}}"},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"},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:"Drag items in the sidebar to reorder. Reset to default order here.",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 and light mode using the sun/moon icon in the sidebar.",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",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)",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:",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."},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.",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"}}},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",clearInstructions:"Clear errors on the printer to dismiss them here.",clearErrors:"Clear Errors",clearSuccess:"HMS errors cleared",clearFailed:"Failed to clear HMS errors"},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...",forgotPassword:"Forgot your password?",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"},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"}},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"},modal:{createUser:"Create User",editUser:"Edit User",cancel:"Cancel",creating:"Creating...",saving:"Saving...",saveChanges:"Save Changes",advancedAuthSubtitle:"with Advanced Authentication"},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:{cloud:"Cloud Profiles",local:"Local Profiles",kprofiles:"K-Profiles"},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",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",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 Lab access token (from Bambu Studio)",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"},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",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",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",addToQueue:"Add to Queue",schedulePrint:"Schedule",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",wrap:"Wrap",enableTextWrapping:"Enable text wrapping",disableTextWrapping:"Disable text wrapping",collapse:"Collapse",collapseFoldersByDefault:"Collapse folders by default",expandFoldersByDefault:"Expand folders by default",dragToResizeTooltip:"Drag to resize, double-click to reset",searchFiles:"Search files...",allTypes:"All types",prints:"Prints",ascending:"Ascending",descending:"Descending",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",noPermissionPrint:"You do not have permission to print",noPermissionAddToQueue:"You do not have permission to add to queue",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...",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",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",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.",noFiles:"No files in this folder.",print:"Print Now",addToQueue:"Add to Queue"},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"},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"},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:"Unlink Spool?",unlinkConfirmMessage:"This will disconnect the spool from Spoolman. The spool data in Spoolman will remain unchanged.",selectSpool:"Select Spool",noUnlinkedSpools:"No unlinked spools available",linkSuccess:"Spool linked to Spoolman successfully",linkFailed:"Failed to link spool",unlinkSuccess:"Spool unlinked from Spoolman successfully",unlinkFailed:"Failed to unlink 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."},inventory:{title:"Spool Inventory",addSpool:"Add Spool",editSpool:"Edit Spool",material:"Material",selectMaterial:"Select material...",subtype:"Subtype",brand:"Brand",searchBrand:"Search brand...",useCustomBrand:'Use "{{brand}}"',useCustomMaterial:"Use custom material: {{material}}",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",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...",archive:"Archive",restore:"Restore",noSpools:"No spools yet. Add your first spool to get started.",noManualSpools:"No manually added spools available. Add a spool to your inventory first.",kProfiles:"K-Profiles",addKProfile:"Add K-Profile",assignSpool:"Assign Spool",unassignSpool:"Unassign",assignSuccess:"Spool assigned and AMS slot configured",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",allMaterials:"All Materials",filterByBrand:"Filter by brand...",showArchived:"Show archived",quickAdd:"Quick Add (Stock)",quantity:"Quantity",stock:"Stock",configured:"Configured",spoolsCreated:"{{count}} spools created",spoolCreated:"Spool created",spoolUpdated:"Spool updated",spoolDeleted:"Spool deleted",spoolArchived:"Spool archived",spoolRestored:"Spool restored",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",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",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?'},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",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:{title:"Start Print",selectPrinter:"Select Printer",selectPlate:"Select Plate",filamentMapping:"Filament Mapping",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",startPrint:"Start Print",addToQueue:"Add to Queue",cancel:"Cancel",noPrintersAvailable:"No printers available",printerBusy:"Printer is busy",printerOffline:"Printer is offline",sameTypeDifferentColor:"Same type, different color",filamentTypeNotLoaded:"Filament type not loaded",openCalendar:"Open calendar",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",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:{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:"GitHub 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.",repositoryUrl:"Repository URL",personalAccessToken:"Personal Access Token",tokenSaved:"(saved)",enterNewToken:"Enter new token to update",tokenHint:"Fine-grained token with Contents read/write permission",branch:"Branch",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",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",utc:"UTC",defaultPathLabel:"Default:",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...",noFilamentsHelp:"No filaments found. Create a K-profile in Bambu Studio first.",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",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)"},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."},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"},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",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",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",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.
+`+M.stack}}var ie=Object.prototype.hasOwnProperty,ge=t.unstable_scheduleCallback,pe=t.unstable_cancelCallback,ce=t.unstable_shouldYield,B=t.unstable_requestPaint,R=t.unstable_now,re=t.unstable_getCurrentPriorityLevel,_e=t.unstable_ImmediatePriority,Se=t.unstable_UserBlockingPriority,ye=t.unstable_NormalPriority,Te=t.unstable_LowPriority,ve=t.unstable_IdlePriority,Ae=t.log,Re=t.unstable_setDisableYieldValue,Me=null,Le=null;function Oe(h){if(typeof Ae=="function"&&Re(h),Le&&typeof Le.setStrictMode=="function")try{Le.setStrictMode(Me,h)}catch{}}var qe=Math.clz32?Math.clz32:he,Qe=Math.log,nt=Math.LN2;function he(h){return h>>>=0,h===0?32:31-(Qe(h)/nt|0)|0}var Fe=256,we=262144,Ve=4194304;function je(h){var y=h&42;if(y!==0)return y;switch(h&-h){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 h&261888;case 262144:case 524288:case 1048576:case 2097152:return h&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return h&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return h}}function de(h,y,S){var M=h.pendingLanes;if(M===0)return 0;var $=0,Z=h.suspendedLanes,Ne=h.pingedLanes;h=h.warmLanes;var He=M&134217727;return He!==0?(M=He&~Z,M!==0?$=je(M):(Ne&=He,Ne!==0?$=je(Ne):S||(S=He&~h,S!==0&&($=je(S))))):(He=M&~Z,He!==0?$=je(He):Ne!==0?$=je(Ne):S||(S=M&~h,S!==0&&($=je(S)))),$===0?0:y!==0&&y!==$&&(y&Z)===0&&(Z=$&-$,S=y&-y,Z>=S||Z===32&&(S&4194048)!==0)?y:$}function xe(h,y){return(h.pendingLanes&~(h.suspendedLanes&~h.pingedLanes)&y)===0}function Be(h,y){switch(h){case 1:case 2:case 4:case 8:case 64:return y+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 y+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 Ze(){var h=Ve;return Ve<<=1,(Ve&62914560)===0&&(Ve=4194304),h}function pt(h){for(var y=[],S=0;31>S;S++)y.push(h);return y}function xt(h,y){h.pendingLanes|=y,y!==268435456&&(h.suspendedLanes=0,h.pingedLanes=0,h.warmLanes=0)}function yt(h,y,S,M,$,Z){var Ne=h.pendingLanes;h.pendingLanes=S,h.suspendedLanes=0,h.pingedLanes=0,h.warmLanes=0,h.expiredLanes&=S,h.entangledLanes&=S,h.errorRecoveryDisabledLanes&=S,h.shellSuspendCounter=0;var He=h.entanglements,rt=h.expirationTimes,Nt=h.hiddenUpdates;for(S=Ne&~S;0"u")return null;try{return h.activeElement||h.body}catch{return h.body}}var Mr=/[\n"\\]/g;function En(h){return h.replace(Mr,function(y){return"\\"+y.charCodeAt(0).toString(16)+" "})}function ja(h,y,S,M,$,Z,Ne,He){h.name="",Ne!=null&&typeof Ne!="function"&&typeof Ne!="symbol"&&typeof Ne!="boolean"?h.type=Ne:h.removeAttribute("type"),y!=null?Ne==="number"?(y===0&&h.value===""||h.value!=y)&&(h.value=""+zn(y)):h.value!==""+zn(y)&&(h.value=""+zn(y)):Ne!=="submit"&&Ne!=="reset"||h.removeAttribute("value"),y!=null?na(h,Ne,zn(y)):S!=null?na(h,Ne,zn(S)):M!=null&&h.removeAttribute("value"),$==null&&Z!=null&&(h.defaultChecked=!!Z),$!=null&&(h.checked=$&&typeof $!="function"&&typeof $!="symbol"),He!=null&&typeof He!="function"&&typeof He!="symbol"&&typeof He!="boolean"?h.name=""+zn(He):h.removeAttribute("name")}function Pn(h,y,S,M,$,Z,Ne,He){if(Z!=null&&typeof Z!="function"&&typeof Z!="symbol"&&typeof Z!="boolean"&&(h.type=Z),y!=null||S!=null){if(!(Z!=="submit"&&Z!=="reset"||y!=null)){gn(h);return}S=S!=null?""+zn(S):"",y=y!=null?""+zn(y):S,He||y===h.value||(h.value=y),h.defaultValue=y}M=M??$,M=typeof M!="function"&&typeof M!="symbol"&&!!M,h.checked=He?h.checked:!!M,h.defaultChecked=!!M,Ne!=null&&typeof Ne!="function"&&typeof Ne!="symbol"&&typeof Ne!="boolean"&&(h.name=Ne),gn(h)}function na(h,y,S){y==="number"&&hr(h.ownerDocument)===h||h.defaultValue===""+S||(h.defaultValue=""+S)}function Bn(h,y,S,M){if(h=h.options,y){y={};for(var $=0;$"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Em=!1;if(Bs)try{var Hs={};Object.defineProperty(Hs,"passive",{get:function(){Em=!0}}),window.addEventListener("test",Hs,Hs),window.removeEventListener("test",Hs,Hs)}catch{Em=!1}var Bo=null,fc=null,ed=null;function mo(){if(ed)return ed;var h,y=fc,S=y.length,M,$="value"in Bo?Bo.value:Bo.textContent,Z=$.length;for(h=0;h=Qt),Ja=" ",Yi=!1;function Sl(h,y){switch(h){case"keyup":return ua.indexOf(y.keyCode)!==-1;case"keydown":return y.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Ho(h){return h=h.detail,typeof h=="object"&&"data"in h?h.data:null}var qr=!1;function Qi(h,y){switch(h){case"compositionend":return Ho(y);case"keypress":return y.which!==32?null:(Yi=!0,Ja);case"textInput":return h=y.data,h===Ja&&Yi?null:h;default:return null}}function vc(h,y){if(qr)return h==="compositionend"||!ga&&Sl(h,y)?(h=mo(),ed=fc=Bo=null,qr=!1,h):null;switch(h){case"paste":return null;case"keypress":if(!(y.ctrlKey||y.altKey||y.metaKey)||y.ctrlKey&&y.altKey){if(y.char&&1=y)return{node:S,offset:y-h};h=M}e:{for(;S;){if(S.nextSibling){S=S.nextSibling;break e}S=S.parentNode}S=void 0}S=m5(S)}}function p5(h,y){return h&&y?h===y?!0:h&&h.nodeType===3?!1:y&&y.nodeType===3?p5(h,y.parentNode):"contains"in h?h.contains(y):h.compareDocumentPosition?!!(h.compareDocumentPosition(y)&16):!1:!1}function f5(h){h=h!=null&&h.ownerDocument!=null&&h.ownerDocument.defaultView!=null?h.ownerDocument.defaultView:window;for(var y=hr(h.document);y instanceof h.HTMLIFrameElement;){try{var S=typeof y.contentWindow.location.href=="string"}catch{S=!1}if(S)h=y.contentWindow;else break;y=hr(h.document)}return y}function xA(h){var y=h&&h.nodeName&&h.nodeName.toLowerCase();return y&&(y==="input"&&(h.type==="text"||h.type==="search"||h.type==="tel"||h.type==="url"||h.type==="password")||y==="textarea"||h.contentEditable==="true")}var mce=Bs&&"documentMode"in document&&11>=document.documentMode,Og=null,yA=null,By=null,vA=!1;function g5(h,y,S){var M=S.window===S?S.document:S.nodeType===9?S:S.ownerDocument;vA||Og==null||Og!==hr(M)||(M=Og,"selectionStart"in M&&xA(M)?M={start:M.selectionStart,end:M.selectionEnd}:(M=(M.ownerDocument&&M.ownerDocument.defaultView||window).getSelection(),M={anchorNode:M.anchorNode,anchorOffset:M.anchorOffset,focusNode:M.focusNode,focusOffset:M.focusOffset}),By&&Uy(By,M)||(By=M,M=N_(yA,"onSelect"),0>=Ne,$-=Ne,sd=1<<32-qe(y)+$|S<<$|M,od=Z+h}else sd=1<Qn?(xr=bn,bn=null):xr=bn.sibling;var Pr=Ct(bt,bn,kt[Qn],It);if(Pr===null){bn===null&&(bn=xr);break}h&&bn&&Pr.alternate===null&&y(bt,bn),mt=Z(Pr,mt,Qn),Cr===null?Cn=Pr:Cr.sibling=Pr,Cr=Pr,bn=xr}if(Qn===kt.length)return S(bt,bn),vr&&ru(bt,Qn),Cn;if(bn===null){for(;QnQn?(xr=bn,bn=null):xr=bn.sibling;var th=Ct(bt,bn,Pr.value,It);if(th===null){bn===null&&(bn=xr);break}h&&bn&&th.alternate===null&&y(bt,bn),mt=Z(th,mt,Qn),Cr===null?Cn=th:Cr.sibling=th,Cr=th,bn=xr}if(Pr.done)return S(bt,bn),vr&&ru(bt,Qn),Cn;if(bn===null){for(;!Pr.done;Qn++,Pr=kt.next())Pr=Ut(bt,Pr.value,It),Pr!==null&&(mt=Z(Pr,mt,Qn),Cr===null?Cn=Pr:Cr.sibling=Pr,Cr=Pr);return vr&&ru(bt,Qn),Cn}for(bn=M(bn);!Pr.done;Qn++,Pr=kt.next())Pr=Dt(bn,bt,Qn,Pr.value,It),Pr!==null&&(h&&Pr.alternate!==null&&bn.delete(Pr.key===null?Qn:Pr.key),mt=Z(Pr,mt,Qn),Cr===null?Cn=Pr:Cr.sibling=Pr,Cr=Pr);return h&&bn.forEach(function(Ede){return y(bt,Ede)}),vr&&ru(bt,Qn),Cn}function Wr(bt,mt,kt,It){if(typeof kt=="object"&&kt!==null&&kt.type===v&&kt.key===null&&(kt=kt.props.children),typeof kt=="object"&&kt!==null){switch(kt.$$typeof){case f:e:{for(var Cn=kt.key;mt!==null;){if(mt.key===Cn){if(Cn=kt.type,Cn===v){if(mt.tag===7){S(bt,mt.sibling),It=$(mt,kt.props.children),It.return=bt,bt=It;break e}}else if(mt.elementType===Cn||typeof Cn=="object"&&Cn!==null&&Cn.$$typeof===F&&qp(Cn)===mt.type){S(bt,mt.sibling),It=$(mt,kt.props),Wy(It,kt),It.return=bt,bt=It;break e}S(bt,mt);break}else y(bt,mt);mt=mt.sibling}kt.type===v?(It=Ip(kt.props.children,bt.mode,It,kt.key),It.return=bt,bt=It):(It=HS(kt.type,kt.key,kt.props,null,bt.mode,It),Wy(It,kt),It.return=bt,bt=It)}return Ne(bt);case x:e:{for(Cn=kt.key;mt!==null;){if(mt.key===Cn)if(mt.tag===4&&mt.stateNode.containerInfo===kt.containerInfo&&mt.stateNode.implementation===kt.implementation){S(bt,mt.sibling),It=$(mt,kt.children||[]),It.return=bt,bt=It;break e}else{S(bt,mt);break}else y(bt,mt);mt=mt.sibling}It=PA(kt,bt.mode,It),It.return=bt,bt=It}return Ne(bt);case F:return kt=qp(kt),Wr(bt,mt,kt,It)}if(te(kt))return hn(bt,mt,kt,It);if(z(kt)){if(Cn=z(kt),typeof Cn!="function")throw Error(r(150));return kt=Cn.call(kt),Rn(bt,mt,kt,It)}if(typeof kt.then=="function")return Wr(bt,mt,XS(kt),It);if(kt.$$typeof===C)return Wr(bt,mt,VS(bt,kt),It);YS(bt,kt)}return typeof kt=="string"&&kt!==""||typeof kt=="number"||typeof kt=="bigint"?(kt=""+kt,mt!==null&&mt.tag===6?(S(bt,mt.sibling),It=$(mt,kt),It.return=bt,bt=It):(S(bt,mt),It=CA(kt,bt.mode,It),It.return=bt,bt=It),Ne(bt)):S(bt,mt)}return function(bt,mt,kt,It){try{Gy=0;var Cn=Wr(bt,mt,kt,It);return Kg=null,Cn}catch(bn){if(bn===Wg||bn===WS)throw bn;var Cr=$o(29,bn,null,bt.mode);return Cr.lanes=It,Cr.return=bt,Cr}}}var Vp=z5(!0),U5=z5(!1),Im=!1;function zA(h){h.updateQueue={baseState:h.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function UA(h,y){h=h.updateQueue,y.updateQueue===h&&(y.updateQueue={baseState:h.baseState,firstBaseUpdate:h.firstBaseUpdate,lastBaseUpdate:h.lastBaseUpdate,shared:h.shared,callbacks:null})}function zm(h){return{lane:h,tag:0,payload:null,callback:null,next:null}}function Um(h,y,S){var M=h.updateQueue;if(M===null)return null;if(M=M.shared,(Er&2)!==0){var $=M.pending;return $===null?y.next=y:(y.next=$.next,$.next=y),M.pending=y,y=BS(h),_5(h,null,S),y}return US(h,M,y,S),BS(h)}function Ky(h,y,S){if(y=y.updateQueue,y!==null&&(y=y.shared,(S&4194048)!==0)){var M=y.lanes;M&=h.pendingLanes,S|=M,y.lanes=S,Xt(h,S)}}function BA(h,y){var S=h.updateQueue,M=h.alternate;if(M!==null&&(M=M.updateQueue,S===M)){var $=null,Z=null;if(S=S.firstBaseUpdate,S!==null){do{var Ne={lane:S.lane,tag:S.tag,payload:S.payload,callback:null,next:null};Z===null?$=Z=Ne:Z=Z.next=Ne,S=S.next}while(S!==null);Z===null?$=Z=y:Z=Z.next=y}else $=Z=y;S={baseState:M.baseState,firstBaseUpdate:$,lastBaseUpdate:Z,shared:M.shared,callbacks:M.callbacks},h.updateQueue=S;return}h=S.lastBaseUpdate,h===null?S.firstBaseUpdate=y:h.next=y,S.lastBaseUpdate=y}var HA=!1;function Xy(){if(HA){var h=Gg;if(h!==null)throw h}}function Yy(h,y,S,M){HA=!1;var $=h.updateQueue;Im=!1;var Z=$.firstBaseUpdate,Ne=$.lastBaseUpdate,He=$.shared.pending;if(He!==null){$.shared.pending=null;var rt=He,Nt=rt.next;rt.next=null,Ne===null?Z=Nt:Ne.next=Nt,Ne=rt;var Ot=h.alternate;Ot!==null&&(Ot=Ot.updateQueue,He=Ot.lastBaseUpdate,He!==Ne&&(He===null?Ot.firstBaseUpdate=Nt:He.next=Nt,Ot.lastBaseUpdate=rt))}if(Z!==null){var Ut=$.baseState;Ne=0,Ot=Nt=rt=null,He=Z;do{var Ct=He.lane&-536870913,Dt=Ct!==He.lane;if(Dt?(br&Ct)===Ct:(M&Ct)===Ct){Ct!==0&&Ct===Vg&&(HA=!0),Ot!==null&&(Ot=Ot.next={lane:0,tag:He.tag,payload:He.payload,callback:null,next:null});e:{var hn=h,Rn=He;Ct=y;var Wr=S;switch(Rn.tag){case 1:if(hn=Rn.payload,typeof hn=="function"){Ut=hn.call(Wr,Ut,Ct);break e}Ut=hn;break e;case 3:hn.flags=hn.flags&-65537|128;case 0:if(hn=Rn.payload,Ct=typeof hn=="function"?hn.call(Wr,Ut,Ct):hn,Ct==null)break e;Ut=m({},Ut,Ct);break e;case 2:Im=!0}}Ct=He.callback,Ct!==null&&(h.flags|=64,Dt&&(h.flags|=8192),Dt=$.callbacks,Dt===null?$.callbacks=[Ct]:Dt.push(Ct))}else Dt={lane:Ct,tag:He.tag,payload:He.payload,callback:He.callback,next:null},Ot===null?(Nt=Ot=Dt,rt=Ut):Ot=Ot.next=Dt,Ne|=Ct;if(He=He.next,He===null){if(He=$.shared.pending,He===null)break;Dt=He,He=Dt.next,Dt.next=null,$.lastBaseUpdate=Dt,$.shared.pending=null}}while(!0);Ot===null&&(rt=Ut),$.baseState=rt,$.firstBaseUpdate=Nt,$.lastBaseUpdate=Ot,Z===null&&($.shared.lanes=0),Vm|=Ne,h.lanes=Ne,h.memoizedState=Ut}}function B5(h,y){if(typeof h!="function")throw Error(r(191,h));h.call(y)}function H5(h,y){var S=h.callbacks;if(S!==null)for(h.callbacks=null,h=0;hZ?Z:8;var Ne=ae.T,He={};ae.T=He,oj(h,!1,y,S);try{var rt=$(),Nt=ae.S;if(Nt!==null&&Nt(He,rt),rt!==null&&typeof rt=="object"&&typeof rt.then=="function"){var Ot=wce(rt,M);Jy(h,y,Ot,Xo(h))}else Jy(h,y,M,Xo(h))}catch(Ut){Jy(h,y,{then:function(){},status:"rejected",reason:Ut},Xo())}finally{J.p=Z,Ne!==null&&He.types!==null&&(Ne.types=He.types),ae.T=Ne}}function Pce(){}function ij(h,y,S,M){if(h.tag!==5)throw Error(r(476));var $=vU(h).queue;yU(h,$,y,le,S===null?Pce:function(){return wU(h),S(M)})}function vU(h){var y=h.memoizedState;if(y!==null)return y;y={memoizedState:le,baseState:le,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ou,lastRenderedState:le},next:null};var S={};return y.next={memoizedState:S,baseState:S,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ou,lastRenderedState:S},next:null},h.memoizedState=y,h=h.alternate,h!==null&&(h.memoizedState=y),y}function wU(h){var y=vU(h);y.next===null&&(y=h.alternate.memoizedState),Jy(h,y.next.queue,{},Xo())}function sj(){return es(gv)}function SU(){return ti().memoizedState}function _U(){return ti().memoizedState}function Tce(h){for(var y=h.return;y!==null;){switch(y.tag){case 24:case 3:var S=Xo();h=zm(S);var M=Um(y,h,S);M!==null&&(So(M,y,S),Ky(M,y,S)),y={cache:RA()},h.payload=y;return}y=y.return}}function Ace(h,y,S){var M=Xo();S={lane:M,revertLane:0,gesture:null,action:S,hasEagerState:!1,eagerState:null,next:null},s_(h)?NU(y,S):(S=kA(h,y,S,M),S!==null&&(So(S,h,M),CU(S,y,M)))}function kU(h,y,S){var M=Xo();Jy(h,y,S,M)}function Jy(h,y,S,M){var $={lane:M,revertLane:0,gesture:null,action:S,hasEagerState:!1,eagerState:null,next:null};if(s_(h))NU(y,$);else{var Z=h.alternate;if(h.lanes===0&&(Z===null||Z.lanes===0)&&(Z=y.lastRenderedReducer,Z!==null))try{var Ne=y.lastRenderedState,He=Z(Ne,S);if($.hasEagerState=!0,$.eagerState=He,qo(He,Ne))return US(h,y,$,0),aa===null&&zS(),!1}catch{}if(S=kA(h,y,$,M),S!==null)return So(S,h,M),CU(S,y,M),!0}return!1}function oj(h,y,S,M){if(M={lane:2,revertLane:zj(),gesture:null,action:M,hasEagerState:!1,eagerState:null,next:null},s_(h)){if(y)throw Error(r(479))}else y=kA(h,S,M,2),y!==null&&So(y,h,2)}function s_(h){var y=h.alternate;return h===Xn||y!==null&&y===Xn}function NU(h,y){Yg=JS=!0;var S=h.pending;S===null?y.next=y:(y.next=S.next,S.next=y),h.pending=y}function CU(h,y,S){if((S&4194048)!==0){var M=y.lanes;M&=h.pendingLanes,S|=M,y.lanes=S,Xt(h,S)}}var ev={readContext:es,use:n_,useCallback:Ia,useContext:Ia,useEffect:Ia,useImperativeHandle:Ia,useLayoutEffect:Ia,useInsertionEffect:Ia,useMemo:Ia,useReducer:Ia,useRef:Ia,useState:Ia,useDebugValue:Ia,useDeferredValue:Ia,useTransition:Ia,useSyncExternalStore:Ia,useId:Ia,useHostTransitionStatus:Ia,useFormState:Ia,useActionState:Ia,useOptimistic:Ia,useMemoCache:Ia,useCacheRefresh:Ia};ev.useEffectEvent=Ia;var PU={readContext:es,use:n_,useCallback:function(h,y){return $s().memoizedState=[h,y===void 0?null:y],h},useContext:es,useEffect:dU,useImperativeHandle:function(h,y,S){S=S!=null?S.concat([h]):null,a_(4194308,4,pU.bind(null,y,h),S)},useLayoutEffect:function(h,y){return a_(4194308,4,h,y)},useInsertionEffect:function(h,y){a_(4,2,h,y)},useMemo:function(h,y){var S=$s();y=y===void 0?null:y;var M=h();if(Gp){Oe(!0);try{h()}finally{Oe(!1)}}return S.memoizedState=[M,y],M},useReducer:function(h,y,S){var M=$s();if(S!==void 0){var $=S(y);if(Gp){Oe(!0);try{S(y)}finally{Oe(!1)}}}else $=y;return M.memoizedState=M.baseState=$,h={pending:null,lanes:0,dispatch:null,lastRenderedReducer:h,lastRenderedState:$},M.queue=h,h=h.dispatch=Ace.bind(null,Xn,h),[M.memoizedState,h]},useRef:function(h){var y=$s();return h={current:h},y.memoizedState=h},useState:function(h){h=ej(h);var y=h.queue,S=kU.bind(null,Xn,y);return y.dispatch=S,[h.memoizedState,S]},useDebugValue:rj,useDeferredValue:function(h,y){var S=$s();return aj(S,h,y)},useTransition:function(){var h=ej(!1);return h=yU.bind(null,Xn,h.queue,!0,!1),$s().memoizedState=h,[!1,h]},useSyncExternalStore:function(h,y,S){var M=Xn,$=$s();if(vr){if(S===void 0)throw Error(r(407));S=S()}else{if(S=y(),aa===null)throw Error(r(349));(br&127)!==0||K5(M,y,S)}$.memoizedState=S;var Z={value:S,getSnapshot:y};return $.queue=Z,dU(Y5.bind(null,M,Z,h),[h]),M.flags|=2048,Zg(9,{destroy:void 0},X5.bind(null,M,Z,S,y),null),S},useId:function(){var h=$s(),y=aa.identifierPrefix;if(vr){var S=od,M=sd;S=(M&~(1<<32-qe(M)-1)).toString(32)+S,y="_"+y+"R_"+S,S=e_++,0<\/script>",Z=Z.removeChild(Z.firstChild);break;case"select":Z=typeof M.is=="string"?Ne.createElement("select",{is:M.is}):Ne.createElement("select"),M.multiple?Z.multiple=!0:M.size&&(Z.size=M.size);break;default:Z=typeof M.is=="string"?Ne.createElement($,{is:M.is}):Ne.createElement($)}}Z[it]=y,Z[ut]=M;e:for(Ne=y.child;Ne!==null;){if(Ne.tag===5||Ne.tag===6)Z.appendChild(Ne.stateNode);else if(Ne.tag!==4&&Ne.tag!==27&&Ne.child!==null){Ne.child.return=Ne,Ne=Ne.child;continue}if(Ne===y)break e;for(;Ne.sibling===null;){if(Ne.return===null||Ne.return===y)break e;Ne=Ne.return}Ne.sibling.return=Ne.return,Ne=Ne.sibling}y.stateNode=Z;e:switch(ns(Z,$,M),$){case"button":case"input":case"select":case"textarea":M=!!M.autoFocus;break e;case"img":M=!0;break e;default:M=!1}M&&cu(y)}}return xa(y),wj(y,y.type,h===null?null:h.memoizedProps,y.pendingProps,S),null;case 6:if(h&&y.stateNode!=null)h.memoizedProps!==M&&cu(y);else{if(typeof M!="string"&&y.stateNode===null)throw Error(r(166));if(h=q.current,qg(y)){if(h=y.stateNode,S=y.memoizedProps,M=null,$=Ji,$!==null)switch($.tag){case 27:case 5:M=$.memoizedProps}h[it]=y,h=!!(h.nodeValue===S||M!==null&&M.suppressHydrationWarning===!0||GB(h.nodeValue,S)),h||Lm(y,!0)}else h=C_(h).createTextNode(M),h[it]=y,y.stateNode=h}return xa(y),null;case 31:if(S=y.memoizedState,h===null||h.memoizedState!==null){if(M=qg(y),S!==null){if(h===null){if(!M)throw Error(r(318));if(h=y.memoizedState,h=h!==null?h.dehydrated:null,!h)throw Error(r(557));h[it]=y}else zp(),(y.flags&128)===0&&(y.memoizedState=null),y.flags|=4;xa(y),h=!1}else S=MA(),h!==null&&h.memoizedState!==null&&(h.memoizedState.hydrationErrors=S),h=!0;if(!h)return y.flags&256?(Go(y),y):(Go(y),null);if((y.flags&128)!==0)throw Error(r(558))}return xa(y),null;case 13:if(M=y.memoizedState,h===null||h.memoizedState!==null&&h.memoizedState.dehydrated!==null){if($=qg(y),M!==null&&M.dehydrated!==null){if(h===null){if(!$)throw Error(r(318));if($=y.memoizedState,$=$!==null?$.dehydrated:null,!$)throw Error(r(317));$[it]=y}else zp(),(y.flags&128)===0&&(y.memoizedState=null),y.flags|=4;xa(y),$=!1}else $=MA(),h!==null&&h.memoizedState!==null&&(h.memoizedState.hydrationErrors=$),$=!0;if(!$)return y.flags&256?(Go(y),y):(Go(y),null)}return Go(y),(y.flags&128)!==0?(y.lanes=S,y):(S=M!==null,h=h!==null&&h.memoizedState!==null,S&&(M=y.child,$=null,M.alternate!==null&&M.alternate.memoizedState!==null&&M.alternate.memoizedState.cachePool!==null&&($=M.alternate.memoizedState.cachePool.pool),Z=null,M.memoizedState!==null&&M.memoizedState.cachePool!==null&&(Z=M.memoizedState.cachePool.pool),Z!==$&&(M.flags|=2048)),S!==h&&S&&(y.child.flags|=8192),u_(y,y.updateQueue),xa(y),null);case 4:return j(),h===null&&qj(y.stateNode.containerInfo),xa(y),null;case 10:return iu(y.type),xa(y),null;case 19:if(ne(ei),M=y.memoizedState,M===null)return xa(y),null;if($=(y.flags&128)!==0,Z=M.rendering,Z===null)if($)nv(M,!1);else{if(za!==0||h!==null&&(h.flags&128)!==0)for(h=y.child;h!==null;){if(Z=ZS(h),Z!==null){for(y.flags|=128,nv(M,!1),h=Z.updateQueue,y.updateQueue=h,u_(y,h),y.subtreeFlags=0,h=S,S=y.child;S!==null;)k5(S,h),S=S.sibling;return fe(ei,ei.current&1|2),vr&&ru(y,M.treeForkCount),y.child}h=h.sibling}M.tail!==null&&R()>g_&&(y.flags|=128,$=!0,nv(M,!1),y.lanes=4194304)}else{if(!$)if(h=ZS(Z),h!==null){if(y.flags|=128,$=!0,h=h.updateQueue,y.updateQueue=h,u_(y,h),nv(M,!0),M.tail===null&&M.tailMode==="hidden"&&!Z.alternate&&!vr)return xa(y),null}else 2*R()-M.renderingStartTime>g_&&S!==536870912&&(y.flags|=128,$=!0,nv(M,!1),y.lanes=4194304);M.isBackwards?(Z.sibling=y.child,y.child=Z):(h=M.last,h!==null?h.sibling=Z:y.child=Z,M.last=Z)}return M.tail!==null?(h=M.tail,M.rendering=h,M.tail=h.sibling,M.renderingStartTime=R(),h.sibling=null,S=ei.current,fe(ei,$?S&1|2:S&1),vr&&ru(y,M.treeForkCount),h):(xa(y),null);case 22:case 23:return Go(y),$A(),M=y.memoizedState!==null,h!==null?h.memoizedState!==null!==M&&(y.flags|=8192):M&&(y.flags|=8192),M?(S&536870912)!==0&&(y.flags&128)===0&&(xa(y),y.subtreeFlags&6&&(y.flags|=8192)):xa(y),S=y.updateQueue,S!==null&&u_(y,S.retryQueue),S=null,h!==null&&h.memoizedState!==null&&h.memoizedState.cachePool!==null&&(S=h.memoizedState.cachePool.pool),M=null,y.memoizedState!==null&&y.memoizedState.cachePool!==null&&(M=y.memoizedState.cachePool.pool),M!==S&&(y.flags|=2048),h!==null&&ne(Hp),null;case 24:return S=null,h!==null&&(S=h.memoizedState.cache),y.memoizedState.cache!==S&&(y.flags|=2048),iu(si),xa(y),null;case 25:return null;case 30:return null}throw Error(r(156,y.tag))}function Fce(h,y){switch(AA(y),y.tag){case 1:return h=y.flags,h&65536?(y.flags=h&-65537|128,y):null;case 3:return iu(si),j(),h=y.flags,(h&65536)!==0&&(h&128)===0?(y.flags=h&-65537|128,y):null;case 26:case 27:case 5:return K(y),null;case 31:if(y.memoizedState!==null){if(Go(y),y.alternate===null)throw Error(r(340));zp()}return h=y.flags,h&65536?(y.flags=h&-65537|128,y):null;case 13:if(Go(y),h=y.memoizedState,h!==null&&h.dehydrated!==null){if(y.alternate===null)throw Error(r(340));zp()}return h=y.flags,h&65536?(y.flags=h&-65537|128,y):null;case 19:return ne(ei),null;case 4:return j(),null;case 10:return iu(y.type),null;case 22:case 23:return Go(y),$A(),h!==null&&ne(Hp),h=y.flags,h&65536?(y.flags=h&-65537|128,y):null;case 24:return iu(si),null;case 25:return null;default:return null}}function QU(h,y){switch(AA(y),y.tag){case 3:iu(si),j();break;case 26:case 27:case 5:K(y);break;case 4:j();break;case 31:y.memoizedState!==null&&Go(y);break;case 13:Go(y);break;case 19:ne(ei);break;case 10:iu(y.type);break;case 22:case 23:Go(y),$A(),h!==null&&ne(Hp);break;case 24:iu(si)}}function rv(h,y){try{var S=y.updateQueue,M=S!==null?S.lastEffect:null;if(M!==null){var $=M.next;S=$;do{if((S.tag&h)===h){M=void 0;var Z=S.create,Ne=S.inst;M=Z(),Ne.destroy=M}S=S.next}while(S!==$)}}catch(He){zr(y,y.return,He)}}function qm(h,y,S){try{var M=y.updateQueue,$=M!==null?M.lastEffect:null;if($!==null){var Z=$.next;M=Z;do{if((M.tag&h)===h){var Ne=M.inst,He=Ne.destroy;if(He!==void 0){Ne.destroy=void 0,$=y;var rt=S,Nt=He;try{Nt()}catch(Ot){zr($,rt,Ot)}}}M=M.next}while(M!==Z)}}catch(Ot){zr(y,y.return,Ot)}}function ZU(h){var y=h.updateQueue;if(y!==null){var S=h.stateNode;try{H5(y,S)}catch(M){zr(h,h.return,M)}}}function JU(h,y,S){S.props=Wp(h.type,h.memoizedProps),S.state=h.memoizedState;try{S.componentWillUnmount()}catch(M){zr(h,y,M)}}function av(h,y){try{var S=h.ref;if(S!==null){switch(h.tag){case 26:case 27:case 5:var M=h.stateNode;break;case 30:M=h.stateNode;break;default:M=h.stateNode}typeof S=="function"?h.refCleanup=S(M):S.current=M}}catch($){zr(h,y,$)}}function ld(h,y){var S=h.ref,M=h.refCleanup;if(S!==null)if(typeof M=="function")try{M()}catch($){zr(h,y,$)}finally{h.refCleanup=null,h=h.alternate,h!=null&&(h.refCleanup=null)}else if(typeof S=="function")try{S(null)}catch($){zr(h,y,$)}else S.current=null}function eB(h){var y=h.type,S=h.memoizedProps,M=h.stateNode;try{e:switch(y){case"button":case"input":case"select":case"textarea":S.autoFocus&&M.focus();break e;case"img":S.src?M.src=S.src:S.srcSet&&(M.srcset=S.srcSet)}}catch($){zr(h,h.return,$)}}function Sj(h,y,S){try{var M=h.stateNode;nde(M,h.type,S,y),M[ut]=y}catch($){zr(h,h.return,$)}}function tB(h){return h.tag===5||h.tag===3||h.tag===26||h.tag===27&&Ym(h.type)||h.tag===4}function _j(h){e:for(;;){for(;h.sibling===null;){if(h.return===null||tB(h.return))return null;h=h.return}for(h.sibling.return=h.return,h=h.sibling;h.tag!==5&&h.tag!==6&&h.tag!==18;){if(h.tag===27&&Ym(h.type)||h.flags&2||h.child===null||h.tag===4)continue e;h.child.return=h,h=h.child}if(!(h.flags&2))return h.stateNode}}function kj(h,y,S){var M=h.tag;if(M===5||M===6)h=h.stateNode,y?(S.nodeType===9?S.body:S.nodeName==="HTML"?S.ownerDocument.body:S).insertBefore(h,y):(y=S.nodeType===9?S.body:S.nodeName==="HTML"?S.ownerDocument.body:S,y.appendChild(h),S=S._reactRootContainer,S!=null||y.onclick!==null||(y.onclick=qt));else if(M!==4&&(M===27&&Ym(h.type)&&(S=h.stateNode,y=null),h=h.child,h!==null))for(kj(h,y,S),h=h.sibling;h!==null;)kj(h,y,S),h=h.sibling}function m_(h,y,S){var M=h.tag;if(M===5||M===6)h=h.stateNode,y?S.insertBefore(h,y):S.appendChild(h);else if(M!==4&&(M===27&&Ym(h.type)&&(S=h.stateNode),h=h.child,h!==null))for(m_(h,y,S),h=h.sibling;h!==null;)m_(h,y,S),h=h.sibling}function nB(h){var y=h.stateNode,S=h.memoizedProps;try{for(var M=h.type,$=y.attributes;$.length;)y.removeAttributeNode($[0]);ns(y,M,S),y[it]=h,y[ut]=S}catch(Z){zr(h,h.return,Z)}}var du=!1,ci=!1,Nj=!1,rB=typeof WeakSet=="function"?WeakSet:Set,Ri=null;function Rce(h,y){if(h=h.containerInfo,Gj=D_,h=f5(h),xA(h)){if("selectionStart"in h)var S={start:h.selectionStart,end:h.selectionEnd};else e:{S=(S=h.ownerDocument)&&S.defaultView||window;var M=S.getSelection&&S.getSelection();if(M&&M.rangeCount!==0){S=M.anchorNode;var $=M.anchorOffset,Z=M.focusNode;M=M.focusOffset;try{S.nodeType,Z.nodeType}catch{S=null;break e}var Ne=0,He=-1,rt=-1,Nt=0,Ot=0,Ut=h,Ct=null;t:for(;;){for(var Dt;Ut!==S||$!==0&&Ut.nodeType!==3||(He=Ne+$),Ut!==Z||M!==0&&Ut.nodeType!==3||(rt=Ne+M),Ut.nodeType===3&&(Ne+=Ut.nodeValue.length),(Dt=Ut.firstChild)!==null;)Ct=Ut,Ut=Dt;for(;;){if(Ut===h)break t;if(Ct===S&&++Nt===$&&(He=Ne),Ct===Z&&++Ot===M&&(rt=Ne),(Dt=Ut.nextSibling)!==null)break;Ut=Ct,Ct=Ut.parentNode}Ut=Dt}S=He===-1||rt===-1?null:{start:He,end:rt}}else S=null}S=S||{start:0,end:0}}else S=null;for(Wj={focusedElem:h,selectionRange:S},D_=!1,Ri=y;Ri!==null;)if(y=Ri,h=y.child,(y.subtreeFlags&1028)!==0&&h!==null)h.return=y,Ri=h;else for(;Ri!==null;){switch(y=Ri,Z=y.alternate,h=y.flags,y.tag){case 0:if((h&4)!==0&&(h=y.updateQueue,h=h!==null?h.events:null,h!==null))for(S=0;S title"))),ns(Z,M,S),Z[it]=h,Ke(Z),M=Z;break e;case"link":var Ne=c8("link","href",$).get(M+(S.href||""));if(Ne){for(var He=0;HeWr&&(Ne=Wr,Wr=Rn,Rn=Ne);var bt=h5(He,Rn),mt=h5(He,Wr);if(bt&&mt&&(Dt.rangeCount!==1||Dt.anchorNode!==bt.node||Dt.anchorOffset!==bt.offset||Dt.focusNode!==mt.node||Dt.focusOffset!==mt.offset)){var kt=Ut.createRange();kt.setStart(bt.node,bt.offset),Dt.removeAllRanges(),Rn>Wr?(Dt.addRange(kt),Dt.extend(mt.node,mt.offset)):(kt.setEnd(mt.node,mt.offset),Dt.addRange(kt))}}}}for(Ut=[],Dt=He;Dt=Dt.parentNode;)Dt.nodeType===1&&Ut.push({element:Dt,left:Dt.scrollLeft,top:Dt.scrollTop});for(typeof He.focus=="function"&&He.focus(),He=0;HeS?32:S,ae.T=null,S=Ej,Ej=null;var Z=Wm,Ne=fu;if(wi=0,rb=Wm=null,fu=0,(Er&6)!==0)throw Error(r(331));var He=Er;if(Er|=4,pB(Z.current),uB(Z,Z.current,Ne,S),Er=He,dv(0,!1),Le&&typeof Le.onPostCommitFiberRoot=="function")try{Le.onPostCommitFiberRoot(Me,Z)}catch{}return!0}finally{J.p=$,ae.T=M,EB(h,y)}}function FB(h,y,S){y=kl(S,y),y=uj(h.stateNode,y,2),h=Um(h,y,2),h!==null&&(xt(h,2),cd(h))}function zr(h,y,S){if(h.tag===3)FB(h,h,S);else for(;y!==null;){if(y.tag===3){FB(y,h,S);break}else if(y.tag===1){var M=y.stateNode;if(typeof y.type.getDerivedStateFromError=="function"||typeof M.componentDidCatch=="function"&&(Gm===null||!Gm.has(M))){h=kl(S,h),S=RU(2),M=Um(y,S,2),M!==null&&(LU(S,M,y,h),xt(M,2),cd(M));break}}y=y.return}}function Lj(h,y,S){var M=h.pingCache;if(M===null){M=h.pingCache=new Ice;var $=new Set;M.set(y,$)}else $=M.get(y),$===void 0&&($=new Set,M.set(y,$));$.has(S)||(Tj=!0,$.add(S),h=qce.bind(null,h,y,S),y.then(h,h))}function qce(h,y,S){var M=h.pingCache;M!==null&&M.delete(y),h.pingedLanes|=h.suspendedLanes&S,h.warmLanes&=~S,aa===h&&(br&S)===S&&(za===4||za===3&&(br&62914560)===br&&300>R()-f_?(Er&2)===0&&ab(h,0):Aj|=S,nb===br&&(nb=0)),cd(h)}function RB(h,y){y===0&&(y=Ze()),h=Op(h,y),h!==null&&(xt(h,y),cd(h))}function $ce(h){var y=h.memoizedState,S=0;y!==null&&(S=y.retryLane),RB(h,S)}function Vce(h,y){var S=0;switch(h.tag){case 31:case 13:var M=h.stateNode,$=h.memoizedState;$!==null&&(S=$.retryLane);break;case 19:M=h.stateNode;break;case 22:M=h.stateNode._retryCache;break;default:throw Error(r(314))}M!==null&&M.delete(y),RB(h,S)}function Gce(h,y){return ge(h,y)}var S_=null,sb=null,Oj=!1,__=!1,Ij=!1,Xm=0;function cd(h){h!==sb&&h.next===null&&(sb===null?S_=sb=h:sb=sb.next=h),__=!0,Oj||(Oj=!0,Kce())}function dv(h,y){if(!Ij&&__){Ij=!0;do for(var S=!1,M=S_;M!==null;){if(h!==0){var $=M.pendingLanes;if($===0)var Z=0;else{var Ne=M.suspendedLanes,He=M.pingedLanes;Z=(1<<31-qe(42|h)+1)-1,Z&=$&~(Ne&~He),Z=Z&201326741?Z&201326741|1:Z?Z|2:0}Z!==0&&(S=!0,zB(M,Z))}else Z=br,Z=de(M,M===aa?Z:0,M.cancelPendingCommit!==null||M.timeoutHandle!==-1),(Z&3)===0||xe(M,Z)||(S=!0,zB(M,Z));M=M.next}while(S);Ij=!1}}function Wce(){LB()}function LB(){__=Oj=!1;var h=0;Xm!==0&&ade()&&(h=Xm);for(var y=R(),S=null,M=S_;M!==null;){var $=M.next,Z=OB(M,y);Z===0?(M.next=null,S===null?S_=$:S.next=$,$===null&&(sb=S)):(S=M,(h!==0||(Z&3)!==0)&&(__=!0)),M=$}wi!==0&&wi!==5||dv(h),Xm!==0&&(Xm=0)}function OB(h,y){for(var S=h.suspendedLanes,M=h.pingedLanes,$=h.expirationTimes,Z=h.pendingLanes&-62914561;0He)break;var Ot=rt.transferSize,Ut=rt.initiatorType;Ot&&WB(Ut)&&(rt=rt.responseEnd,Ne+=Ot*(rt"u"?null:document;function i8(h,y,S){var M=ob;if(M&&typeof y=="string"&&y){var $=En(y);$='link[rel="'+h+'"][href="'+$+'"]',typeof S=="string"&&($+='[crossorigin="'+S+'"]'),a8.has($)||(a8.add($),h={rel:h,crossOrigin:S,href:y},M.querySelector($)===null&&(y=M.createElement("link"),ns(y,"link",h),Ke(y),M.head.appendChild(y)))}}function hde(h){gu.D(h),i8("dns-prefetch",h,null)}function pde(h,y){gu.C(h,y),i8("preconnect",h,y)}function fde(h,y,S){gu.L(h,y,S);var M=ob;if(M&&h&&y){var $='link[rel="preload"][as="'+En(y)+'"]';y==="image"&&S&&S.imageSrcSet?($+='[imagesrcset="'+En(S.imageSrcSet)+'"]',typeof S.imageSizes=="string"&&($+='[imagesizes="'+En(S.imageSizes)+'"]')):$+='[href="'+En(h)+'"]';var Z=$;switch(y){case"style":Z=lb(h);break;case"script":Z=cb(h)}jl.has(Z)||(h=m({rel:"preload",href:y==="image"&&S&&S.imageSrcSet?void 0:h,as:y},S),jl.set(Z,h),M.querySelector($)!==null||y==="style"&&M.querySelector(pv(Z))||y==="script"&&M.querySelector(fv(Z))||(y=M.createElement("link"),ns(y,"link",h),Ke(y),M.head.appendChild(y)))}}function gde(h,y){gu.m(h,y);var S=ob;if(S&&h){var M=y&&typeof y.as=="string"?y.as:"script",$='link[rel="modulepreload"][as="'+En(M)+'"][href="'+En(h)+'"]',Z=$;switch(M){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":Z=cb(h)}if(!jl.has(Z)&&(h=m({rel:"modulepreload",href:h},y),jl.set(Z,h),S.querySelector($)===null)){switch(M){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(S.querySelector(fv(Z)))return}M=S.createElement("link"),ns(M,"link",h),Ke(M),S.head.appendChild(M)}}}function bde(h,y,S){gu.S(h,y,S);var M=ob;if(M&&h){var $=et(M).hoistableStyles,Z=lb(h);y=y||"default";var Ne=$.get(Z);if(!Ne){var He={loading:0,preload:null};if(Ne=M.querySelector(pv(Z)))He.loading=5;else{h=m({rel:"stylesheet",href:h,"data-precedence":y},S),(S=jl.get(Z))&&eM(h,S);var rt=Ne=M.createElement("link");Ke(rt),ns(rt,"link",h),rt._p=new Promise(function(Nt,Ot){rt.onload=Nt,rt.onerror=Ot}),rt.addEventListener("load",function(){He.loading|=1}),rt.addEventListener("error",function(){He.loading|=2}),He.loading|=4,T_(Ne,y,M)}Ne={type:"stylesheet",instance:Ne,count:1,state:He},$.set(Z,Ne)}}}function xde(h,y){gu.X(h,y);var S=ob;if(S&&h){var M=et(S).hoistableScripts,$=cb(h),Z=M.get($);Z||(Z=S.querySelector(fv($)),Z||(h=m({src:h,async:!0},y),(y=jl.get($))&&tM(h,y),Z=S.createElement("script"),Ke(Z),ns(Z,"link",h),S.head.appendChild(Z)),Z={type:"script",instance:Z,count:1,state:null},M.set($,Z))}}function yde(h,y){gu.M(h,y);var S=ob;if(S&&h){var M=et(S).hoistableScripts,$=cb(h),Z=M.get($);Z||(Z=S.querySelector(fv($)),Z||(h=m({src:h,async:!0,type:"module"},y),(y=jl.get($))&&tM(h,y),Z=S.createElement("script"),Ke(Z),ns(Z,"link",h),S.head.appendChild(Z)),Z={type:"script",instance:Z,count:1,state:null},M.set($,Z))}}function s8(h,y,S,M){var $=($=q.current)?P_($):null;if(!$)throw Error(r(446));switch(h){case"meta":case"title":return null;case"style":return typeof S.precedence=="string"&&typeof S.href=="string"?(y=lb(S.href),S=et($).hoistableStyles,M=S.get(y),M||(M={type:"style",instance:null,count:0,state:null},S.set(y,M)),M):{type:"void",instance:null,count:0,state:null};case"link":if(S.rel==="stylesheet"&&typeof S.href=="string"&&typeof S.precedence=="string"){h=lb(S.href);var Z=et($).hoistableStyles,Ne=Z.get(h);if(Ne||($=$.ownerDocument||$,Ne={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},Z.set(h,Ne),(Z=$.querySelector(pv(h)))&&!Z._p&&(Ne.instance=Z,Ne.state.loading=5),jl.has(h)||(S={rel:"preload",as:"style",href:S.href,crossOrigin:S.crossOrigin,integrity:S.integrity,media:S.media,hrefLang:S.hrefLang,referrerPolicy:S.referrerPolicy},jl.set(h,S),Z||vde($,h,S,Ne.state))),y&&M===null)throw Error(r(528,""));return Ne}if(y&&M!==null)throw Error(r(529,""));return null;case"script":return y=S.async,S=S.src,typeof S=="string"&&y&&typeof y!="function"&&typeof y!="symbol"?(y=cb(S),S=et($).hoistableScripts,M=S.get(y),M||(M={type:"script",instance:null,count:0,state:null},S.set(y,M)),M):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,h))}}function lb(h){return'href="'+En(h)+'"'}function pv(h){return'link[rel="stylesheet"]['+h+"]"}function o8(h){return m({},h,{"data-precedence":h.precedence,precedence:null})}function vde(h,y,S,M){h.querySelector('link[rel="preload"][as="style"]['+y+"]")?M.loading=1:(y=h.createElement("link"),M.preload=y,y.addEventListener("load",function(){return M.loading|=1}),y.addEventListener("error",function(){return M.loading|=2}),ns(y,"link",S),Ke(y),h.head.appendChild(y))}function cb(h){return'[src="'+En(h)+'"]'}function fv(h){return"script[async]"+h}function l8(h,y,S){if(y.count++,y.instance===null)switch(y.type){case"style":var M=h.querySelector('style[data-href~="'+En(S.href)+'"]');if(M)return y.instance=M,Ke(M),M;var $=m({},S,{"data-href":S.href,"data-precedence":S.precedence,href:null,precedence:null});return M=(h.ownerDocument||h).createElement("style"),Ke(M),ns(M,"style",$),T_(M,S.precedence,h),y.instance=M;case"stylesheet":$=lb(S.href);var Z=h.querySelector(pv($));if(Z)return y.state.loading|=4,y.instance=Z,Ke(Z),Z;M=o8(S),($=jl.get($))&&eM(M,$),Z=(h.ownerDocument||h).createElement("link"),Ke(Z);var Ne=Z;return Ne._p=new Promise(function(He,rt){Ne.onload=He,Ne.onerror=rt}),ns(Z,"link",M),y.state.loading|=4,T_(Z,S.precedence,h),y.instance=Z;case"script":return Z=cb(S.src),($=h.querySelector(fv(Z)))?(y.instance=$,Ke($),$):(M=S,($=jl.get(Z))&&(M=m({},S),tM(M,$)),h=h.ownerDocument||h,$=h.createElement("script"),Ke($),ns($,"link",M),h.head.appendChild($),y.instance=$);case"void":return null;default:throw Error(r(443,y.type))}else y.type==="stylesheet"&&(y.state.loading&4)===0&&(M=y.instance,y.state.loading|=4,T_(M,S.precedence,h));return y.instance}function T_(h,y,S){for(var M=S.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),$=M.length?M[M.length-1]:null,Z=$,Ne=0;Ne title"):null)}function wde(h,y,S){if(S===1||y.itemProp!=null)return!1;switch(h){case"meta":case"title":return!0;case"style":if(typeof y.precedence!="string"||typeof y.href!="string"||y.href==="")break;return!0;case"link":if(typeof y.rel!="string"||typeof y.href!="string"||y.href===""||y.onLoad||y.onError)break;return y.rel==="stylesheet"?(h=y.disabled,typeof y.precedence=="string"&&h==null):!0;case"script":if(y.async&&typeof y.async!="function"&&typeof y.async!="symbol"&&!y.onLoad&&!y.onError&&y.src&&typeof y.src=="string")return!0}return!1}function u8(h){return!(h.type==="stylesheet"&&(h.state.loading&3)===0)}function Sde(h,y,S,M){if(S.type==="stylesheet"&&(typeof M.media!="string"||matchMedia(M.media).matches!==!1)&&(S.state.loading&4)===0){if(S.instance===null){var $=lb(M.href),Z=y.querySelector(pv($));if(Z){y=Z._p,y!==null&&typeof y=="object"&&typeof y.then=="function"&&(h.count++,h=j_.bind(h),y.then(h,h)),S.state.loading|=4,S.instance=Z,Ke(Z);return}Z=y.ownerDocument||y,M=o8(M),($=jl.get($))&&eM(M,$),Z=Z.createElement("link"),Ke(Z);var Ne=Z;Ne._p=new Promise(function(He,rt){Ne.onload=He,Ne.onerror=rt}),ns(Z,"link",M),S.instance=Z}h.stylesheets===null&&(h.stylesheets=new Map),h.stylesheets.set(S,y),(y=S.state.preload)&&(S.state.loading&3)===0&&(h.count++,S=j_.bind(h),y.addEventListener("load",S),y.addEventListener("error",S))}}var nM=0;function _de(h,y){return h.stylesheets&&h.count===0&&E_(h,h.stylesheets),0nM?50:800)+y);return h.unsuspend=S,function(){h.unsuspend=null,clearTimeout(M),clearTimeout($)}}:null}function j_(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)E_(this,this.stylesheets);else if(this.unsuspend){var h=this.unsuspend;this.unsuspend=null,h()}}}var M_=null;function E_(h,y){h.stylesheets=null,h.unsuspend!==null&&(h.count++,M_=new Map,y.forEach(kde,h),M_=null,j_.call(h))}function kde(h,y){if(!(y.state.loading&4)){var S=M_.get(h);if(S)var M=S.get(null);else{S=new Map,M_.set(h,S);for(var $=h.querySelectorAll("link[data-precedence],style[data-precedence]"),Z=0;Z<$.length;Z++){var Ne=$[Z];(Ne.nodeName==="LINK"||Ne.getAttribute("media")!=="not all")&&(S.set(Ne.dataset.precedence,Ne),M=Ne)}M&&S.set(null,M)}$=y.instance,Ne=$.getAttribute("data-precedence"),Z=S.get(Ne)||M,Z===M&&S.set(null,$),S.set(Ne,$),this.count++,M=j_.bind(this),$.addEventListener("load",M),$.addEventListener("error",M),Z?Z.parentNode.insertBefore($,Z.nextSibling):(h=h.nodeType===9?h.head:h,h.insertBefore($,h.firstChild)),y.state.loading|=4}}var gv={$$typeof:C,Provider:null,Consumer:null,_currentValue:le,_currentValue2:le,_threadCount:0};function Nde(h,y,S,M,$,Z,Ne,He,rt){this.tag=1,this.containerInfo=h,this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.next=this.pendingContext=this.context=this.cancelPendingCommit=null,this.callbackPriority=0,this.expirationTimes=pt(-1),this.entangledLanes=this.shellSuspendCounter=this.errorRecoveryDisabledLanes=this.expiredLanes=this.warmLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=pt(0),this.hiddenUpdates=pt(null),this.identifierPrefix=M,this.onUncaughtError=$,this.onCaughtError=Z,this.onRecoverableError=Ne,this.pooledCache=null,this.pooledCacheLanes=0,this.formState=rt,this.incompleteTransitions=new Map}function m8(h,y,S,M,$,Z,Ne,He,rt,Nt,Ot,Ut){return h=new Nde(h,y,S,Ne,rt,Nt,Ot,Ut,He),y=1,Z===!0&&(y|=24),Z=$o(3,null,null,y),h.current=Z,Z.stateNode=h,y=RA(),y.refCount++,h.pooledCache=y,y.refCount++,Z.memoizedState={element:M,isDehydrated:S,cache:y},zA(Z),h}function h8(h){return h?(h=Ug,h):Ug}function p8(h,y,S,M,$,Z){$=h8($),M.context===null?M.context=$:M.pendingContext=$,M=zm(y),M.payload={element:S},Z=Z===void 0?null:Z,Z!==null&&(M.callback=Z),S=Um(h,M,y),S!==null&&(So(S,h,y),Ky(S,h,y))}function f8(h,y){if(h=h.memoizedState,h!==null&&h.dehydrated!==null){var S=h.retryLane;h.retryLane=S!==0&&S"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(t)}catch(e){console.error(e)}}return t(),uM.exports=Bde(),uM.exports}var qde=Hde();const Hn=t=>typeof t=="string",Sv=()=>{let t,e;const n=new Promise((r,i)=>{t=r,e=i});return n.resolve=t,n.reject=e,n},R8=t=>t==null?"":""+t,$de=(t,e,n)=>{t.forEach(r=>{e[r]&&(n[r]=e[r])})},Vde=/###/g,L8=t=>t&&t.indexOf("###")>-1?t.replace(Vde,"."):t,O8=t=>!t||Hn(t),y0=(t,e,n)=>{const r=Hn(e)?e.split("."):e;let i=0;for(;i{const{obj:r,k:i}=y0(t,e,Object);if(r!==void 0||e.length===1){r[i]=n;return}let s=e[e.length-1],o=e.slice(0,e.length-1),l=y0(t,o,Object);for(;l.obj===void 0&&o.length;)s=`${o[o.length-1]}.${s}`,o=o.slice(0,o.length-1),l=y0(t,o,Object),l?.obj&&typeof l.obj[`${l.k}.${s}`]<"u"&&(l.obj=void 0);l.obj[`${l.k}.${s}`]=n},Gde=(t,e,n,r)=>{const{obj:i,k:s}=y0(t,e,Object);i[s]=i[s]||[],i[s].push(n)},sN=(t,e)=>{const{obj:n,k:r}=y0(t,e);if(n&&Object.prototype.hasOwnProperty.call(n,r))return n[r]},Wde=(t,e,n)=>{const r=sN(t,n);return r!==void 0?r:sN(e,n)},OY=(t,e,n)=>{for(const r in e)r!=="__proto__"&&r!=="constructor"&&(r in t?Hn(t[r])||t[r]instanceof String||Hn(e[r])||e[r]instanceof String?n&&(t[r]=e[r]):OY(t[r],e[r],n):t[r]=e[r]);return t},ub=t=>t.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&");var Kde={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"};const Xde=t=>Hn(t)?t.replace(/[&<>"'\/]/g,e=>Kde[e]):t;class Yde{constructor(e){this.capacity=e,this.regExpMap=new Map,this.regExpQueue=[]}getRegExp(e){const n=this.regExpMap.get(e);if(n!==void 0)return n;const r=new RegExp(e);return this.regExpQueue.length===this.capacity&&this.regExpMap.delete(this.regExpQueue.shift()),this.regExpMap.set(e,r),this.regExpQueue.push(e),r}}const Qde=[" ",",","?","!",";"],Zde=new Yde(20),Jde=(t,e,n)=>{e=e||"",n=n||"";const r=Qde.filter(o=>e.indexOf(o)<0&&n.indexOf(o)<0);if(r.length===0)return!0;const i=Zde.getRegExp(`(${r.map(o=>o==="?"?"\\?":o).join("|")})`);let s=!i.test(t);if(!s){const o=t.indexOf(n);o>0&&!i.test(t.substring(0,o))&&(s=!0)}return s},R3=(t,e,n=".")=>{if(!t)return;if(t[e])return Object.prototype.hasOwnProperty.call(t,e)?t[e]:void 0;const r=e.split(n);let i=t;for(let s=0;s-1&&ct?.replace("_","-"),eue={type:"logger",log(t){this.output("log",t)},warn(t){this.output("warn",t)},error(t){this.output("error",t)},output(t,e){console?.[t]?.apply?.(console,e)}};class oN{constructor(e,n={}){this.init(e,n)}init(e,n={}){this.prefix=n.prefix||"i18next:",this.logger=e||eue,this.options=n,this.debug=n.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,n,r,i){return i&&!this.debug?null:(Hn(e[0])&&(e[0]=`${r}${this.prefix} ${e[0]}`),this.logger[n](e))}create(e){return new oN(this.logger,{prefix:`${this.prefix}:${e}:`,...this.options})}clone(e){return e=e||this.options,e.prefix=e.prefix||this.prefix,new oN(this.logger,e)}}var Cd=new oN;let EP=class{constructor(){this.observers={}}on(e,n){return e.split(" ").forEach(r=>{this.observers[r]||(this.observers[r]=new Map);const i=this.observers[r].get(n)||0;this.observers[r].set(n,i+1)}),this}off(e,n){if(this.observers[e]){if(!n){delete this.observers[e];return}this.observers[e].delete(n)}}emit(e,...n){this.observers[e]&&Array.from(this.observers[e].entries()).forEach(([i,s])=>{for(let o=0;o{for(let o=0;o-1&&this.options.ns.splice(n,1)}getResource(e,n,r,i={}){const s=i.keySeparator!==void 0?i.keySeparator:this.options.keySeparator,o=i.ignoreJSONStructure!==void 0?i.ignoreJSONStructure:this.options.ignoreJSONStructure;let l;e.indexOf(".")>-1?l=e.split("."):(l=[e,n],r&&(Array.isArray(r)?l.push(...r):Hn(r)&&s?l.push(...r.split(s)):l.push(r)));const c=sN(this.data,l);return!c&&!n&&!r&&e.indexOf(".")>-1&&(e=l[0],n=l[1],r=l.slice(2).join(".")),c||!o||!Hn(r)?c:R3(this.data?.[e]?.[n],r,s)}addResource(e,n,r,i,s={silent:!1}){const o=s.keySeparator!==void 0?s.keySeparator:this.options.keySeparator;let l=[e,n];r&&(l=l.concat(o?r.split(o):r)),e.indexOf(".")>-1&&(l=e.split("."),i=n,n=l[1]),this.addNamespaces(n),I8(this.data,l,i),s.silent||this.emit("added",e,n,r,i)}addResources(e,n,r,i={silent:!1}){for(const s in r)(Hn(r[s])||Array.isArray(r[s]))&&this.addResource(e,n,s,r[s],{silent:!0});i.silent||this.emit("added",e,n,r)}addResourceBundle(e,n,r,i,s,o={silent:!1,skipCopy:!1}){let l=[e,n];e.indexOf(".")>-1&&(l=e.split("."),i=r,r=n,n=l[1]),this.addNamespaces(n);let c=sN(this.data,l)||{};o.skipCopy||(r=JSON.parse(JSON.stringify(r))),i?OY(c,r,s):c={...c,...r},I8(this.data,l,c),o.silent||this.emit("added",e,n,r)}removeResourceBundle(e,n){this.hasResourceBundle(e,n)&&delete this.data[e][n],this.removeNamespaces(n),this.emit("removed",e,n)}hasResourceBundle(e,n){return this.getResource(e,n)!==void 0}getResourceBundle(e,n){return n||(n=this.options.defaultNS),this.getResource(e,n)}getDataByLanguage(e){return this.data[e]}hasLanguageSomeTranslations(e){const n=this.getDataByLanguage(e);return!!(n&&Object.keys(n)||[]).find(i=>n[i]&&Object.keys(n[i]).length>0)}toJSON(){return this.data}}var IY={processors:{},addPostProcessor(t){this.processors[t.name]=t},handle(t,e,n,r,i){return t.forEach(s=>{e=this.processors[s]?.process(e,n,r,i)??e}),e}};const zY=Symbol("i18next/PATH_KEY");function tue(){const t=[],e=Object.create(null);let n;return e.get=(r,i)=>(n?.revoke?.(),i===zY?t:(t.push(i),n=Proxy.revocable(r,e),n.proxy)),Proxy.revocable(Object.create(null),e).proxy}function L3(t,e){const{[zY]:n}=t(tue());return n.join(e?.keySeparator??".")}const U8={},fM=t=>!Hn(t)&&typeof t!="boolean"&&typeof t!="number";class lN extends EP{constructor(e,n={}){super(),$de(["resourceStore","languageUtils","pluralResolver","interpolator","backendConnector","i18nFormat","utils"],e,this),this.options=n,this.options.keySeparator===void 0&&(this.options.keySeparator="."),this.logger=Cd.create("translator")}changeLanguage(e){e&&(this.language=e)}exists(e,n={interpolation:{}}){const r={...n};if(e==null)return!1;const i=this.resolve(e,r);if(i?.res===void 0)return!1;const s=fM(i.res);return!(r.returnObjects===!1&&s)}extractFromKey(e,n){let r=n.nsSeparator!==void 0?n.nsSeparator:this.options.nsSeparator;r===void 0&&(r=":");const i=n.keySeparator!==void 0?n.keySeparator:this.options.keySeparator;let s=n.ns||this.options.defaultNS||[];const o=r&&e.indexOf(r)>-1,l=!this.options.userDefinedKeySeparator&&!n.keySeparator&&!this.options.userDefinedNsSeparator&&!n.nsSeparator&&!Jde(e,r,i);if(o&&!l){const c=e.match(this.interpolator.nestingRegexp);if(c&&c.length>0)return{key:e,namespaces:Hn(s)?[s]:s};const d=e.split(r);(r!==i||r===i&&this.options.ns.indexOf(d[0])>-1)&&(s=d.shift()),e=d.join(i)}return{key:e,namespaces:Hn(s)?[s]:s}}translate(e,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||(i={}),e==null)return"";typeof e=="function"&&(e=L3(e,{...this.options,...i})),Array.isArray(e)||(e=[String(e)]);const s=i.returnDetails!==void 0?i.returnDetails:this.options.returnDetails,o=i.keySeparator!==void 0?i.keySeparator:this.options.keySeparator,{key:l,namespaces:c}=this.extractFromKey(e[e.length-1],i),d=c[c.length-1];let u=i.nsSeparator!==void 0?i.nsSeparator:this.options.nsSeparator;u===void 0&&(u=":");const m=i.lng||this.language,p=i.appendNamespaceToCIMode||this.options.appendNamespaceToCIMode;if(m?.toLowerCase()==="cimode")return p?s?{res:`${d}${u}${l}`,usedKey:l,exactUsedKey:l,usedLng:m,usedNS:d,usedParams:this.getUsedParamsDetails(i)}:`${d}${u}${l}`:s?{res:l,usedKey:l,exactUsedKey:l,usedLng:m,usedNS:d,usedParams:this.getUsedParamsDetails(i)}:l;const f=this.resolve(e,i);let x=f?.res;const v=f?.usedKey||l,b=f?.exactUsedKey||l,g=["[object Number]","[object Function]","[object RegExp]"],_=i.joinArrays!==void 0?i.joinArrays:this.options.joinArrays,C=!this.i18nFormat||this.i18nFormat.handleAsObject,P=i.count!==void 0&&!Hn(i.count),N=lN.hasDefaultValue(i),A=P?this.pluralResolver.getSuffix(m,i.count,i):"",T=i.ordinal&&P?this.pluralResolver.getSuffix(m,i.count,{ordinal:!1}):"",F=P&&!i.ordinal&&i.count===0,k=F&&i[`defaultValue${this.options.pluralSeparator}zero`]||i[`defaultValue${A}`]||i[`defaultValue${T}`]||i.defaultValue;let D=x;C&&!x&&N&&(D=k);const H=fM(D),z=Object.prototype.toString.apply(D);if(C&&D&&H&&g.indexOf(z)<0&&!(Hn(_)&&Array.isArray(D))){if(!i.returnObjects&&!this.options.returnObjects){this.options.returnedObjectHandler||this.logger.warn("accessing an object - but returnObjects options is not enabled!");const Y=this.options.returnedObjectHandler?this.options.returnedObjectHandler(v,D,{...i,ns:c}):`key '${l} (${this.language})' returned an object instead of string.`;return s?(f.res=Y,f.usedParams=this.getUsedParamsDetails(i),f):Y}if(o){const Y=Array.isArray(D),L=Y?[]:{},te=Y?b:v;for(const ae in D)if(Object.prototype.hasOwnProperty.call(D,ae)){const J=`${te}${o}${ae}`;N&&!x?L[ae]=this.translate(J,{...i,defaultValue:fM(k)?k[ae]:void 0,joinArrays:!1,ns:c}):L[ae]=this.translate(J,{...i,joinArrays:!1,ns:c}),L[ae]===J&&(L[ae]=D[ae])}x=L}}else if(C&&Hn(_)&&Array.isArray(x))x=x.join(_),x&&(x=this.extendTranslation(x,e,i,r));else{let Y=!1,L=!1;!this.isValidLookup(x)&&N&&(Y=!0,x=k),this.isValidLookup(x)||(L=!0,x=l);const ae=(i.missingKeyNoValueFallbackToKey||this.options.missingKeyNoValueFallbackToKey)&&L?void 0:x,J=N&&k!==x&&this.options.updateMissing;if(L||Y||J){if(this.logger.log(J?"updateKey":"missingKey",m,d,l,J?k:x),o){const W=this.resolve(l,{...i,keySeparator:!1});W&&W.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 le=[];const se=this.languageUtils.getFallbackCodes(this.options.fallbackLng,i.lng||this.language);if(this.options.saveMissingTo==="fallback"&&se&&se[0])for(let W=0;W{const be=N&&fe!==x?fe:ae;this.options.missingKeyHandler?this.options.missingKeyHandler(W,d,ne,be,J,i):this.backendConnector?.saveMissing&&this.backendConnector.saveMissing(W,d,ne,be,J,i),this.emit("missingKey",W,d,ne,x)};this.options.saveMissing&&(this.options.saveMissingPlurals&&P?le.forEach(W=>{const ne=this.pluralResolver.getSuffixes(W,i);F&&i[`defaultValue${this.options.pluralSeparator}zero`]&&ne.indexOf(`${this.options.pluralSeparator}zero`)<0&&ne.push(`${this.options.pluralSeparator}zero`),ne.forEach(fe=>{oe([W],l+fe,i[`defaultValue${fe}`]||k)})}):oe(le,l,k))}x=this.extendTranslation(x,e,i,f,r),L&&x===l&&this.options.appendNamespaceToMissingKey&&(x=`${d}${u}${l}`),(L||Y)&&this.options.parseMissingKeyHandler&&(x=this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey?`${d}${u}${l}`:l,Y?x:void 0,i))}return s?(f.res=x,f.usedParams=this.getUsedParamsDetails(i),f):x}extendTranslation(e,n,r,i,s){if(this.i18nFormat?.parse)e=this.i18nFormat.parse(e,{...this.options.interpolation.defaultVariables,...r},r.lng||this.language||i.usedLng,i.usedNS,i.usedKey,{resolved:i});else if(!r.skipInterpolation){r.interpolation&&this.interpolator.init({...r,interpolation:{...this.options.interpolation,...r.interpolation}});const c=Hn(e)&&(r?.interpolation?.skipOnVariables!==void 0?r.interpolation.skipOnVariables:this.options.interpolation.skipOnVariables);let d;if(c){const m=e.match(this.interpolator.nestingRegexp);d=m&&m.length}let u=r.replace&&!Hn(r.replace)?r.replace:r;if(this.options.interpolation.defaultVariables&&(u={...this.options.interpolation.defaultVariables,...u}),e=this.interpolator.interpolate(e,u,r.lng||this.language||i.usedLng,r),c){const m=e.match(this.interpolator.nestingRegexp),p=m&&m.length;ds?.[0]===m[0]&&!r.context?(this.logger.warn(`It seems you are nesting recursively key: ${m[0]} in key: ${n[0]}`),null):this.translate(...m,n),r)),r.interpolation&&this.interpolator.reset()}const o=r.postProcess||this.options.postProcess,l=Hn(o)?[o]:o;return e!=null&&l?.length&&r.applyPostProcessor!==!1&&(e=IY.handle(l,e,n,this.options&&this.options.postProcessPassResolved?{i18nResolved:{...i,usedParams:this.getUsedParamsDetails(r)},...r}:r,this)),e}resolve(e,n={}){let r,i,s,o,l;return Hn(e)&&(e=[e]),e.forEach(c=>{if(this.isValidLookup(r))return;const d=this.extractFromKey(c,n),u=d.key;i=u;let m=d.namespaces;this.options.fallbackNS&&(m=m.concat(this.options.fallbackNS));const p=n.count!==void 0&&!Hn(n.count),f=p&&!n.ordinal&&n.count===0,x=n.context!==void 0&&(Hn(n.context)||typeof n.context=="number")&&n.context!=="",v=n.lngs?n.lngs:this.languageUtils.toResolveHierarchy(n.lng||this.language,n.fallbackLng);m.forEach(b=>{this.isValidLookup(r)||(l=b,!U8[`${v[0]}-${b}`]&&this.utils?.hasLoadedNamespace&&!this.utils?.hasLoadedNamespace(l)&&(U8[`${v[0]}-${b}`]=!0,this.logger.warn(`key "${i}" for languages "${v.join(", ")}" won't get resolved as namespace "${l}" 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!!!")),v.forEach(g=>{if(this.isValidLookup(r))return;o=g;const _=[u];if(this.i18nFormat?.addLookupKeys)this.i18nFormat.addLookupKeys(_,u,g,b,n);else{let P;p&&(P=this.pluralResolver.getSuffix(g,n.count,n));const N=`${this.options.pluralSeparator}zero`,A=`${this.options.pluralSeparator}ordinal${this.options.pluralSeparator}`;if(p&&(n.ordinal&&P.indexOf(A)===0&&_.push(u+P.replace(A,this.options.pluralSeparator)),_.push(u+P),f&&_.push(u+N)),x){const T=`${u}${this.options.contextSeparator||"_"}${n.context}`;_.push(T),p&&(n.ordinal&&P.indexOf(A)===0&&_.push(T+P.replace(A,this.options.pluralSeparator)),_.push(T+P),f&&_.push(T+N))}}let C;for(;C=_.pop();)this.isValidLookup(r)||(s=C,r=this.getResource(g,b,C,n))}))})}),{res:r,usedKey:i,exactUsedKey:s,usedLng:o,usedNS:l}}isValidLookup(e){return e!==void 0&&!(!this.options.returnNull&&e===null)&&!(!this.options.returnEmptyString&&e==="")}getResource(e,n,r,i={}){return this.i18nFormat?.getResource?this.i18nFormat.getResource(e,n,r,i):this.resourceStore.getResource(e,n,r,i)}getUsedParamsDetails(e={}){const n=["defaultValue","ordinal","context","replace","lng","lngs","fallbackLng","ns","keySeparator","nsSeparator","returnObjects","returnDetails","joinArrays","postProcess","interpolation"],r=e.replace&&!Hn(e.replace);let i=r?e.replace:e;if(r&&typeof e.count<"u"&&(i.count=e.count),this.options.interpolation.defaultVariables&&(i={...this.options.interpolation.defaultVariables,...i}),!r){i={...i};for(const s of n)delete i[s]}return i}static hasDefaultValue(e){const n="defaultValue";for(const r in e)if(Object.prototype.hasOwnProperty.call(e,r)&&n===r.substring(0,n.length)&&e[r]!==void 0)return!0;return!1}}class B8{constructor(e){this.options=e,this.supportedLngs=this.options.supportedLngs||!1,this.logger=Cd.create("languageUtils")}getScriptPartFromCode(e){if(e=G0(e),!e||e.indexOf("-")<0)return null;const n=e.split("-");return n.length===2||(n.pop(),n[n.length-1].toLowerCase()==="x")?null:this.formatLanguageCode(n.join("-"))}getLanguagePartFromCode(e){if(e=G0(e),!e||e.indexOf("-")<0)return e;const n=e.split("-");return this.formatLanguageCode(n[0])}formatLanguageCode(e){if(Hn(e)&&e.indexOf("-")>-1){let n;try{n=Intl.getCanonicalLocales(e)[0]}catch{}return n&&this.options.lowerCaseLng&&(n=n.toLowerCase()),n||(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 n;return e.forEach(r=>{if(n)return;const i=this.formatLanguageCode(r);(!this.options.supportedLngs||this.isSupportedCode(i))&&(n=i)}),!n&&this.options.supportedLngs&&e.forEach(r=>{if(n)return;const i=this.getScriptPartFromCode(r);if(this.isSupportedCode(i))return n=i;const s=this.getLanguagePartFromCode(r);if(this.isSupportedCode(s))return n=s;n=this.options.supportedLngs.find(o=>{if(o===s)return o;if(!(o.indexOf("-")<0&&s.indexOf("-")<0)&&(o.indexOf("-")>0&&s.indexOf("-")<0&&o.substring(0,o.indexOf("-"))===s||o.indexOf(s)===0&&s.length>1))return o})}),n||(n=this.getFallbackCodes(this.options.fallbackLng)[0]),n}getFallbackCodes(e,n){if(!e)return[];if(typeof e=="function"&&(e=e(n)),Hn(e)&&(e=[e]),Array.isArray(e))return e;if(!n)return e.default||[];let r=e[n];return r||(r=e[this.getScriptPartFromCode(n)]),r||(r=e[this.formatLanguageCode(n)]),r||(r=e[this.getLanguagePartFromCode(n)]),r||(r=e.default),r||[]}toResolveHierarchy(e,n){const r=this.getFallbackCodes((n===!1?[]:n)||this.options.fallbackLng||[],e),i=[],s=o=>{o&&(this.isSupportedCode(o)?i.push(o):this.logger.warn(`rejecting language code not found in supportedLngs: ${o}`))};return Hn(e)&&(e.indexOf("-")>-1||e.indexOf("_")>-1)?(this.options.load!=="languageOnly"&&s(this.formatLanguageCode(e)),this.options.load!=="languageOnly"&&this.options.load!=="currentOnly"&&s(this.getScriptPartFromCode(e)),this.options.load!=="currentOnly"&&s(this.getLanguagePartFromCode(e))):Hn(e)&&s(this.formatLanguageCode(e)),r.forEach(o=>{i.indexOf(o)<0&&s(this.formatLanguageCode(o))}),i}}const H8={zero:0,one:1,two:2,few:3,many:4,other:5},q8={select:t=>t===1?"one":"other",resolvedOptions:()=>({pluralCategories:["one","other"]})};class nue{constructor(e,n={}){this.languageUtils=e,this.options=n,this.logger=Cd.create("pluralResolver"),this.pluralRulesCache={}}addRule(e,n){this.rules[e]=n}clearCache(){this.pluralRulesCache={}}getRule(e,n={}){const r=G0(e==="dev"?"en":e),i=n.ordinal?"ordinal":"cardinal",s=JSON.stringify({cleanedCode:r,type:i});if(s in this.pluralRulesCache)return this.pluralRulesCache[s];let o;try{o=new Intl.PluralRules(r,{type:i})}catch{if(!Intl)return this.logger.error("No Intl support, please use an Intl polyfill!"),q8;if(!e.match(/-|_/))return q8;const c=this.languageUtils.getLanguagePartFromCode(e);o=this.getRule(c,n)}return this.pluralRulesCache[s]=o,o}needsPlural(e,n={}){let r=this.getRule(e,n);return r||(r=this.getRule("dev",n)),r?.resolvedOptions().pluralCategories.length>1}getPluralFormsOfKey(e,n,r={}){return this.getSuffixes(e,r).map(i=>`${n}${i}`)}getSuffixes(e,n={}){let r=this.getRule(e,n);return r||(r=this.getRule("dev",n)),r?r.resolvedOptions().pluralCategories.sort((i,s)=>H8[i]-H8[s]).map(i=>`${this.options.prepend}${n.ordinal?`ordinal${this.options.prepend}`:""}${i}`):[]}getSuffix(e,n,r={}){const i=this.getRule(e,r);return i?`${this.options.prepend}${r.ordinal?`ordinal${this.options.prepend}`:""}${i.select(n)}`:(this.logger.warn(`no plural rule found for: ${e}`),this.getSuffix("dev",n,r))}}const $8=(t,e,n,r=".",i=!0)=>{let s=Wde(t,e,n);return!s&&i&&Hn(n)&&(s=R3(t,n,r),s===void 0&&(s=R3(e,n,r))),s},gM=t=>t.replace(/\$/g,"$$$$");class rue{constructor(e={}){this.logger=Cd.create("interpolator"),this.options=e,this.format=e?.interpolation?.format||(n=>n),this.init(e)}init(e={}){e.interpolation||(e.interpolation={escapeValue:!0});const{escape:n,escapeValue:r,useRawValueToEscape:i,prefix:s,prefixEscaped:o,suffix:l,suffixEscaped:c,formatSeparator:d,unescapeSuffix:u,unescapePrefix:m,nestingPrefix:p,nestingPrefixEscaped:f,nestingSuffix:x,nestingSuffixEscaped:v,nestingOptionsSeparator:b,maxReplaces:g,alwaysFormat:_}=e.interpolation;this.escape=n!==void 0?n:Xde,this.escapeValue=r!==void 0?r:!0,this.useRawValueToEscape=i!==void 0?i:!1,this.prefix=s?ub(s):o||"{{",this.suffix=l?ub(l):c||"}}",this.formatSeparator=d||",",this.unescapePrefix=u?"":m||"-",this.unescapeSuffix=this.unescapePrefix?"":u||"",this.nestingPrefix=p?ub(p):f||ub("$t("),this.nestingSuffix=x?ub(x):v||ub(")"),this.nestingOptionsSeparator=b||",",this.maxReplaces=g||1e3,this.alwaysFormat=_!==void 0?_:!1,this.resetRegExp()}reset(){this.options&&this.init(this.options)}resetRegExp(){const e=(n,r)=>n?.source===r?(n.lastIndex=0,n):new RegExp(r,"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,n,r,i){let s,o,l;const c=this.options&&this.options.interpolation&&this.options.interpolation.defaultVariables||{},d=f=>{if(f.indexOf(this.formatSeparator)<0){const g=$8(n,c,f,this.options.keySeparator,this.options.ignoreJSONStructure);return this.alwaysFormat?this.format(g,void 0,r,{...i,...n,interpolationkey:f}):g}const x=f.split(this.formatSeparator),v=x.shift().trim(),b=x.join(this.formatSeparator).trim();return this.format($8(n,c,v,this.options.keySeparator,this.options.ignoreJSONStructure),b,r,{...i,...n,interpolationkey:v})};this.resetRegExp();const u=i?.missingInterpolationHandler||this.options.missingInterpolationHandler,m=i?.interpolation?.skipOnVariables!==void 0?i.interpolation.skipOnVariables:this.options.interpolation.skipOnVariables;return[{regex:this.regexpUnescape,safeValue:f=>gM(f)},{regex:this.regexp,safeValue:f=>this.escapeValue?gM(this.escape(f)):gM(f)}].forEach(f=>{for(l=0;s=f.regex.exec(e);){const x=s[1].trim();if(o=d(x),o===void 0)if(typeof u=="function"){const b=u(e,s,i);o=Hn(b)?b:""}else if(i&&Object.prototype.hasOwnProperty.call(i,x))o="";else if(m){o=s[0];continue}else this.logger.warn(`missed to pass in variable ${x} for interpolating ${e}`),o="";else!Hn(o)&&!this.useRawValueToEscape&&(o=R8(o));const v=f.safeValue(o);if(e=e.replace(s[0],v),m?(f.regex.lastIndex+=o.length,f.regex.lastIndex-=s[0].length):f.regex.lastIndex=0,l++,l>=this.maxReplaces)break}}),e}nest(e,n,r={}){let i,s,o;const l=(c,d)=>{const u=this.nestingOptionsSeparator;if(c.indexOf(u)<0)return c;const m=c.split(new RegExp(`${u}[ ]*{`));let p=`{${m[1]}`;c=m[0],p=this.interpolate(p,o);const f=p.match(/'/g),x=p.match(/"/g);((f?.length??0)%2===0&&!x||x.length%2!==0)&&(p=p.replace(/'/g,'"'));try{o=JSON.parse(p),d&&(o={...d,...o})}catch(v){return this.logger.warn(`failed parsing options string in nesting for key ${c}`,v),`${c}${u}${p}`}return o.defaultValue&&o.defaultValue.indexOf(this.prefix)>-1&&delete o.defaultValue,c};for(;i=this.nestingRegexp.exec(e);){let c=[];o={...r},o=o.replace&&!Hn(o.replace)?o.replace:o,o.applyPostProcessor=!1,delete o.defaultValue;const d=/{.*}/.test(i[1])?i[1].lastIndexOf("}")+1:i[1].indexOf(this.formatSeparator);if(d!==-1&&(c=i[1].slice(d).split(this.formatSeparator).map(u=>u.trim()).filter(Boolean),i[1]=i[1].slice(0,d)),s=n(l.call(this,i[1].trim(),o),o),s&&i[0]===e&&!Hn(s))return s;Hn(s)||(s=R8(s)),s||(this.logger.warn(`missed to resolve ${i[1]} for nesting ${e}`),s=""),c.length&&(s=c.reduce((u,m)=>this.format(u,m,r.lng,{...r,interpolationkey:i[1].trim()}),s.trim())),e=e.replace(i[0],s),this.regexp.lastIndex=0}return e}}const aue=t=>{let e=t.toLowerCase().trim();const n={};if(t.indexOf("(")>-1){const r=t.split("(");e=r[0].toLowerCase().trim();const i=r[1].substring(0,r[1].length-1);e==="currency"&&i.indexOf(":")<0?n.currency||(n.currency=i.trim()):e==="relativetime"&&i.indexOf(":")<0?n.range||(n.range=i.trim()):i.split(";").forEach(o=>{if(o){const[l,...c]=o.split(":"),d=c.join(":").trim().replace(/^'+|'+$/g,""),u=l.trim();n[u]||(n[u]=d),d==="false"&&(n[u]=!1),d==="true"&&(n[u]=!0),isNaN(d)||(n[u]=parseInt(d,10))}})}return{formatName:e,formatOptions:n}},V8=t=>{const e={};return(n,r,i)=>{let s=i;i&&i.interpolationkey&&i.formatParams&&i.formatParams[i.interpolationkey]&&i[i.interpolationkey]&&(s={...s,[i.interpolationkey]:void 0});const o=r+JSON.stringify(s);let l=e[o];return l||(l=t(G0(r),i),e[o]=l),l(n)}},iue=t=>(e,n,r)=>t(G0(n),r)(e);class sue{constructor(e={}){this.logger=Cd.create("formatter"),this.options=e,this.init(e)}init(e,n={interpolation:{}}){this.formatSeparator=n.interpolation.formatSeparator||",";const r=n.cacheInBuiltFormats?V8:iue;this.formats={number:r((i,s)=>{const o=new Intl.NumberFormat(i,{...s});return l=>o.format(l)}),currency:r((i,s)=>{const o=new Intl.NumberFormat(i,{...s,style:"currency"});return l=>o.format(l)}),datetime:r((i,s)=>{const o=new Intl.DateTimeFormat(i,{...s});return l=>o.format(l)}),relativetime:r((i,s)=>{const o=new Intl.RelativeTimeFormat(i,{...s});return l=>o.format(l,s.range||"day")}),list:r((i,s)=>{const o=new Intl.ListFormat(i,{...s});return l=>o.format(l)})}}add(e,n){this.formats[e.toLowerCase().trim()]=n}addCached(e,n){this.formats[e.toLowerCase().trim()]=V8(n)}format(e,n,r,i={}){const s=n.split(this.formatSeparator);if(s.length>1&&s[0].indexOf("(")>1&&s[0].indexOf(")")<0&&s.find(l=>l.indexOf(")")>-1)){const l=s.findIndex(c=>c.indexOf(")")>-1);s[0]=[s[0],...s.splice(1,l)].join(this.formatSeparator)}return s.reduce((l,c)=>{const{formatName:d,formatOptions:u}=aue(c);if(this.formats[d]){let m=l;try{const p=i?.formatParams?.[i.interpolationkey]||{},f=p.locale||p.lng||i.locale||i.lng||r;m=this.formats[d](l,f,{...u,...i,...p})}catch(p){this.logger.warn(p)}return m}else this.logger.warn(`there was no format function for ${d}`);return l},e)}}const oue=(t,e)=>{t.pending[e]!==void 0&&(delete t.pending[e],t.pendingCount--)};class lue extends EP{constructor(e,n,r,i={}){super(),this.backend=e,this.store=n,this.services=r,this.languageUtils=r.languageUtils,this.options=i,this.logger=Cd.create("backendConnector"),this.waitingReads=[],this.maxParallelReads=i.maxParallelReads||10,this.readingCalls=0,this.maxRetries=i.maxRetries>=0?i.maxRetries:5,this.retryTimeout=i.retryTimeout>=1?i.retryTimeout:350,this.state={},this.queue=[],this.backend?.init?.(r,i.backend,i)}queueLoad(e,n,r,i){const s={},o={},l={},c={};return e.forEach(d=>{let u=!0;n.forEach(m=>{const p=`${d}|${m}`;!r.reload&&this.store.hasResourceBundle(d,m)?this.state[p]=2:this.state[p]<0||(this.state[p]===1?o[p]===void 0&&(o[p]=!0):(this.state[p]=1,u=!1,o[p]===void 0&&(o[p]=!0),s[p]===void 0&&(s[p]=!0),c[m]===void 0&&(c[m]=!0)))}),u||(l[d]=!0)}),(Object.keys(s).length||Object.keys(o).length)&&this.queue.push({pending:o,pendingCount:Object.keys(o).length,loaded:{},errors:[],callback:i}),{toLoad:Object.keys(s),pending:Object.keys(o),toLoadLanguages:Object.keys(l),toLoadNamespaces:Object.keys(c)}}loaded(e,n,r){const i=e.split("|"),s=i[0],o=i[1];n&&this.emit("failedLoading",s,o,n),!n&&r&&this.store.addResourceBundle(s,o,r,void 0,void 0,{skipCopy:!0}),this.state[e]=n?-1:2,n&&r&&(this.state[e]=0);const l={};this.queue.forEach(c=>{Gde(c.loaded,[s],o),oue(c,e),n&&c.errors.push(n),c.pendingCount===0&&!c.done&&(Object.keys(c.loaded).forEach(d=>{l[d]||(l[d]={});const u=c.loaded[d];u.length&&u.forEach(m=>{l[d][m]===void 0&&(l[d][m]=!0)})}),c.done=!0,c.errors.length?c.callback(c.errors):c.callback())}),this.emit("loaded",l),this.queue=this.queue.filter(c=>!c.done)}read(e,n,r,i=0,s=this.retryTimeout,o){if(!e.length)return o(null,{});if(this.readingCalls>=this.maxParallelReads){this.waitingReads.push({lng:e,ns:n,fcName:r,tried:i,wait:s,callback:o});return}this.readingCalls++;const l=(d,u)=>{if(this.readingCalls--,this.waitingReads.length>0){const m=this.waitingReads.shift();this.read(m.lng,m.ns,m.fcName,m.tried,m.wait,m.callback)}if(d&&u&&i{this.read.call(this,e,n,r,i+1,s*2,o)},s);return}o(d,u)},c=this.backend[r].bind(this.backend);if(c.length===2){try{const d=c(e,n);d&&typeof d.then=="function"?d.then(u=>l(null,u)).catch(l):l(null,d)}catch(d){l(d)}return}return c(e,n,l)}prepareLoading(e,n,r={},i){if(!this.backend)return this.logger.warn("No backend was added via i18next.use. Will not load resources."),i&&i();Hn(e)&&(e=this.languageUtils.toResolveHierarchy(e)),Hn(n)&&(n=[n]);const s=this.queueLoad(e,n,r,i);if(!s.toLoad.length)return s.pending.length||i(),null;s.toLoad.forEach(o=>{this.loadOne(o)})}load(e,n,r){this.prepareLoading(e,n,{},r)}reload(e,n,r){this.prepareLoading(e,n,{reload:!0},r)}loadOne(e,n=""){const r=e.split("|"),i=r[0],s=r[1];this.read(i,s,"read",void 0,void 0,(o,l)=>{o&&this.logger.warn(`${n}loading namespace ${s} for language ${i} failed`,o),!o&&l&&this.logger.log(`${n}loaded namespace ${s} for language ${i}`,l),this.loaded(e,o,l)})}saveMissing(e,n,r,i,s,o={},l=()=>{}){if(this.services?.utils?.hasLoadedNamespace&&!this.services?.utils?.hasLoadedNamespace(n)){this.logger.warn(`did not save key "${r}" as the namespace "${n}" 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(!(r==null||r==="")){if(this.backend?.create){const c={...o,isUpdate:s},d=this.backend.create.bind(this.backend);if(d.length<6)try{let u;d.length===5?u=d(e,n,r,i,c):u=d(e,n,r,i),u&&typeof u.then=="function"?u.then(m=>l(null,m)).catch(l):l(null,u)}catch(u){l(u)}else d(e,n,r,i,l,c)}!e||!e[0]||this.store.addResource(e[0],n,r,i)}}}const G8=()=>({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:t=>{let e={};if(typeof t[1]=="object"&&(e=t[1]),Hn(t[1])&&(e.defaultValue=t[1]),Hn(t[2])&&(e.tDescription=t[2]),typeof t[2]=="object"||typeof t[3]=="object"){const n=t[3]||t[2];Object.keys(n).forEach(r=>{e[r]=n[r]})}return e},interpolation:{escapeValue:!0,format:t=>t,prefix:"{{",suffix:"}}",formatSeparator:",",unescapePrefix:"-",nestingPrefix:"$t(",nestingSuffix:")",nestingOptionsSeparator:",",maxReplaces:1e3,skipOnVariables:!0},cacheInBuiltFormats:!0}),W8=t=>(Hn(t.ns)&&(t.ns=[t.ns]),Hn(t.fallbackLng)&&(t.fallbackLng=[t.fallbackLng]),Hn(t.fallbackNS)&&(t.fallbackNS=[t.fallbackNS]),t.supportedLngs?.indexOf?.("cimode")<0&&(t.supportedLngs=t.supportedLngs.concat(["cimode"])),typeof t.initImmediate=="boolean"&&(t.initAsync=t.initImmediate),t),B_=()=>{},cue=t=>{Object.getOwnPropertyNames(Object.getPrototypeOf(t)).forEach(n=>{typeof t[n]=="function"&&(t[n]=t[n].bind(t))})};class v0 extends EP{constructor(e={},n){if(super(),this.options=W8(e),this.services={},this.logger=Cd,this.modules={external:[]},cue(this),n&&!this.isInitialized&&!e.isClone){if(!this.options.initAsync)return this.init(e,n),this;setTimeout(()=>{this.init(e,n)},0)}}init(e={},n){this.isInitializing=!0,typeof e=="function"&&(n=e,e={}),e.defaultNS==null&&e.ns&&(Hn(e.ns)?e.defaultNS=e.ns:e.ns.indexOf("translation")<0&&(e.defaultNS=e.ns[0]));const r=G8();this.options={...r,...this.options,...W8(e)},this.options.interpolation={...r.interpolation,...this.options.interpolation},e.keySeparator!==void 0&&(this.options.userDefinedKeySeparator=e.keySeparator),e.nsSeparator!==void 0&&(this.options.userDefinedNsSeparator=e.nsSeparator);const i=d=>d?typeof d=="function"?new d:d:null;if(!this.options.isClone){this.modules.logger?Cd.init(i(this.modules.logger),this.options):Cd.init(null,this.options);let d;this.modules.formatter?d=this.modules.formatter:d=sue;const u=new B8(this.options);this.store=new z8(this.options.resources,this.options);const m=this.services;m.logger=Cd,m.resourceStore=this.store,m.languageUtils=u,m.pluralResolver=new nue(u,{prepend:this.options.pluralSeparator,simplifyPluralSuffix:this.options.simplifyPluralSuffix}),this.options.interpolation.format&&this.options.interpolation.format!==r.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"),d&&(!this.options.interpolation.format||this.options.interpolation.format===r.interpolation.format)&&(m.formatter=i(d),m.formatter.init&&m.formatter.init(m,this.options),this.options.interpolation.format=m.formatter.format.bind(m.formatter)),m.interpolator=new rue(this.options),m.utils={hasLoadedNamespace:this.hasLoadedNamespace.bind(this)},m.backendConnector=new lue(i(this.modules.backend),m.resourceStore,m,this.options),m.backendConnector.on("*",(f,...x)=>{this.emit(f,...x)}),this.modules.languageDetector&&(m.languageDetector=i(this.modules.languageDetector),m.languageDetector.init&&m.languageDetector.init(m,this.options.detection,this.options)),this.modules.i18nFormat&&(m.i18nFormat=i(this.modules.i18nFormat),m.i18nFormat.init&&m.i18nFormat.init(this)),this.translator=new lN(this.services,this.options),this.translator.on("*",(f,...x)=>{this.emit(f,...x)}),this.modules.external.forEach(f=>{f.init&&f.init(this)})}if(this.format=this.options.interpolation.format,n||(n=B_),this.options.fallbackLng&&!this.services.languageDetector&&!this.options.lng){const d=this.services.languageUtils.getFallbackCodes(this.options.fallbackLng);d.length>0&&d[0]!=="dev"&&(this.options.lng=d[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(d=>{this[d]=(...u)=>this.store[d](...u)}),["addResource","addResources","addResourceBundle","removeResourceBundle"].forEach(d=>{this[d]=(...u)=>(this.store[d](...u),this)});const l=Sv(),c=()=>{const d=(u,m)=>{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),l.resolve(m),n(u,m)};if(this.languages&&!this.isInitialized)return d(null,this.t.bind(this));this.changeLanguage(this.options.lng,d)};return this.options.resources||!this.options.initAsync?c():setTimeout(c,0),l}loadResources(e,n=B_){let r=n;const i=Hn(e)?e:this.language;if(typeof e=="function"&&(r=e),!this.options.resources||this.options.partialBundledLanguages){if(i?.toLowerCase()==="cimode"&&(!this.options.preload||this.options.preload.length===0))return r();const s=[],o=l=>{if(!l||l==="cimode")return;this.services.languageUtils.toResolveHierarchy(l).forEach(d=>{d!=="cimode"&&s.indexOf(d)<0&&s.push(d)})};i?o(i):this.services.languageUtils.getFallbackCodes(this.options.fallbackLng).forEach(c=>o(c)),this.options.preload?.forEach?.(l=>o(l)),this.services.backendConnector.load(s,this.options.ns,l=>{!l&&!this.resolvedLanguage&&this.language&&this.setResolvedLanguage(this.language),r(l)})}else r(null)}reloadResources(e,n,r){const i=Sv();return typeof e=="function"&&(r=e,e=void 0),typeof n=="function"&&(r=n,n=void 0),e||(e=this.languages),n||(n=this.options.ns),r||(r=B_),this.services.backendConnector.reload(e,n,s=>{i.resolve(),r(s)}),i}use(e){if(!e)throw new Error("You are passing an undefined module! Please check the object you are passing to i18next.use()");if(!e.type)throw new 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"&&IY.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 n=0;n-1)&&this.store.hasLanguageSomeTranslations(r)){this.resolvedLanguage=r;break}}!this.resolvedLanguage&&this.languages.indexOf(e)<0&&this.store.hasLanguageSomeTranslations(e)&&(this.resolvedLanguage=e,this.languages.unshift(e))}}changeLanguage(e,n){this.isLanguageChangingTo=e;const r=Sv();this.emit("languageChanging",e);const i=l=>{this.language=l,this.languages=this.services.languageUtils.toResolveHierarchy(l),this.resolvedLanguage=void 0,this.setResolvedLanguage(l)},s=(l,c)=>{c?this.isLanguageChangingTo===e&&(i(c),this.translator.changeLanguage(c),this.isLanguageChangingTo=void 0,this.emit("languageChanged",c),this.logger.log("languageChanged",c)):this.isLanguageChangingTo=void 0,r.resolve((...d)=>this.t(...d)),n&&n(l,(...d)=>this.t(...d))},o=l=>{!e&&!l&&this.services.languageDetector&&(l=[]);const c=Hn(l)?l:l&&l[0],d=this.store.hasLanguageSomeTranslations(c)?c:this.services.languageUtils.getBestMatchFromCodes(Hn(l)?[l]:l);d&&(this.language||i(d),this.translator.language||this.translator.changeLanguage(d),this.services.languageDetector?.cacheUserLanguage?.(d)),this.loadResources(d,u=>{s(u,d)})};return!e&&this.services.languageDetector&&!this.services.languageDetector.async?o(this.services.languageDetector.detect()):!e&&this.services.languageDetector&&this.services.languageDetector.async?this.services.languageDetector.detect.length===0?this.services.languageDetector.detect().then(o):this.services.languageDetector.detect(o):o(e),r}getFixedT(e,n,r){const i=(s,o,...l)=>{let c;typeof o!="object"?c=this.options.overloadTranslationOptionHandler([s,o].concat(l)):c={...o},c.lng=c.lng||i.lng,c.lngs=c.lngs||i.lngs,c.ns=c.ns||i.ns,c.keyPrefix!==""&&(c.keyPrefix=c.keyPrefix||r||i.keyPrefix);const d=this.options.keySeparator||".";let u;return c.keyPrefix&&Array.isArray(s)?u=s.map(m=>(typeof m=="function"&&(m=L3(m,{...this.options,...o})),`${c.keyPrefix}${d}${m}`)):(typeof s=="function"&&(s=L3(s,{...this.options,...o})),u=c.keyPrefix?`${c.keyPrefix}${d}${s}`:s),this.t(u,c)};return Hn(e)?i.lng=e:i.lngs=e,i.ns=n,i.keyPrefix=r,i}t(...e){return this.translator?.translate(...e)}exists(...e){return this.translator?.exists(...e)}setDefaultNamespace(e){this.options.defaultNS=e}hasLoadedNamespace(e,n={}){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;const r=n.lng||this.resolvedLanguage||this.languages[0],i=this.options?this.options.fallbackLng:!1,s=this.languages[this.languages.length-1];if(r.toLowerCase()==="cimode")return!0;const o=(l,c)=>{const d=this.services.backendConnector.state[`${l}|${c}`];return d===-1||d===0||d===2};if(n.precheck){const l=n.precheck(this,o);if(l!==void 0)return l}return!!(this.hasResourceBundle(r,e)||!this.services.backendConnector.backend||this.options.resources&&!this.options.partialBundledLanguages||o(r,e)&&(!i||o(s,e)))}loadNamespaces(e,n){const r=Sv();return this.options.ns?(Hn(e)&&(e=[e]),e.forEach(i=>{this.options.ns.indexOf(i)<0&&this.options.ns.push(i)}),this.loadResources(i=>{r.resolve(),n&&n(i)}),r):(n&&n(),Promise.resolve())}loadLanguages(e,n){const r=Sv();Hn(e)&&(e=[e]);const i=this.options.preload||[],s=e.filter(o=>i.indexOf(o)<0&&this.services.languageUtils.isSupportedCode(o));return s.length?(this.options.preload=i.concat(s),this.loadResources(o=>{r.resolve(),n&&n(o)}),r):(n&&n(),Promise.resolve())}dir(e){if(e||(e=this.resolvedLanguage||(this.languages?.length>0?this.languages[0]:this.language)),!e)return"rtl";try{const i=new Intl.Locale(e);if(i&&i.getTextInfo){const s=i.getTextInfo();if(s&&s.direction)return s.direction}}catch{}const n=["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"],r=this.services?.languageUtils||new B8(G8());return e.toLowerCase().indexOf("-latn")>1?"ltr":n.indexOf(r.getLanguagePartFromCode(e))>-1||e.toLowerCase().indexOf("-arab")>1?"rtl":"ltr"}static createInstance(e={},n){const r=new v0(e,n);return r.createInstance=v0.createInstance,r}cloneInstance(e={},n=B_){const r=e.forkResourceStore;r&&delete e.forkResourceStore;const i={...this.options,...e,isClone:!0},s=new v0(i);if((e.debug!==void 0||e.prefix!==void 0)&&(s.logger=s.logger.clone(e)),["store","services","language"].forEach(l=>{s[l]=this[l]}),s.services={...this.services},s.services.utils={hasLoadedNamespace:s.hasLoadedNamespace.bind(s)},r){const l=Object.keys(this.store.data).reduce((c,d)=>(c[d]={...this.store.data[d]},c[d]=Object.keys(c[d]).reduce((u,m)=>(u[m]={...c[d][m]},u),c[d]),c),{});s.store=new z8(l,i),s.services.resourceStore=s.store}return s.translator=new lN(s.services,i),s.translator.on("*",(l,...c)=>{s.emit(l,...c)}),s.init(i,n),s.translator.options=i,s.translator.backendConnector.services.utils={hasLoadedNamespace:s.hasLoadedNamespace.bind(s)},s}toJSON(){return{options:this.options,store:this.store,language:this.language,languages:this.languages,resolvedLanguage:this.resolvedLanguage}}}const uo=v0.createInstance();uo.createInstance;uo.dir;uo.init;uo.loadResources;uo.reloadResources;uo.use;uo.changeLanguage;uo.getFixedT;uo.t;uo.exists;uo.setDefaultNamespace;uo.hasLoadedNamespace;uo.loadNamespaces;uo.loadLanguages;const due=(t,e,n,r)=>{const i=[n,{code:e,...r||{}}];if(t?.services?.logger?.forward)return t.services.logger.forward(i,"warn","react-i18next::",!0);Xf(i[0])&&(i[0]=`react-i18next:: ${i[0]}`),t?.services?.logger?.warn?t.services.logger.warn(...i):console?.warn&&console.warn(...i)},K8={},UY=(t,e,n,r)=>{Xf(n)&&K8[n]||(Xf(n)&&(K8[n]=new Date),due(t,e,n,r))},BY=(t,e)=>()=>{if(t.isInitialized)e();else{const n=()=>{setTimeout(()=>{t.off("initialized",n)},0),e()};t.on("initialized",n)}},O3=(t,e,n)=>{t.loadNamespaces(e,BY(t,n))},X8=(t,e,n,r)=>{if(Xf(n)&&(n=[n]),t.options.preload&&t.options.preload.indexOf(e)>-1)return O3(t,n,r);n.forEach(i=>{t.options.ns.indexOf(i)<0&&t.options.ns.push(i)}),t.loadLanguages(e,BY(t,r))},uue=(t,e,n={})=>!e.languages||!e.languages.length?(UY(e,"NO_LANGUAGES","i18n.languages were undefined or empty",{languages:e.languages}),!0):e.hasLoadedNamespace(t,{lng:n.lng,precheck:(r,i)=>{if(n.bindI18n&&n.bindI18n.indexOf("languageChanging")>-1&&r.services.backendConnector.backend&&r.isLanguageChangingTo&&!i(r.isLanguageChangingTo,t))return!1}}),Xf=t=>typeof t=="string",mue=t=>typeof t=="object"&&t!==null,hue=/&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34|nbsp|#160|copy|#169|reg|#174|hellip|#8230|#x2F|#47);/g,pue={"&":"&","&":"&","<":"<","<":"<",">":">",">":">","'":"'","'":"'",""":'"',""":'"'," ":" "," ":" ","©":"©","©":"©","®":"®","®":"®","…":"…","…":"…","/":"/","/":"/"},fue=t=>pue[t],gue=t=>t.replace(hue,fue);let I3={bindI18n:"languageChanged",bindI18nStore:"",transEmptyNodeValue:"",transSupportBasicHtmlNodes:!0,transWrapTextNodes:"",transKeepBasicHtmlNodesFor:["br","strong","i","p"],useSuspense:!0,unescape:gue,transDefaultProps:void 0};const bue=(t={})=>{I3={...I3,...t}},xue=()=>I3;let HY;const yue=t=>{HY=t},vue=()=>HY,wue={type:"3rdParty",init(t){bue(t.options.react),yue(t)}},Sue=w.createContext();class _ue{constructor(){this.usedNamespaces={}}addUsedNamespaces(e){e.forEach(n=>{this.usedNamespaces[n]||(this.usedNamespaces[n]=!0)})}getUsedNamespaces(){return Object.keys(this.usedNamespaces)}}var bM={exports:{}},xM={};var Y8;function kue(){if(Y8)return xM;Y8=1;var t=_g();function e(m,p){return m===p&&(m!==0||1/m===1/p)||m!==m&&p!==p}var n=typeof Object.is=="function"?Object.is:e,r=t.useState,i=t.useEffect,s=t.useLayoutEffect,o=t.useDebugValue;function l(m,p){var f=p(),x=r({inst:{value:f,getSnapshot:p}}),v=x[0].inst,b=x[1];return s(function(){v.value=f,v.getSnapshot=p,c(v)&&b({inst:v})},[m,f,p]),i(function(){return c(v)&&b({inst:v}),m(function(){c(v)&&b({inst:v})})},[m]),o(f),f}function c(m){var p=m.getSnapshot;m=m.value;try{var f=p();return!n(m,f)}catch{return!0}}function d(m,p){return p()}var u=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?d:l;return xM.useSyncExternalStore=t.useSyncExternalStore!==void 0?t.useSyncExternalStore:u,xM}var Q8;function qY(){return Q8||(Q8=1,bM.exports=kue()),bM.exports}var sO=qY();const Nue=(t,e)=>Xf(e)?e:mue(e)&&Xf(e.defaultValue)?e.defaultValue:Array.isArray(t)?t[t.length-1]:t,Cue={t:Nue,ready:!1},Pue=()=>()=>{},Ft=(t,e={})=>{const{i18n:n}=e,{i18n:r,defaultNS:i}=w.useContext(Sue)||{},s=n||r||vue();s&&!s.reportNamespaces&&(s.reportNamespaces=new _ue),s||UY(s,"NO_I18NEXT_INSTANCE","useTranslation: You will need to pass in an i18next instance by using initReactI18next");const o=w.useMemo(()=>({...xue(),...s?.options?.react,...e}),[s,e]),{useSuspense:l,keyPrefix:c}=o,d=i||s?.options?.defaultNS,u=Xf(d)?[d]:d||["translation"],m=w.useMemo(()=>u,u);s?.reportNamespaces?.addUsedNamespaces?.(m);const p=w.useRef(0),f=w.useCallback(k=>{if(!s)return Pue;const{bindI18n:D,bindI18nStore:H}=o,z=()=>{p.current+=1,k()};return D&&s.on(D,z),H&&s.store.on(H,z),()=>{D&&D.split(" ").forEach(Y=>s.off(Y,z)),H&&H.split(" ").forEach(Y=>s.store.off(Y,z))}},[s,o]),x=w.useRef(),v=w.useCallback(()=>{if(!s)return Cue;const k=!!(s.isInitialized||s.initializedStoreOnce)&&m.every(te=>uue(te,s,o)),D=e.lng||s.language,H=p.current,z=x.current;if(z&&z.ready===k&&z.lng===D&&z.keyPrefix===c&&z.revision===H)return z;const L={t:s.getFixedT(D,o.nsMode==="fallback"?m:m[0],c),ready:k,lng:D,keyPrefix:c,revision:H};return x.current=L,L},[s,m,c,o,e.lng]),[b,g]=w.useState(0),{t:_,ready:C}=sO.useSyncExternalStore(f,v,v);w.useEffect(()=>{if(s&&!C&&!l){const k=()=>g(D=>D+1);e.lng?X8(s,e.lng,m,k):O3(s,m,k)}},[s,e.lng,m,C,l,b]);const P=s||{},N=w.useRef(null),A=w.useRef(),T=k=>{const D=Object.getOwnPropertyDescriptors(k);D.__original&&delete D.__original;const H=Object.create(Object.getPrototypeOf(k),D);if(!Object.prototype.hasOwnProperty.call(H,"__original"))try{Object.defineProperty(H,"__original",{value:k,writable:!1,enumerable:!1,configurable:!1})}catch{}return H},F=w.useMemo(()=>{const k=P,D=k?.language;let H=k;k&&(N.current&&N.current.__original===k?A.current!==D?(H=T(k),N.current=H,A.current=D):H=N.current:(H=T(k),N.current=H,A.current=D));const z=[_,H,C];return z.t=_,z.i18n=H,z.ready=C,z},[_,P,C,P.resolvedLanguage,P.language,P.languages]);if(s&&l&&!C)throw new Promise(k=>{const D=()=>k();e.lng?X8(s,e.lng,m,D):O3(s,m,D)});return F},{slice:Tue,forEach:Aue}=[];function jue(t){return Aue.call(Tue.call(arguments,1),e=>{if(e)for(const n in e)t[n]===void 0&&(t[n]=e[n])}),t}function Mue(t){return typeof t!="string"?!1:[/<\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(n=>n.test(t))}const Z8=/^[\u0009\u0020-\u007e\u0080-\u00ff]+$/,Eue=function(t,e){const r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{path:"/"},i=encodeURIComponent(e);let s=`${t}=${i}`;if(r.maxAge>0){const o=r.maxAge-0;if(Number.isNaN(o))throw new Error("maxAge should be a Number");s+=`; Max-Age=${Math.floor(o)}`}if(r.domain){if(!Z8.test(r.domain))throw new TypeError("option domain is invalid");s+=`; Domain=${r.domain}`}if(r.path){if(!Z8.test(r.path))throw new TypeError("option path is invalid");s+=`; Path=${r.path}`}if(r.expires){if(typeof r.expires.toUTCString!="function")throw new TypeError("option expires is invalid");s+=`; Expires=${r.expires.toUTCString()}`}if(r.httpOnly&&(s+="; HttpOnly"),r.secure&&(s+="; Secure"),r.sameSite)switch(typeof r.sameSite=="string"?r.sameSite.toLowerCase():r.sameSite){case!0:s+="; SameSite=Strict";break;case"lax":s+="; SameSite=Lax";break;case"strict":s+="; SameSite=Strict";break;case"none":s+="; SameSite=None";break;default:throw new TypeError("option sameSite is invalid")}return r.partitioned&&(s+="; Partitioned"),s},J8={create(t,e,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=Eue(t,e,i)},read(t){const e=`${t}=`,n=document.cookie.split(";");for(let r=0;r-1&&(r=window.location.hash.substring(window.location.hash.indexOf("?")));const s=r.substring(1).split("&");for(let o=0;o0&&s[o].substring(0,l)===e&&(n=s[o].substring(l+1))}}return n}},Rue={name:"hash",lookup(t){let{lookupHash:e,lookupFromHashIndex:n}=t,r;if(typeof window<"u"){const{hash:i}=window.location;if(i&&i.length>2){const s=i.substring(1);if(e){const o=s.split("&");for(let l=0;l0&&o[l].substring(0,c)===e&&(r=o[l].substring(c+1))}}if(r)return r;if(!r&&n>-1){const o=i.match(/\/([a-zA-Z-]*)/g);return Array.isArray(o)?o[typeof n=="number"?n:0]?.replace("/",""):void 0}}}return r}};let mb=null;const eH=()=>{if(mb!==null)return mb;try{if(mb=typeof window<"u"&&window.localStorage!==null,!mb)return!1;const t="i18next.translate.boo";window.localStorage.setItem(t,"foo"),window.localStorage.removeItem(t)}catch{mb=!1}return mb};var Lue={name:"localStorage",lookup(t){let{lookupLocalStorage:e}=t;if(e&&eH())return window.localStorage.getItem(e)||void 0},cacheUserLanguage(t,e){let{lookupLocalStorage:n}=e;n&&eH()&&window.localStorage.setItem(n,t)}};let hb=null;const tH=()=>{if(hb!==null)return hb;try{if(hb=typeof window<"u"&&window.sessionStorage!==null,!hb)return!1;const t="i18next.translate.boo";window.sessionStorage.setItem(t,"foo"),window.sessionStorage.removeItem(t)}catch{hb=!1}return hb};var Oue={name:"sessionStorage",lookup(t){let{lookupSessionStorage:e}=t;if(e&&tH())return window.sessionStorage.getItem(e)||void 0},cacheUserLanguage(t,e){let{lookupSessionStorage:n}=e;n&&tH()&&window.sessionStorage.setItem(n,t)}},Iue={name:"navigator",lookup(t){const e=[];if(typeof navigator<"u"){const{languages:n,userLanguage:r,language:i}=navigator;if(n)for(let s=0;s0?e:void 0}},zue={name:"htmlTag",lookup(t){let{htmlTag:e}=t,n;const r=e||(typeof document<"u"?document.documentElement:null);return r&&typeof r.getAttribute=="function"&&(n=r.getAttribute("lang")),n}},Uue={name:"path",lookup(t){let{lookupFromPathIndex:e}=t;if(typeof window>"u")return;const n=window.location.pathname.match(/\/([a-zA-Z-]*)/g);return Array.isArray(n)?n[typeof e=="number"?e:0]?.replace("/",""):void 0}},Bue={name:"subdomain",lookup(t){let{lookupFromSubdomainIndex:e}=t;const n=typeof e=="number"?e+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]}};let $Y=!1;try{document.cookie,$Y=!0}catch{}const VY=["querystring","cookie","localStorage","sessionStorage","navigator","htmlTag"];$Y||VY.splice(1,1);const Hue=()=>({order:VY,lookupQuerystring:"lng",lookupCookie:"i18next",lookupLocalStorage:"i18nextLng",lookupSessionStorage:"i18nextLng",caches:["localStorage"],excludeCacheFor:["cimode"],convertDetectedLanguage:t=>t});class GY{constructor(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{};this.type="languageDetector",this.detectors={},this.init(e,n)}init(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{languageUtils:{}},n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:{},r=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};this.services=e,this.options=jue(n,this.options||{},Hue()),typeof this.options.convertDetectedLanguage=="string"&&this.options.convertDetectedLanguage.indexOf("15897")>-1&&(this.options.convertDetectedLanguage=i=>i.replace("-","_")),this.options.lookupFromUrlIndex&&(this.options.lookupFromPathIndex=this.options.lookupFromUrlIndex),this.i18nOptions=r,this.addDetector(Due),this.addDetector(Fue),this.addDetector(Lue),this.addDetector(Oue),this.addDetector(Iue),this.addDetector(zue),this.addDetector(Uue),this.addDetector(Bue),this.addDetector(Rue)}addDetector(e){return this.detectors[e.name]=e,this}detect(){let e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:this.options.order,n=[];return e.forEach(r=>{if(this.detectors[r]){let i=this.detectors[r].lookup(this.options);i&&typeof i=="string"&&(i=[i]),i&&(n=n.concat(i))}}),n=n.filter(r=>r!=null&&!Mue(r)).map(r=>this.options.convertDetectedLanguage(r)),this.services&&this.services.languageUtils&&this.services.languageUtils.getBestMatchFromCodes?n:n.length>0?n[0]:null}cacheUserLanguage(e){let n=arguments.length>1&&arguments[1]!==void 0?arguments[1]:this.options.caches;n&&(this.options.excludeCacheFor&&this.options.excludeCacheFor.indexOf(e)>-1||n.forEach(r=>{this.detectors[r]&&this.detectors[r].cacheUserLanguage(e,this.options)}))}}GY.type="languageDetector";const que={nav:{printers:"Printers",archives:"Archives",queue:"Queue",stats:"Statistics",profiles:"Profiles",maintenance:"Maintenance",projects:"Projects",inventory:"Filament",files:"File Manager",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",smartSwitches:"Smart Switches",logout:"Logout"},common:{save:"Save",saving:"Saving...",cancel:"Cancel",delete:"Delete",edit:"Edit",add:"Add",close:"Close",confirm:"Confirm",loading:"Loading...",error:"Error",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",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",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"},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",ascending:"Sort ascending",descending:"Sort descending"},cardSize:{small:"Small cards",medium:"Medium cards",large:"Large cards",extraLarge:"Extra large cards"},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"},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",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}}",printerAdded:"Printer added",printerUpdated:"Printer updated",failedToDelete:"Failed to delete printer",failedToAdd:"Failed to add printer",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"},connection:{connected:"Connected",offline:"Offline"},queue:{inQueue:"{{count}} print in queue",inQueue_plural:"{{count}} prints in queue"},controls:"Controls",rfid:{reread:"Re-read RFID"},bedJog:{title:"Move build plate",bed:"Bed",step:"Step (mm)",up:"Move plate up",down:"Move plate down",disabledWhilePrinting:"Disabled while printing",notHomedTitle:"Printer is not homed",notHomedMessage:"The Z axis has not been homed since the last print. Home Z first for safe positioning, or move anyway — soft endstops will be bypassed.",homeZ:"Home Z",moveAnyway:"Move anyway",homingStarted:"Homing Z axis…"},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.'},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"},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"},drying:{start:"Start Drying",stop:"Stop Drying",temperature:"Temperature",duration:"Duration",hours:"hours",timeRemaining:"{{time}} left",active:"Drying",notSupported:"Drying not supported",powerRequired:"Connect AMS power adapter to enable drying",startingDrying:"Starting drying...",stoppingDrying:"Stopping drying...",rotateTray:"Rotate spool during drying"},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",chamber:"Chamber Fan"},clickToViewHmsErrors:"Click to view HMS errors",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",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",reprint:"Reprint",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",schedule:"Schedule",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",goToProject:"Go to Project: {{name}}",addToProject:"Add to Project",removeFromProject:"Remove from Project",loading:"Loading...",noProjectsAvailable:"No projects available",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",noCreate:"You do not have permission to create archives"},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}}",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",noPermissionEdit:"You do not have permission to edit archives",noPermissionDelete:"You do not have permission to delete archives",reprint:"Reprint",schedulePrint:"Schedule Print",schedule:"Schedule",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"},modal:{deleteArchive:"Delete Archive",deleteConfirm:'Are you sure you want to delete "{{name}}"? This action cannot be undone.',deleteButton:"Delete",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"}},queue:{title:"Print Queue",subtitle:"Schedule and manage your print jobs",addToQueue:"Add to Queue",print:"Print",reprint:"Re-print",schedulePrint:"Schedule Print",editQueueItem:"Edit Queue Item",printToPrinters:"Print to {{count}} Printers",queueToPrinters:"Queue to {{count}} Printers",queueSelectedPlates:"Queue {{count}} Plates",selectAllPlates:"Select All {{count}} Plates",deselectAll:"Deselect All",printQueued:"Print queued",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",clearPlate:"Clear Plate & Start Next",clearPlateSuccess:"Plate cleared — ready for next print",plateReady:"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:"Batch",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:{asap:"ASAP",overdue:"Overdue",now:"Now",lessThanMinute:"In less than a minute",inMinutes:"In {{count}} min",inHours:"In {{count}} hours"},actions:{stopPrint:"Stop Print",startPrint:"Start 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",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"},timeline:{listView:"List",timelineView:"Timeline",unassigned:"Unassigned",noData:"No scheduled prints for this day",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"}},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"}},backgroundDispatch:{unknownFile:"Unknown file",unknownPrinter:"Unknown printer",startingPrints:"Starting prints",progressSummary:"{{complete}}/{{total}} complete • Dispatched: {{dispatched}} • Processing: {{processing}}",expandDetails:"Expand dispatch details",collapseDetails:"Collapse dispatch details",dismissToast:"Dismiss dispatch toast",cancelDispatchJob:"Cancel dispatch job",cancel:"Cancel",cancelling:"Cancelling…",status:{dispatched:"Dispatched",processing:"Processing",completed:"Completed",failed:"Failed",cancelled:"Cancelled"},toast:{cancellingUpload:"Cancelling upload...",cancelled:"Dispatch cancelled",cancelFailed:"Failed to cancel dispatch",completeWithFailures:"Background dispatch complete: {{completed}} succeeded, {{failed}} failed",completeSuccess:"Background dispatch complete: {{completed}} succeeded",printStartedRemaining:"{{completed}} print(s) started, {{remaining}} more sending..."}},stats:{title:"Dashboard",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:",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",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",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"},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",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.",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.",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",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",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",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",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",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",staggeredStart:"Staggered Start",staggeredStartDescription:"Default group size and interval when staggering multi-printer batch starts. Can be overridden per batch in the print modal.",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. Disable for farm workflows where plates are verified physically.",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.",dryingPresets:"Drying Presets",dryingPresetsDescription:"Temperature and duration per filament type. AMS 2 Pro uses lower temps, AMS-HT supports higher temps.",dryingFilament:"Filament",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 (min 6 characters)",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:"Choose which slicer application to open files with",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 6 characters",enterGroupName:"Please enter a group name",settingsSaved:"Settings saved",cameraSettingsSaved:"Camera settings saved",enterCameraUrl:"Please enter a camera URL",passwordChanged:"Password changed successfully",connectionFailed:"Connection failed",testFailed:"Test failed",cameraConnected:"Camera connected{{resolution}}"},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"},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:"Drag items in the sidebar to reorder. Reset to default order here.",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 and light mode using the sun/moon icon in the sidebar.",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",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)",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:",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."},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.",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"}}},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",clearInstructions:"Clear errors on the printer to dismiss them here.",clearErrors:"Clear Errors",clearSuccess:"HMS errors cleared",clearFailed:"Failed to clear HMS errors"},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...",forgotPassword:"Forgot your password?",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"},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"}},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"},modal:{createUser:"Create User",editUser:"Edit User",cancel:"Cancel",creating:"Creating...",saving:"Saving...",saveChanges:"Save Changes",advancedAuthSubtitle:"with Advanced Authentication"},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:{cloud:"Cloud Profiles",local:"Local Profiles",kprofiles:"K-Profiles"},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",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",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 Lab access token (from Bambu Studio)",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"},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",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",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",addToQueue:"Add to Queue",schedulePrint:"Schedule",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",wrap:"Wrap",enableTextWrapping:"Enable text wrapping",disableTextWrapping:"Disable text wrapping",collapse:"Collapse",collapseFoldersByDefault:"Collapse folders by default",expandFoldersByDefault:"Expand folders by default",dragToResizeTooltip:"Drag to resize, double-click to reset",searchFiles:"Search files...",allTypes:"All types",prints:"Prints",ascending:"Ascending",descending:"Descending",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",noPermissionPrint:"You do not have permission to print",noPermissionAddToQueue:"You do not have permission to add to queue",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...",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",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",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.",noFiles:"No files in this folder.",print:"Print Now",addToQueue:"Add to Queue"},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"},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"},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:"Unlink Spool?",unlinkConfirmMessage:"This will disconnect the spool from Spoolman. The spool data in Spoolman will remain unchanged.",selectSpool:"Select Spool",noUnlinkedSpools:"No unlinked spools available",linkSuccess:"Spool linked to Spoolman successfully",linkFailed:"Failed to link spool",unlinkSuccess:"Spool unlinked from Spoolman successfully",unlinkFailed:"Failed to unlink 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."},inventory:{title:"Spool Inventory",addSpool:"Add Spool",editSpool:"Edit Spool",material:"Material",selectMaterial:"Select material...",subtype:"Subtype",brand:"Brand",searchBrand:"Search brand...",useCustomBrand:'Use "{{brand}}"',useCustomMaterial:"Use custom material: {{material}}",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",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...",archive:"Archive",restore:"Restore",noSpools:"No spools yet. Add your first spool to get started.",noManualSpools:"No manually added spools available. Add a spool to your inventory first.",kProfiles:"K-Profiles",addKProfile:"Add K-Profile",assignSpool:"Assign Spool",unassignSpool:"Unassign",assignSuccess:"Spool assigned and AMS slot configured",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",allMaterials:"All Materials",filterByBrand:"Filter by brand...",showArchived:"Show archived",quickAdd:"Quick Add (Stock)",quantity:"Quantity",stock:"Stock",configured:"Configured",spoolsCreated:"{{count}} spools created",spoolCreated:"Spool created",spoolUpdated:"Spool updated",spoolDeleted:"Spool deleted",spoolArchived:"Spool archived",spoolRestored:"Spool restored",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",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",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?'},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",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:{title:"Start Print",selectPrinter:"Select Printer",selectPlate:"Select Plate",filamentMapping:"Filament Mapping",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",startPrint:"Start Print",addToQueue:"Add to Queue",cancel:"Cancel",noPrintersAvailable:"No printers available",printerBusy:"Printer is busy",printerOffline:"Printer is offline",sameTypeDifferentColor:"Same type, different color",filamentTypeNotLoaded:"Filament type not loaded",openCalendar:"Open calendar",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",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:{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:"GitHub 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.",repositoryUrl:"Repository URL",personalAccessToken:"Personal Access Token",tokenSaved:"(saved)",enterNewToken:"Enter new token to update",tokenHint:"Fine-grained token with Contents read/write permission",branch:"Branch",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",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",utc:"UTC",defaultPathLabel:"Default:",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...",noFilamentsHelp:"No filaments found. Create a K-profile in Bambu Studio first.",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",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)"},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."},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"},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",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",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",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",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"},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"},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",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",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",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)",cancel:"Cancel",save:"Save",add:"Add",nameRequired:"Name is required",fieldRequired:"{{field}} is required",phoneNumber:"Phone Number",apiKey:"API Key",serverUrl:"Server URL",topic:"Topic",authToken:"Auth Token",userKey:"User Key",appToken:"App Token",priority:"Priority",botToken:"Bot Token",chatId:"Chat ID",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:{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",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.",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:"GitHub 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"},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!",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...",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"},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"}},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...",submitSuccess:"Bug report submitted successfully!",submitFailed:"Failed to submit bug report",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).",test:"Test",testSuccess:"ML API reachable and healthy.",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."}},$ue={nav:{printers:"Drucker",archives:"Archiv",queue:"Warteschlange",stats:"Statistiken",profiles:"Profile",maintenance:"Wartung",projects:"Projekte",inventory:"Filament",files:"Dateimanager",notifications:"Benachrichtigungen",settings:"Einstellungen",system:"System",collapseSidebar:"Seitenleiste einklappen",expandSidebar:"Seitenleiste ausklappen",update:"Update",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",smartSwitches:"Smart Switches",logout:"Abmelden"},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",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",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:{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"},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",ascending:"Aufsteigend sortieren",descending:"Absteigend sortieren"},cardSize:{small:"Kleine Karten",medium:"Mittlere Karten",large:"Große Karten",extraLarge:"Extra große Karten"},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"},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",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:"High Flow",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}}",printerAdded:"Drucker hinzugefügt",printerUpdated:"Drucker aktualisiert",failedToDelete:"Drucker konnte nicht gelöscht werden",failedToAdd:"Drucker konnte nicht hinzugefügt werden",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"},connection:{connected:"Verbunden",offline:"Offline"},queue:{inQueue:"{{count}} Druck in Warteschlange",inQueue_plural:"{{count}} Drucke in Warteschlange"},controls:"Steuerung",rfid:{reread:"RFID neu lesen"},bedJog:{title:"Druckbett bewegen",bed:"Bett",step:"Schritt (mm)",up:"Platte hoch",down:"Platte runter",disabledWhilePrinting:"Während des Drucks deaktiviert",notHomedTitle:"Drucker ist nicht referenziert",notHomedMessage:"Die Z-Achse wurde seit dem letzten Druck nicht referenziert. Referenzieren Sie Z zuerst für eine sichere Positionierung oder bewegen Sie trotzdem — die Software-Endschalter werden dabei umgangen.",homeZ:"Z referenzieren",moveAnyway:"Trotzdem bewegen",homingStarted:"Z-Achse wird 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.'},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"},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"},drying:{start:"Trocknung starten",stop:"Trocknung stoppen",temperature:"Temperatur",duration:"Dauer",hours:"Stunden",timeRemaining:"{{time}} verbleibend",active:"Trocknung",notSupported:"Trocknung nicht unterstützt",powerRequired:"AMS-Netzteil anschließen, um Trocknung zu aktivieren",startingDrying:"Trocknung wird gestartet...",stoppingDrying:"Trocknung wird gestoppt...",rotateTray:"Spule während der Trocknung drehen"},filaments:"Filamente",openCameraOverlay:"Kamera-Overlay öffnen",openCameraWindow:"Kamera in neuem Fenster öffnen",firmwareUpdateAvailable:"Firmware-Update verfügbar: {{current}} → {{latest}}",firmwareUpToDate:"Firmware {{version}} — Aktuell",firmwareUpdateButton:"Update",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",chamber:"Kammerventilator"},clickToViewHmsErrors:"Klicken, um HMS-Fehler anzuzeigen",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",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",reprint:"Drucken",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",schedule:"Planen",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",goToProject:"Zum Projekt: {{name}}",addToProject:"Zu Projekt hinzufügen",removeFromProject:"Aus Projekt entfernen",loading:"Laden...",noProjectsAvailable:"Keine Projekte verfügbar",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",noCreate:"Sie haben keine Berechtigung, Archive zu erstellen"},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}}",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",noPermissionEdit:"Sie haben keine Berechtigung, Archive zu bearbeiten",noPermissionDelete:"Sie haben keine Berechtigung, Archive zu löschen",reprint:"Drucken",schedulePrint:"Druck planen",schedule:"Planen",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"},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",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"}},queue:{title:"Druckwarteschlange",subtitle:"Planen und verwalten Sie Ihre Druckaufträge",addToQueue:"Zur Warteschlange hinzufügen",print:"Drucken",reprint:"Erneut drucken",schedulePrint:"Druck planen",editQueueItem:"Warteschlangeneintrag bearbeiten",printToPrinters:"Auf {{count}} Druckern drucken",queueToPrinters:"Zu {{count}} Druckern hinzufügen",queueSelectedPlates:"{{count}} Platten in die Warteschlange",selectAllPlates:"Alle {{count}} Platten auswählen",deselectAll:"Alle abwählen",printQueued:"Druck in Warteschlange",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",clearPlate:"Druckplatte freigeben & Nächsten starten",clearPlateSuccess:"Druckplatte freigegeben — bereit für nächsten Druck",plateReady:"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:"Stapel",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:{asap:"Sofort",overdue:"Überfällig",now:"Jetzt",lessThanMinute:"In weniger als einer Minute",inMinutes:"In {{count}} Min",inHours:"In {{count}} Stunden"},actions:{stopPrint:"Druck stoppen",startPrint:"Druck starten",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",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"},timeline:{listView:"Liste",timelineView:"Zeitstrahl",unassigned:"Nicht zugewiesen",noData:"Keine geplanten Drucke für diesen Tag",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"}},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"}},backgroundDispatch:{unknownFile:"Unbekannte Datei",unknownPrinter:"Unbekannter Drucker",startingPrints:"Starte Drucke",progressSummary:"{{complete}}/{{total}} abgeschlossen • Geplant: {{dispatched}} • In Bearbeitung: {{processing}}",expandDetails:"Dispatch-Details ausklappen",collapseDetails:"Dispatch-Details einklappen",dismissToast:"Dispatch-Hinweis schließen",cancelDispatchJob:"Dispatch-Job abbrechen",cancel:"Abbrechen",cancelling:"Wird abgebrochen…",status:{dispatched:"Geplant",processing:"In Bearbeitung",completed:"Abgeschlossen",failed:"Fehlgeschlagen",cancelled:"Abgebrochen"},toast:{cancellingUpload:"Upload wird abgebrochen...",cancelled:"Dispatch abgebrochen",cancelFailed:"Dispatch konnte nicht abgebrochen werden",completeWithFailures:"Background Dispatch abgeschlossen: {{completed}} erfolgreich, {{failed}} fehlgeschlagen",completeSuccess:"Background Dispatch abgeschlossen: {{completed}} erfolgreich",printStartedRemaining:"{{completed}} Druck(e) gestartet, {{remaining}} weitere werden gesendet..."}},stats:{title:"Dashboard",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:",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",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",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"},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.",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.",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:"Updates",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.",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",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",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",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",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",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",staggeredStart:"Staggered Start",staggeredStartDescription:"Default group size and interval when staggering multi-printer batch starts. Can be overridden per batch in the print modal.",plateClear:"Druckplatte-Bestätigung",requirePlateClear:"Druckplatte-Bestätigung erforderlich",requirePlateClearDescription:"Wenn aktiviert, wartet der Scheduler auf eine Druckplatte-Bestätigung pro Drucker, bevor geplante Drucke auf Druckern mit abgeschlossenen Aufträgen gestartet werden. Deaktivieren Sie dies für Farm-Workflows, bei denen die Platten physisch überprüft werden.",gcodeInjection:"G-code Injection",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:"Group size",staggerGroupSizeHelp:"Printers to start simultaneously per group",staggerInterval:"Interval (minutes)",staggerIntervalHelp:"Delay between each group starting",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.",dryingPresets:"Trocknungsvoreinstellungen",dryingPresetsDescription:"Temperatur und Dauer pro Filamenttyp. AMS 2 Pro verwendet niedrigere Temperaturen, AMS-HT unterstützt höhere.",dryingFilament:"Filament",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 (min. 6 Zeichen)",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:"Wähle die Slicer-Anwendung zum Öffnen von Dateien",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 6 Zeichen lang sein",enterGroupName:"Bitte geben Sie einen Gruppennamen ein",settingsSaved:"Einstellungen gespeichert",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}}"},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"},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:"Sync",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:"Elemente in der Seitenleiste per Drag & Drop neu anordnen. Hier auf Standardreihenfolge zurücksetzen.",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 Hell- und Dunkelmodus mit dem Sonnen-/Mondsymbol in der Seitenleiste wechseln.",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",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)",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:",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."},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.",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:"Scopes",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"}}},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",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"},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:"Topic",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...",forgotPassword:"Passwort vergessen?",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"},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"}},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"},modal:{createUser:"Benutzer erstellen",editUser:"Benutzer bearbeiten",cancel:"Abbrechen",creating:"Erstellen...",saving:"Speichern...",saveChanges:"Änderungen speichern",advancedAuthSubtitle:"mit erweiterter Authentifizierung"},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:{cloud:"Cloud-Profile",local:"Lokale Profile",kprofiles:"K-Profile"},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",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",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 Lab Zugriffstoken ein (aus Bambu Studio)",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"},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",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",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",addToQueue:"Zur Warteschlange",schedulePrint:"Planen",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",wrap:"Umbrechen",enableTextWrapping:"Textumbruch aktivieren",disableTextWrapping:"Textumbruch deaktivieren",collapse:"Einklappen",collapseFoldersByDefault:"Ordner standardmäßig einklappen",expandFoldersByDefault:"Ordner standardmäßig ausklappen",dragToResizeTooltip:"Ziehen zum Ändern der Größe, Doppelklick zum Zurücksetzen",searchFiles:"Dateien suchen...",allTypes:"Alle Typen",prints:"Drucke",ascending:"Aufsteigend",descending:"Absteigend",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",noPermissionPrint:"Sie haben keine Berechtigung zum Drucken",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...",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",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",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.",noFiles:"Keine Dateien in diesem Ordner.",print:"Jetzt drucken",addToQueue:"Zur Warteschlange"},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"},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"},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 entkoppeln?",unlinkConfirmMessage:"Dadurch wird die Spule von Spoolman getrennt. Die Spulendaten in Spoolman bleiben unverändert.",selectSpool:"Spule auswählen",noUnlinkedSpools:"Keine nicht verknüpften Spulen verfügbar",linkSuccess:"Spule erfolgreich mit Spoolman verknüpft",linkFailed:"Verknüpfung mit Spoolman fehlgeschlagen",unlinkSuccess:"Spule erfolgreich von Spoolman getrennt",unlinkFailed:"Trennen der Spule von Spoolman fehlgeschlagen",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."},inventory:{title:"Spulen-Inventar",addSpool:"Spule hinzufügen",editSpool:"Spule bearbeiten",material:"Material",selectMaterial:"Material auswählen...",subtype:"Untertyp",brand:"Marke",searchBrand:"Marke suchen...",useCustomBrand:'"{{brand}}" verwenden',useCustomMaterial:"Benutzerdefiniertes Material verwenden: {{material}}",colorName:"Farbname",colorNamePlaceholder:"Jade White, Fire Red...",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",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...",archive:"Archivieren",restore:"Wiederherstellen",noSpools:"Noch keine Spulen. Fügen Sie Ihre erste Spule hinzu.",noManualSpools:"Keine manuell hinzugefügten Spulen verfügbar. Fügen Sie zuerst eine Spule zum Inventar hinzu.",kProfiles:"K-Profile",addKProfile:"K-Profil hinzufügen",assignSpool:"Spule zuweisen",unassignSpool:"Zuweisung aufheben",assignSuccess:"Spule zugewiesen und AMS-Slot 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",allMaterials:"Alle Materialien",filterByBrand:"Nach Marke filtern...",showArchived:"Archivierte anzeigen",quickAdd:"Schnellerfassung (Lager)",quantity:"Menge",stock:"Lager",configured:"Konfiguriert",spoolsCreated:"{{count}} Spulen erstellt",spoolCreated:"Spule erstellt",spoolUpdated:"Spule aktualisiert",spoolDeleted:"Spule gelöscht",spoolArchived:"Spule archiviert",spoolRestored:"Spule wiederhergestellt",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",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",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?'},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",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:{title:"Druck starten",selectPrinter:"Drucker auswählen",selectPlate:"Platte auswählen",filamentMapping:"Filamentzuordnung",totalCost:"Gesamtkosten:",slotRemainingShort:" - {{grams}}g übrig",printSettings:"Druckeinstellungen",bedLeveling:"Bett-Nivellierung",flowCalibration:"Fluss-Kalibrierung",vibrationCalibration:"Vibrations-Kalibrierung",layerInspection:"Erste-Schicht-Prüfung",timelapse:"Zeitraffer",startPrint:"Druck starten",addToQueue:"Zur Warteschlange hinzufügen",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",openCalendar:"Kalender öffnen",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",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:"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:"Gestaffelt an {{count}} Drucker senden",gcodeInjection:"Auto-Print G-code einfügen"},backup:{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:"GitHub 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.",repositoryUrl:"Repository-URL",personalAccessToken:"Persönlicher Zugriffstoken",tokenSaved:"(gespeichert)",enterNewToken:"Neuen Token eingeben zum Aktualisieren",tokenHint:"Feingranularer Token mit Lese-/Schreibberechtigung für Inhalte",branch:"Branch",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 der Bambu Cloud",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:"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",utc:"UTC",defaultPathLabel:"Default:",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...",noFilamentsHelp:"Keine Filamente gefunden. Erstellen Sie zuerst ein K-Profil in Bambu Studio.",flowType:"Flusstyp",highFlow:"High Flow",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",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)"},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."},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"},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",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",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",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:"Topic",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.
@@ -32,7 +32,7 @@ ON值:表示"ON"的确切字符串。留空以自动检测(ON、true、1)
乘數:Wh→kWh使用0.001,MWh→kWh使用1000。`,mqttStateHint:`JSON路徑從JSON負載中提取值。原始值請留空。
ON值:表示"ON"的確切字串。留空以自動檢測(ON、true、1)。`,restControl:"控制",restOnUrl:"開啟 URL",restOffUrl:"關閉 URL",restOnBody:"開啟請求內容",restOffBody:"關閉請求內容",restMethod:"HTTP 方法",restHeaders:"自訂標頭(JSON)",restStatusUrl:"狀態 URL",restStatusPath:"狀態 JSON 路徑",restStatusOnValue:"ON 值",restPowerUrl:"功率URL",restPowerPath:"功率 JSON 路徑",restPowerMultiplier:"功率乘數",restEnergyUrl:"能耗URL",restEnergyPath:"能耗 JSON 路徑",restEnergyMultiplier:"能耗乘數",restUrlRequired:"REST 插座至少需要一個 URL(ON 或 OFF)",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"},providerDescriptions:{email:"SMTP 電子郵件通知",telegram:"透過 Telegram 機器人傳送通知",discord:"透過 Webhook 傳送到 Discord 頻道",ntfy:"免費、可自託管的推送通知",pushover:"簡單、可靠的推送通知",callmebot:"透過 CallMeBot 免費傳送 WhatsApp 通知",webhook:"通用 HTTP POST 到任意 URL",homeassistant:"Home Assistant 儀表板中的持久通知"},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:"列印前偵測到物體",printCompleted:"列印已完成",bedCooledLabel:"熱床已冷卻",bedCooledDescription:"列印後熱床溫度降至閾值以下",firstLayerCompleteLabel:"首層列印完成",firstLayerCompleteDescription:"首層完成時傳送帶照片的通知",missingSpoolAssignmentLabel:"缺少料卷分配",missingSpoolAssignmentDescription:"當列印開始且所需料盤沒有分配料卷時傳送通知",printFailed:"列印失敗",printStopped:"列印已停止",progressMilestones:"進度里程碑",progressMilestonesDescription:"在 25%、50%、75% 時通知",printerOffline:"印表機離線",printerError:"印表機錯誤",lowFilamentLabel:"耗材不足",maintenanceDue:"需要維護",maintenanceDueDescription:"需要維護時通知",amsHumidityHigh:"AMS 濕度過高",amsHumidityHighDescription:"普通 AMS 濕度超過閾值",amsTemperatureHigh:"AMS 溫度過高",amsTemperatureHighDescription:"普通 AMS 溫度超過閾值",amsHtHumidityHigh:"AMS-HT 濕度過高",amsHtHumidityHighDescription:"AMS-HT 濕度超過閾值",amsHtTemperatureHigh:"AMS-HT 溫度過高",amsHtTemperatureHighDescription:"AMS-HT 溫度超過閾值",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:"(列印完成後)",cancel:"取消",save:"儲存",add:"新增",nameRequired:"名稱為必填項",fieldRequired:"{{field}}為必填項",phoneNumber:"電話號碼",apiKey:"API 金鑰",serverUrl:"伺服器 URL",topic:"主題",authToken:"認證權杖",userKey:"使用者金鑰",appToken:"應用程式權杖",priority:"優先順序",botToken:"機器人權杖",chatId:"聊天 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:{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:"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:"無雲端預設。登入拓竹雲以同步。",noPresetsAvailable:"無可用預設。登入拓竹雲或匯入本機設定。",noMatchingPresets:"未找到匹配的預設。",custom:"自訂",builtin:"內建",settingsSentToPrinter:"設定已傳送到印表機",filamentProfile:"耗材設定",kProfileLabel:"K 值設定(壓力推進)",filteringFor:"篩選:{{material}}",noKProfile:"無 K 值設定(使用預設值 0.020)",noMatchingKProfiles:"未找到匹配的 K 值設定。將使用預設 K=0.020。",selectFilamentFirst:"請先選擇耗材設定",kFromCalibration:"K={{value}}(來自印表機校準)",customColorLabel:"自訂顏色(可選)",presetColors:"{{name}} 顏色:",showLessColors:"顯示更少顏色",showMoreColors:"顯示更多顏色",clear:"清除",hexLabel:"十六進位:#{{hex}}",resetting:"重設中...",resetSlot:"重設槽位",cancel:"取消",configuring:"設定中...",configureSlot:"設定槽位"},githubBackup:{title:"GitHub 備份",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:"透過 Webhook 傳送到 Discord 頻道",ntfy:"免費、可自託管的推送通知",pushover:"簡單、可靠的推送通知",callmebot:"透過 CallMeBot 的免費 WhatsApp 通知",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:"目前耗材"},modal:{spoolDetected:"偵測到耗材",assignToAms:"分配到 AMS",syncWeight:"同步重量",weightSynced:"已同步!",syncing:"同步中...",newTagDetected:"偵測到新標籤",addToInventory:"新增到庫存",assignToAmsTitle:"分配到 AMS",selectSlot:"選擇槽位",assign:"分配",assigning:"分配中...",assignSuccess:"已分配!",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:"去皮命令已傳送。等待裝置回應...",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:"重量 (g)",createSpool:"建立耗材",creating:"建立中...",spoolCreated:"耗材已建立!準備寫入。",createFailed:"建立耗材失敗"},quickMenu:{printerPower:"印表機電源",systemControls:"系統",restartDaemon:"重新啟動守護程式",restartBrowser:"重新啟動瀏覽器",reboot:"重新開機",shutdown:"關機",swipeToClose:"向下滑動關閉",confirmTitle:"確認",confirmShutdown:"確定要關閉 SpoolBuddy 嗎?您需要實體存取才能重新開啟。",confirmReboot:"確定要重新開機 SpoolBuddy 嗎?",confirmRestartDaemon:"重新啟動 SpoolBuddy 守護程式?NFC 和磅秤將暫時不可用。",confirmRestartBrowser:"重新啟動kiosk瀏覽器?螢幕將短暫變黑。",confirm:"確認",confirmPlugOn:"開啟 {{name}}?",confirmPlugOff:"關閉 {{name}}?",turnOn:"開啟",turnOff:"關閉"}},bugReport:{title:"報告錯誤",description:"描述",descriptionPlaceholder:"出了什麼問題?請描述問題...",email:"信箱(可選)",emailPlaceholder:"your@email.com",emailPrivacy:"如果提供,您的信箱將包含在GitHub Issue的摺疊部分中,以便維護者後續跟進。",screenshot:"截圖",uploadOrPaste:"上傳、貼上或拖曳圖片",dataCollectedSummary:"報告中包含哪些資料?",dataIncluded:"包含:",dataIncludedList:"應用程式版本、作業系統、架構、Python版本、資料庫統計(僅計數)、印表機型號、噴嘴數量、韌體版本、連線狀態、整合狀態(Spoolman、MQTT、HA)、非敏感設定、網路介面數量、Docker詳情、依賴版本。",dataNeverIncluded:"絕不包含:",dataNeverIncludedList:"印表機名稱、序列號、存取碼、密碼、IP 位址、信箱地址、API金鑰、權杖、Webhook URL、主機名稱或使用者名稱。",submit:"提交",startLogging:"開始偵錯日誌",stepEnableLogging:"偵錯日誌已啟用",stepReproduce:"請現在重現問題",stepStopLogging:"停止並提交報告",stopAndSubmit:"停止並提交",maxDuration:"{{minutes}} 分鐘後自動停止",stoppingLogs:"正在收集日誌並提交...",submitting:"正在提交錯誤報告...",submitSuccess:"錯誤報告提交成功!",submitFailed:"提交錯誤報告失敗",thankYou:"謝謝!",submitted:"您的錯誤報告已提交。",viewIssue:"檢視 Issue",unexpectedError:"發生了意外錯誤"},failureDetection:{title:"AI 故障檢測",description:"透過自託管的 Obico ML API 監控列印,並對偵測到的故障自動採取行動。",mlUrl:"Obico ML API 地址",mlUrlHint:"您自託管的 Obico ml_api 容器的基礎 URL(例如 http://192.168.1.10:3333)。",test:"測試",testSuccess:"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:"尚無檢測紀錄。"}},Que={en:{translation:que},de:{translation:$ue},fr:{translation:Vue},ja:{translation:Gue},it:{translation:Wue},"pt-BR":{translation:Kue},"zh-CN":{translation:Xue},"zh-TW":{translation:Yue}};uo.use(GY).use(wue).init({resources:Que,fallbackLng:"en",supportedLngs:["en","de","fr","ja","it","pt-BR","zh-CN","zh-TW"],detection:{order:["localStorage","navigator","htmlTag"],lookupLocalStorage:"bambutrack_language",caches:["localStorage"]},interpolation:{escapeValue:!1},react:{useSuspense:!1}});const nH=[{code:"en",name:"English",nativeName:"English"},{code:"de",name:"German",nativeName:"Deutsch"},{code:"fr",name:"French",nativeName:"Français"},{code:"ja",name:"Japanese",nativeName:"日本語"},{code:"it",name:"Italian",nativeName:"Italiano"},{code:"pt-BR",name:"Portuguese (Brazil)",nativeName:"Português (Brasil)"},{code:"zh-CN",name:"Chinese (Simplified)",nativeName:"简体中文"},{code:"zh-TW",name:"Chinese (Traditional)",nativeName:"繁體中文"}];var rH="popstate";function Zue(t={}){function e(r,i){let{pathname:s,search:o,hash:l}=r.location;return z3("",{pathname:s,search:o,hash:l},i.state&&i.state.usr||null,i.state&&i.state.key||"default")}function n(r,i){return typeof i=="string"?i:W0(i)}return eme(e,n,null,t)}function Pa(t,e){if(t===!1||t===null||typeof t>"u")throw new Error(e)}function rc(t,e){if(!t){typeof console<"u"&&console.warn(e);try{throw new Error(e)}catch{}}}function Jue(){return Math.random().toString(36).substring(2,10)}function aH(t,e){return{usr:t.state,key:t.key,idx:e}}function z3(t,e,n=null,r){return{pathname:typeof t=="string"?t:t.pathname,search:"",hash:"",...typeof e=="string"?ly(e):e,state:n,key:e&&e.key||r||Jue()}}function W0({pathname:t="/",search:e="",hash:n=""}){return e&&e!=="?"&&(t+=e.charAt(0)==="?"?e:"?"+e),n&&n!=="#"&&(t+=n.charAt(0)==="#"?n:"#"+n),t}function ly(t){let e={};if(t){let n=t.indexOf("#");n>=0&&(e.hash=t.substring(n),t=t.substring(0,n));let r=t.indexOf("?");r>=0&&(e.search=t.substring(r),t=t.substring(0,r)),t&&(e.pathname=t)}return e}function eme(t,e,n,r={}){let{window:i=document.defaultView,v5Compat:s=!1}=r,o=i.history,l="POP",c=null,d=u();d==null&&(d=0,o.replaceState({...o.state,idx:d},""));function u(){return(o.state||{idx:null}).idx}function m(){l="POP";let b=u(),g=b==null?null:b-d;d=b,c&&c({action:l,location:v.location,delta:g})}function p(b,g){l="PUSH";let _=z3(v.location,b,g);d=u()+1;let C=aH(_,d),P=v.createHref(_);try{o.pushState(C,"",P)}catch(N){if(N instanceof DOMException&&N.name==="DataCloneError")throw N;i.location.assign(P)}s&&c&&c({action:l,location:v.location,delta:1})}function f(b,g){l="REPLACE";let _=z3(v.location,b,g);d=u();let C=aH(_,d),P=v.createHref(_);o.replaceState(C,"",P),s&&c&&c({action:l,location:v.location,delta:0})}function x(b){return tme(b)}let v={get action(){return l},get location(){return t(i,o)},listen(b){if(c)throw new Error("A history only accepts one active listener");return i.addEventListener(rH,m),c=b,()=>{i.removeEventListener(rH,m),c=null}},createHref(b){return e(i,b)},createURL:x,encodeLocation(b){let g=x(b);return{pathname:g.pathname,search:g.search,hash:g.hash}},push:p,replace:f,go(b){return o.go(b)}};return v}function tme(t,e=!1){let n="http://localhost";typeof window<"u"&&(n=window.location.origin!=="null"?window.location.origin:window.location.href),Pa(n,"No window.location.(origin|href) available to create URL");let r=typeof t=="string"?t:W0(t);return r=r.replace(/ $/,"%20"),!e&&r.startsWith("//")&&(r=n+r),new URL(r,n)}function WY(t,e,n="/"){return nme(t,e,n,!1)}function nme(t,e,n,r){let i=typeof e=="string"?ly(e):e,s=cm(i.pathname||"/",n);if(s==null)return null;let o=KY(t);rme(o);let l=null;for(let c=0;l==null&&c{let u={relativePath:d===void 0?o.path||"":d,caseSensitive:o.caseSensitive===!0,childrenIndex:l,route:o};if(u.relativePath.startsWith("/")){if(!u.relativePath.startsWith(r)&&c)return;Pa(u.relativePath.startsWith(r),`Absolute route path "${u.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),u.relativePath=u.relativePath.slice(r.length)}let m=Ju([r,u.relativePath]),p=n.concat(u);o.children&&o.children.length>0&&(Pa(o.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${m}".`),KY(o.children,e,p,m,c)),!(o.path==null&&!o.index)&&e.push({path:m,score:dme(m,o.index),routesMeta:p})};return t.forEach((o,l)=>{if(o.path===""||!o.path?.includes("?"))s(o,l);else for(let c of XY(o.path))s(o,l,!0,c)}),e}function XY(t){let e=t.split("/");if(e.length===0)return[];let[n,...r]=e,i=n.endsWith("?"),s=n.replace(/\?$/,"");if(r.length===0)return i?[s,""]:[s];let o=XY(r.join("/")),l=[];return l.push(...o.map(c=>c===""?s:[s,c].join("/"))),i&&l.push(...o),l.map(c=>t.startsWith("/")&&c===""?"/":c)}function rme(t){t.sort((e,n)=>e.score!==n.score?n.score-e.score:ume(e.routesMeta.map(r=>r.childrenIndex),n.routesMeta.map(r=>r.childrenIndex)))}var ame=/^:[\w-]+$/,ime=3,sme=2,ome=1,lme=10,cme=-2,iH=t=>t==="*";function dme(t,e){let n=t.split("/"),r=n.length;return n.some(iH)&&(r+=cme),e&&(r+=sme),n.filter(i=>!iH(i)).reduce((i,s)=>i+(ame.test(s)?ime:s===""?ome:lme),r)}function ume(t,e){return t.length===e.length&&t.slice(0,-1).every((r,i)=>r===e[i])?t[t.length-1]-e[e.length-1]:0}function mme(t,e,n=!1){let{routesMeta:r}=t,i={},s="/",o=[];for(let l=0;l{if(u==="*"){let x=l[p]||"";o=s.slice(0,s.length-x.length).replace(/(.)\/+$/,"$1")}const f=l[p];return m&&!f?d[u]=void 0:d[u]=(f||"").replace(/%2F/g,"/"),d},{}),pathname:s,pathnameBase:o,pattern:t}}function hme(t,e=!1,n=!0){rc(t==="*"||!t.endsWith("*")||t.endsWith("/*"),`Route path "${t}" will be treated as if it were "${t.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${t.replace(/\*$/,"/*")}".`);let r=[],i="^"+t.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(o,l,c)=>(r.push({paramName:l,isOptional:c!=null}),c?"/?([^\\/]+)?":"/([^\\/]+)")).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return t.endsWith("*")?(r.push({paramName:"*"}),i+=t==="*"||t==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):n?i+="\\/*$":t!==""&&t!=="/"&&(i+="(?:(?=\\/|$))"),[new RegExp(i,e?void 0:"i"),r]}function pme(t){try{return t.split("/").map(e=>decodeURIComponent(e).replace(/\//g,"%2F")).join("/")}catch(e){return rc(!1,`The URL path "${t}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${e}).`),t}}function cm(t,e){if(e==="/")return t;if(!t.toLowerCase().startsWith(e.toLowerCase()))return null;let n=e.endsWith("/")?e.length-1:e.length,r=t.charAt(n);return r&&r!=="/"?null:t.slice(n)||"/"}var fme=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i;function gme(t,e="/"){let{pathname:n,search:r="",hash:i=""}=typeof t=="string"?ly(t):t,s;return n?(n=n.replace(/\/\/+/g,"/"),n.startsWith("/")?s=sH(n.substring(1),"/"):s=sH(n,e)):s=e,{pathname:s,search:yme(r),hash:vme(i)}}function sH(t,e){let n=e.replace(/\/+$/,"").split("/");return t.split("/").forEach(i=>{i===".."?n.length>1&&n.pop():i!=="."&&n.push(i)}),n.length>1?n.join("/"):"/"}function yM(t,e,n,r){return`Cannot include a '${t}' character in a manually specified \`to.${e}\` 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 bme(t){return t.filter((e,n)=>n===0||e.route.path&&e.route.path.length>0)}function oO(t){let e=bme(t);return e.map((n,r)=>r===e.length-1?n.pathname:n.pathnameBase)}function lO(t,e,n,r=!1){let i;typeof t=="string"?i=ly(t):(i={...t},Pa(!i.pathname||!i.pathname.includes("?"),yM("?","pathname","search",i)),Pa(!i.pathname||!i.pathname.includes("#"),yM("#","pathname","hash",i)),Pa(!i.search||!i.search.includes("#"),yM("#","search","hash",i)));let s=t===""||i.pathname==="",o=s?"/":i.pathname,l;if(o==null)l=n;else{let m=e.length-1;if(!r&&o.startsWith("..")){let p=o.split("/");for(;p[0]==="..";)p.shift(),m-=1;i.pathname=p.join("/")}l=m>=0?e[m]:"/"}let c=gme(i,l),d=o&&o!=="/"&&o.endsWith("/"),u=(s||o===".")&&n.endsWith("/");return!c.pathname.endsWith("/")&&(d||u)&&(c.pathname+="/"),c}var Ju=t=>t.join("/").replace(/\/\/+/g,"/"),xme=t=>t.replace(/\/+$/,"").replace(/^\/*/,"/"),yme=t=>!t||t==="?"?"":t.startsWith("?")?t:"?"+t,vme=t=>!t||t==="#"?"":t.startsWith("#")?t:"#"+t,wme=class{constructor(t,e,n,r=!1){this.status=t,this.statusText=e||"",this.internal=r,n instanceof Error?(this.data=n.toString(),this.error=n):this.data=n}};function Sme(t){return t!=null&&typeof t.status=="number"&&typeof t.statusText=="string"&&typeof t.internal=="boolean"&&"data"in t}function _me(t){return t.map(e=>e.route.path).filter(Boolean).join("/").replace(/\/\/*/g,"/")||"/"}var YY=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u";function QY(t,e){let n=t;if(typeof n!="string"||!fme.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let r=n,i=!1;if(YY)try{let s=new URL(window.location.href),o=n.startsWith("//")?new URL(s.protocol+n):new URL(n),l=cm(o.pathname,e);o.origin===s.origin&&l!=null?n=l+o.search+o.hash:i=!0}catch{rc(!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 ZY=["POST","PUT","PATCH","DELETE"];new Set(ZY);var kme=["GET",...ZY];new Set(kme);var cy=w.createContext(null);cy.displayName="DataRouter";var DP=w.createContext(null);DP.displayName="DataRouterState";var Nme=w.createContext(!1),JY=w.createContext({isTransitioning:!1});JY.displayName="ViewTransition";var Cme=w.createContext(new Map);Cme.displayName="Fetchers";var Pme=w.createContext(null);Pme.displayName="Await";var gl=w.createContext(null);gl.displayName="Navigation";var Bw=w.createContext(null);Bw.displayName="Location";var hc=w.createContext({outlet:null,matches:[],isDataRoute:!1});hc.displayName="Route";var cO=w.createContext(null);cO.displayName="RouteError";var eQ="REACT_ROUTER_ERROR",Tme="REDIRECT",Ame="ROUTE_ERROR_RESPONSE";function jme(t){if(t.startsWith(`${eQ}:${Tme}:{`))try{let e=JSON.parse(t.slice(28));if(typeof e=="object"&&e&&typeof e.status=="number"&&typeof e.statusText=="string"&&typeof e.location=="string"&&typeof e.reloadDocument=="boolean"&&typeof e.replace=="boolean")return e}catch{}}function Mme(t){if(t.startsWith(`${eQ}:${Ame}:{`))try{let e=JSON.parse(t.slice(40));if(typeof e=="object"&&e&&typeof e.status=="number"&&typeof e.statusText=="string")return new wme(e.status,e.statusText,e.data)}catch{}}function Eme(t,{relative:e}={}){Pa(dy(),"useHref() may be used only in the context of a component.");let{basename:n,navigator:r}=w.useContext(gl),{hash:i,pathname:s,search:o}=qw(t,{relative:e}),l=s;return n!=="/"&&(l=s==="/"?n:Ju([n,s])),r.createHref({pathname:l,search:o,hash:i})}function dy(){return w.useContext(Bw)!=null}function Kc(){return Pa(dy(),"useLocation() may be used only in the context of a component."),w.useContext(Bw).location}var tQ="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function nQ(t){w.useContext(gl).static||w.useLayoutEffect(t)}function Lo(){let{isDataRoute:t}=w.useContext(hc);return t?Gme():Dme()}function Dme(){Pa(dy(),"useNavigate() may be used only in the context of a component.");let t=w.useContext(cy),{basename:e,navigator:n}=w.useContext(gl),{matches:r}=w.useContext(hc),{pathname:i}=Kc(),s=JSON.stringify(oO(r)),o=w.useRef(!1);return nQ(()=>{o.current=!0}),w.useCallback((c,d={})=>{if(rc(o.current,tQ),!o.current)return;if(typeof c=="number"){n.go(c);return}let u=lO(c,JSON.parse(s),i,d.relative==="path");t==null&&e!=="/"&&(u.pathname=u.pathname==="/"?e:Ju([e,u.pathname])),(d.replace?n.replace:n.push)(u,d.state,d)},[e,n,s,i,t])}var rQ=w.createContext(null);function uy(){return w.useContext(rQ)}function Fme(t){let e=w.useContext(hc).outlet;return w.useMemo(()=>e&&w.createElement(rQ.Provider,{value:t},e),[e,t])}function Hw(){let{matches:t}=w.useContext(hc),e=t[t.length-1];return e?e.params:{}}function qw(t,{relative:e}={}){let{matches:n}=w.useContext(hc),{pathname:r}=Kc(),i=JSON.stringify(oO(n));return w.useMemo(()=>lO(t,JSON.parse(i),r,e==="path"),[t,i,r,e])}function Rme(t,e){return aQ(t,e)}function aQ(t,e,n,r,i){Pa(dy(),"useRoutes() may be used only in the context of a component.");let{navigator:s}=w.useContext(gl),{matches:o}=w.useContext(hc),l=o[o.length-1],c=l?l.params:{},d=l?l.pathname:"/",u=l?l.pathnameBase:"/",m=l&&l.route;{let _=m&&m.path||"";sQ(d,!m||_.endsWith("*")||_.endsWith("*?"),`You rendered descendant (or called \`useRoutes()\`) at "${d}" (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 p=Kc(),f;if(e){let _=typeof e=="string"?ly(e):e;Pa(u==="/"||_.pathname?.startsWith(u),`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 "${u}" but pathname "${_.pathname}" was given in the \`location\` prop.`),f=_}else f=p;let x=f.pathname||"/",v=x;if(u!=="/"){let _=u.replace(/^\//,"").split("/");v="/"+x.replace(/^\//,"").split("/").slice(_.length).join("/")}let b=WY(t,{pathname:v});rc(m||b!=null,`No routes matched location "${f.pathname}${f.search}${f.hash}" `),rc(b==null||b[b.length-1].route.element!==void 0||b[b.length-1].route.Component!==void 0||b[b.length-1].route.lazy!==void 0,`Matched leaf route at location "${f.pathname}${f.search}${f.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 g=Ume(b&&b.map(_=>Object.assign({},_,{params:Object.assign({},c,_.params),pathname:Ju([u,s.encodeLocation?s.encodeLocation(_.pathname.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:_.pathname]),pathnameBase:_.pathnameBase==="/"?u:Ju([u,s.encodeLocation?s.encodeLocation(_.pathnameBase.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:_.pathnameBase])})),o,n,r,i);return e&&g?w.createElement(Bw.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",...f},navigationType:"POP"}},g):g}function Lme(){let t=Vme(),e=Sme(t)?`${t.status} ${t.statusText}`:t instanceof Error?t.message:JSON.stringify(t),n=t instanceof Error?t.stack:null,r="rgba(200,200,200, 0.5)",i={padding:"0.5rem",backgroundColor:r},s={padding:"2px 4px",backgroundColor:r},o=null;return console.error("Error handled by React Router default ErrorBoundary:",t),o=w.createElement(w.Fragment,null,w.createElement("p",null,"💿 Hey developer 👋"),w.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",w.createElement("code",{style:s},"ErrorBoundary")," or"," ",w.createElement("code",{style:s},"errorElement")," prop on your route.")),w.createElement(w.Fragment,null,w.createElement("h2",null,"Unexpected Application Error!"),w.createElement("h3",{style:{fontStyle:"italic"}},e),n?w.createElement("pre",{style:i},n):null,o)}var Ome=w.createElement(Lme,null),iQ=class extends w.Component{constructor(t){super(t),this.state={location:t.location,revalidation:t.revalidation,error:t.error}}static getDerivedStateFromError(t){return{error:t}}static getDerivedStateFromProps(t,e){return e.location!==t.location||e.revalidation!=="idle"&&t.revalidation==="idle"?{error:t.error,location:t.location,revalidation:t.revalidation}:{error:t.error!==void 0?t.error:e.error,location:e.location,revalidation:t.revalidation||e.revalidation}}componentDidCatch(t,e){this.props.onError?this.props.onError(t,e):console.error("React Router caught the following error during render",t)}render(){let t=this.state.error;if(this.context&&typeof t=="object"&&t&&"digest"in t&&typeof t.digest=="string"){const n=Mme(t.digest);n&&(t=n)}let e=t!==void 0?w.createElement(hc.Provider,{value:this.props.routeContext},w.createElement(cO.Provider,{value:t,children:this.props.component})):this.props.children;return this.context?w.createElement(Ime,{error:t},e):e}};iQ.contextType=Nme;var vM=new WeakMap;function Ime({children:t,error:e}){let{basename:n}=w.useContext(gl);if(typeof e=="object"&&e&&"digest"in e&&typeof e.digest=="string"){let r=jme(e.digest);if(r){let i=vM.get(e);if(i)throw i;let s=QY(r.location,n);if(YY&&!vM.get(e))if(s.isExternal||r.reloadDocument)window.location.href=s.absoluteURL||s.to;else{const o=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(s.to,{replace:r.replace}));throw vM.set(e,o),o}return w.createElement("meta",{httpEquiv:"refresh",content:`0;url=${s.absoluteURL||s.to}`})}}return t}function zme({routeContext:t,match:e,children:n}){let r=w.useContext(cy);return r&&r.static&&r.staticContext&&(e.route.errorElement||e.route.ErrorBoundary)&&(r.staticContext._deepestRenderedBoundaryId=e.route.id),w.createElement(hc.Provider,{value:t},n)}function Ume(t,e=[],n=null,r=null,i=null){if(t==null){if(!n)return null;if(n.errors)t=n.matches;else if(e.length===0&&!n.initialized&&n.matches.length>0)t=n.matches;else return null}let s=t,o=n?.errors;if(o!=null){let u=s.findIndex(m=>m.route.id&&o?.[m.route.id]!==void 0);Pa(u>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(o).join(",")}`),s=s.slice(0,Math.min(s.length,u+1))}let l=!1,c=-1;if(n)for(let u=0;u=0?s=s.slice(0,c+1):s=[s[0]];break}}}let d=n&&r?(u,m)=>{r(u,{location:n.location,params:n.matches?.[0]?.params??{},unstable_pattern:_me(n.matches),errorInfo:m})}:void 0;return s.reduceRight((u,m,p)=>{let f,x=!1,v=null,b=null;n&&(f=o&&m.route.id?o[m.route.id]:void 0,v=m.route.errorElement||Ome,l&&(c<0&&p===0?(sQ("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),x=!0,b=null):c===p&&(x=!0,b=m.route.hydrateFallbackElement||null)));let g=e.concat(s.slice(0,p+1)),_=()=>{let C;return f?C=v:x?C=b:m.route.Component?C=w.createElement(m.route.Component,null):m.route.element?C=m.route.element:C=u,w.createElement(zme,{match:m,routeContext:{outlet:u,matches:g,isDataRoute:n!=null},children:C})};return n&&(m.route.ErrorBoundary||m.route.errorElement||p===0)?w.createElement(iQ,{location:n.location,revalidation:n.revalidation,component:v,error:f,children:_(),routeContext:{outlet:null,matches:g,isDataRoute:!0},onError:d}):_()},null)}function dO(t){return`${t} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function Bme(t){let e=w.useContext(cy);return Pa(e,dO(t)),e}function Hme(t){let e=w.useContext(DP);return Pa(e,dO(t)),e}function qme(t){let e=w.useContext(hc);return Pa(e,dO(t)),e}function uO(t){let e=qme(t),n=e.matches[e.matches.length-1];return Pa(n.route.id,`${t} can only be used on routes that contain a unique "id"`),n.route.id}function $me(){return uO("useRouteId")}function Vme(){let t=w.useContext(cO),e=Hme("useRouteError"),n=uO("useRouteError");return t!==void 0?t:e.errors?.[n]}function Gme(){let{router:t}=Bme("useNavigate"),e=uO("useNavigate"),n=w.useRef(!1);return nQ(()=>{n.current=!0}),w.useCallback(async(i,s={})=>{rc(n.current,tQ),n.current&&(typeof i=="number"?await t.navigate(i):await t.navigate(i,{fromRouteId:e,...s}))},[t,e])}var oH={};function sQ(t,e,n){!e&&!oH[t]&&(oH[t]=!0,rc(!1,n))}w.memo(Wme);function Wme({routes:t,future:e,state:n,onError:r}){return aQ(t,void 0,n,r,e)}function Ex({to:t,replace:e,state:n,relative:r}){Pa(dy()," may be used only in the context of a component.");let{static:i}=w.useContext(gl);rc(!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:s}=w.useContext(hc),{pathname:o}=Kc(),l=Lo(),c=lO(t,oO(s),o,r==="path"),d=JSON.stringify(c);return w.useEffect(()=>{l(JSON.parse(d),{replace:e,state:n,relative:r})},[l,d,r,e,n]),null}function oQ(t){return Fme(t.context)}function Dr(t){Pa(!1,"A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .")}function Kme({basename:t="/",children:e=null,location:n,navigationType:r="POP",navigator:i,static:s=!1,unstable_useTransitions:o}){Pa(!dy(),"You cannot render a inside another . You should never have more than one in your app.");let l=t.replace(/^\/*/,"/"),c=w.useMemo(()=>({basename:l,navigator:i,static:s,unstable_useTransitions:o,future:{}}),[l,i,s,o]);typeof n=="string"&&(n=ly(n));let{pathname:d="/",search:u="",hash:m="",state:p=null,key:f="default"}=n,x=w.useMemo(()=>{let v=cm(d,l);return v==null?null:{location:{pathname:v,search:u,hash:m,state:p,key:f},navigationType:r}},[l,d,u,m,p,f,r]);return rc(x!=null,` is not able to match the URL "${d}${u}${m}" because it does not start with the basename, so the won't render anything.`),x==null?null:w.createElement(gl.Provider,{value:c},w.createElement(Bw.Provider,{children:e,value:x}))}function Xme({children:t,location:e}){return Rme(U3(t),e)}function U3(t,e=[]){let n=[];return w.Children.forEach(t,(r,i)=>{if(!w.isValidElement(r))return;let s=[...e,i];if(r.type===w.Fragment){n.push.apply(n,U3(r.props.children,s));return}Pa(r.type===Dr,`[${typeof r.type=="string"?r.type:r.type.name}] is not a component. All component children of must be a or `),Pa(!r.props.index||!r.props.children,"An index route cannot have child routes.");let o={id:r.props.id||s.join("-"),caseSensitive:r.props.caseSensitive,element:r.props.element,Component:r.props.Component,index:r.props.index,path:r.props.path,middleware:r.props.middleware,loader:r.props.loader,action:r.props.action,hydrateFallbackElement:r.props.hydrateFallbackElement,HydrateFallback:r.props.HydrateFallback,errorElement:r.props.errorElement,ErrorBoundary:r.props.ErrorBoundary,hasErrorBoundary:r.props.hasErrorBoundary===!0||r.props.ErrorBoundary!=null||r.props.errorElement!=null,shouldRevalidate:r.props.shouldRevalidate,handle:r.props.handle,lazy:r.props.lazy};r.props.children&&(o.children=U3(r.props.children,s)),n.push(o)}),n}var Mk="get",Ek="application/x-www-form-urlencoded";function FP(t){return typeof HTMLElement<"u"&&t instanceof HTMLElement}function Yme(t){return FP(t)&&t.tagName.toLowerCase()==="button"}function Qme(t){return FP(t)&&t.tagName.toLowerCase()==="form"}function Zme(t){return FP(t)&&t.tagName.toLowerCase()==="input"}function Jme(t){return!!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey)}function ehe(t,e){return t.button===0&&(!e||e==="_self")&&!Jme(t)}function B3(t=""){return new URLSearchParams(typeof t=="string"||Array.isArray(t)||t instanceof URLSearchParams?t:Object.keys(t).reduce((e,n)=>{let r=t[n];return e.concat(Array.isArray(r)?r.map(i=>[n,i]):[[n,r]])},[]))}function the(t,e){let n=B3(t);return e&&e.forEach((r,i)=>{n.has(i)||e.getAll(i).forEach(s=>{n.append(i,s)})}),n}var H_=null;function nhe(){if(H_===null)try{new FormData(document.createElement("form"),0),H_=!1}catch{H_=!0}return H_}var rhe=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function wM(t){return t!=null&&!rhe.has(t)?(rc(!1,`"${t}" is not a valid \`encType\` for \`