Merge branch 'benphelps:main' into main

This commit is contained in:
Ajay Kristipati 2023-01-14 18:56:45 -05:00 committed by GitHub
commit cc375f9842
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 774 additions and 445 deletions

View File

@ -7,12 +7,10 @@ WORKDIR /app
COPY --link package.json pnpm-lock.yaml* ./ COPY --link package.json pnpm-lock.yaml* ./
RUN <<EOF SHELL ["/bin/ash", "-xeo", "pipefail", "-c"]
set -xe RUN apk add --no-cache libc6-compat \
apk add libc6-compat && apk add --no-cache --virtual .gyp python3 make g++ \
apk add --virtual .gyp python3 make g++ && npm install -g pnpm
npm install -g pnpm
EOF
RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm fetch | grep -v "cross-device link not permitted\|Falling back to copying packages from store" RUN --mount=type=cache,id=pnpm-store,target=/root/.local/share/pnpm/store pnpm fetch | grep -v "cross-device link not permitted\|Falling back to copying packages from store"
@ -29,12 +27,10 @@ ARG REVISION
COPY --link --from=deps /app/node_modules ./node_modules/ COPY --link --from=deps /app/node_modules ./node_modules/
COPY . . COPY . .
RUN <<EOF SHELL ["/bin/ash", "-xeo", "pipefail", "-c"]
set -xe RUN npm run telemetry \
npm run telemetry && mkdir config && echo '---' > config/settings.yaml \
mkdir config && echo '-' > config/settings.yaml && NEXT_PUBLIC_BUILDTIME=$BUILDTIME NEXT_PUBLIC_VERSION=$VERSION NEXT_PUBLIC_REVISION=$REVISION npm run build
NEXT_PUBLIC_BUILDTIME=$BUILDTIME NEXT_PUBLIC_VERSION=$VERSION NEXT_PUBLIC_REVISION=$REVISION npm run build
EOF
# Production image, copy all the files and run next # Production image, copy all the files and run next
FROM docker.io/node:18-alpine AS runner FROM docker.io/node:18-alpine AS runner
@ -50,12 +46,15 @@ ENV NODE_ENV production
WORKDIR /app WORKDIR /app
# Copy files from context (this allows the files to copy before the builder stage is done). # Copy files from context (this allows the files to copy before the builder stage is done).
COPY --link package.json next.config.js ./ COPY --link --chown=1000:1000 package.json next.config.js ./
COPY --link /public ./public COPY --link --chown=1000:1000 /public ./public/
# Copy files from builder # Copy files from builder
COPY --link --from=builder /app/.next/standalone ./ COPY --link --from=builder --chown=1000:1000 /app/.next/standalone ./
COPY --link --from=builder /app/.next/static/ ./.next/static/ COPY --link --from=builder --chown=1000:1000 /app/.next/static/ ./.next/static/
COPY --link --chmod=755 docker-entrypoint.sh /usr/local/bin/
RUN apk add --no-cache su-exec
ENV PORT 3000 ENV PORT 3000
EXPOSE $PORT EXPOSE $PORT
@ -63,4 +62,5 @@ EXPOSE $PORT
HEALTHCHECK --interval=10s --timeout=3s --start-period=20s \ HEALTHCHECK --interval=10s --timeout=3s --start-period=20s \
CMD wget --no-verbose --tries=1 --spider --no-check-certificate http://localhost:$PORT/api/healthcheck || exit 1 CMD wget --no-verbose --tries=1 --spider --no-check-certificate http://localhost:$PORT/api/healthcheck || exit 1
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["node", "server.js"] CMD ["node", "server.js"]

View File

@ -2,8 +2,22 @@
set -e set -e
# Default to root, so old installations won't break
export PUID=${PUID:-0}
export PGID=${PGID:-0}
# This is in attempt to preserve the original behavior of the Dockerfile, # This is in attempt to preserve the original behavior of the Dockerfile,
# while also supporting the lscr.io /config directory # while also supporting the lscr.io /config directory
[ ! -d "/app/config" ] && ln -s /config /app/config [ ! -d "/app/config" ] && ln -s /config /app/config
node server.js # Set privileges for /app but only if pid 1 user is root and we are dropping privileges.
# If container is run as an unprivileged user, it means owner already handled ownership setup on their own.
# Running chown in that case (as non-root) will cause error
[ "$(id -u)" == "0" ] && [ "${PUID}" != "0" ] && chown -R ${PUID}:${PGID} /app
# Drop privileges (when asked to) if root, otherwise run as current user
if [ "$(id -u)" == "0" ] && [ "${PUID}" != "0" ]; then
su-exec ${PUID}:${PGID} "$@"
else
exec "$@"
fi

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"print_progress": "Progress",
"printer_state": "Printer State",
"print_status": "Print Status",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"print_progress": "Progress",
"printer_state": "Printer State",
"print_status": "Print Status",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -412,5 +412,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"layers": "Layers",
"print_progress": "Progress"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Memoria activa", "memory": "Memoria activa",
"wanUpload": "Carga WAN", "wanUpload": "Carga WAN",
"wanDownload": "Descargar WAN" "wanDownload": "Descargar WAN"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Mém. Utilisée", "memory": "Mém. Utilisée",
"wanUpload": "WAN Envoi", "wanUpload": "WAN Envoi",
"wanDownload": "WAN Récep." "wanDownload": "WAN Récep."
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -77,13 +77,13 @@
"emby": { "emby": {
"playing": "Reprodukcija", "playing": "Reprodukcija",
"transcoding": "Prekodiranje", "transcoding": "Prekodiranje",
"bitrate": "Brzina prijenosa", "bitrate": "Stopa bitova",
"no_active": "Nema aktivnih prijenosa" "no_active": "Nema aktivnih prijenosa"
}, },
"tautulli": { "tautulli": {
"playing": "Reprodukcija", "playing": "Reprodukcija",
"transcoding": "Prekodiranje", "transcoding": "Prekodiranje",
"bitrate": "Brzina prijenosa", "bitrate": "Stopa bitova",
"no_active": "Nema aktivnih prijenosa" "no_active": "Nema aktivnih prijenosa"
}, },
"nzbget": { "nzbget": {
@ -388,10 +388,10 @@
"seed": "Prenošenje preuzetog sadržaja" "seed": "Prenošenje preuzetog sadržaja"
}, },
"mikrotik": { "mikrotik": {
"cpuLoad": "CPU Load", "cpuLoad": "CPU opterećenje",
"memoryUsed": "Korištena memorija", "memoryUsed": "Korištena memorija",
"uptime": "Uptime", "uptime": "Radno vrijeme",
"numberOfLeases": "Leases" "numberOfLeases": "Unajmljivanja"
}, },
"xteve": { "xteve": {
"streams_all": "Svi prijenosi", "streams_all": "Svi prijenosi",
@ -399,9 +399,15 @@
"streams_xepg": "XEPG kanali" "streams_xepg": "XEPG kanali"
}, },
"opnsense": { "opnsense": {
"cpu": "CPU Load", "cpu": "CPU opterećenje",
"memory": "Aktivna memorija", "memory": "Aktivna memorija",
"wanUpload": "WAN prijenos", "wanUpload": "WAN prijenos",
"wanDownload": "WAN preuzimanje" "wanDownload": "WAN preuzimanje"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"layers": "Layers",
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress"
} }
} }

View File

@ -51,7 +51,7 @@
"total": "Totale", "total": "Totale",
"free": "Libero", "free": "Libero",
"used": "In utilizzo", "used": "In utilizzo",
"load": "Carica", "load": "Carico",
"cpu": "CPU" "cpu": "CPU"
}, },
"rutorrent": { "rutorrent": {
@ -175,7 +175,7 @@
"strelaysrv": { "strelaysrv": {
"numActiveSessions": "Sessioni", "numActiveSessions": "Sessioni",
"numConnections": "Connessioni", "numConnections": "Connessioni",
"dataRelayed": "Ritrasmettessi", "dataRelayed": "Ritrasmessi",
"transferRate": "Velocità" "transferRate": "Velocità"
}, },
"authentik": { "authentik": {
@ -222,10 +222,10 @@
"wmo": { "wmo": {
"65-day": "Pioggia Intensa", "65-day": "Pioggia Intensa",
"2-night": "Parzialmente Nuvoloso", "2-night": "Parzialmente Nuvoloso",
"0-day": "Solleggiato", "0-day": "Soleggiato",
"0-night": "Pulisci", "0-night": "Sereno",
"1-day": "Principalmente Soleggiato", "1-day": "Prevalentemente Soleggiato",
"1-night": "Principalmente Sereno", "1-night": "Prevalentemente Sereno",
"2-day": "Parzialmente Nuvoloso", "2-day": "Parzialmente Nuvoloso",
"3-day": "Nuvoloso", "3-day": "Nuvoloso",
"3-night": "Nuvoloso", "3-night": "Nuvoloso",
@ -314,7 +314,7 @@
}, },
"navidrome": { "navidrome": {
"nothing_streaming": "Nessun Sistema Attivo", "nothing_streaming": "Nessun Sistema Attivo",
"please_wait": "Attendere, Prego" "please_wait": "Attendere prego"
}, },
"pyload": { "pyload": {
"speed": "Velocità", "speed": "Velocità",
@ -391,17 +391,23 @@
"cpuLoad": "Carico della CPU", "cpuLoad": "Carico della CPU",
"memoryUsed": "Memoria Utilizzata", "memoryUsed": "Memoria Utilizzata",
"uptime": "Tempo di attività", "uptime": "Tempo di attività",
"numberOfLeases": "Leases" "numberOfLeases": "Lease"
}, },
"xteve": { "xteve": {
"streams_all": "All Streams", "streams_all": "Tutti gli stream",
"streams_active": "Active Streams", "streams_active": "Stream attivi",
"streams_xepg": "XEPG Channels" "streams_xepg": "Canali XEPG"
}, },
"opnsense": { "opnsense": {
"cpu": "CPU Load", "cpu": "Carico CPU",
"memory": "Active Memory", "memory": "Memoria in uso",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -31,8 +31,8 @@
"public_ip": "Public IP" "public_ip": "Public IP"
}, },
"common": { "common": {
"bibyterate": "", "bibyterate": "{{value, rate(bits: false; binary: true)}}",
"bibitrate": "" "bibitrate": "{{value, rate(bits: true; binary: true)}}"
}, },
"widget": { "widget": {
"api_error": "APIエラー", "api_error": "APIエラー",
@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -412,5 +412,11 @@
"memory": "Memória Ativa", "memory": "Memória Ativa",
"wanUpload": "Envio WAN", "wanUpload": "Envio WAN",
"wanDownload": "WAN Descarga" "wanDownload": "WAN Descarga"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"print_progress": "Progress",
"printer_state": "Printer State",
"print_status": "Print Status",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -23,8 +23,8 @@
"deluge": { "deluge": {
"download": "Завантаження", "download": "Завантаження",
"upload": "Відправлення", "upload": "Відправлення",
"leech": "Leech", "leech": "Ліч",
"seed": "Seed" "seed": "Сід"
}, },
"readarr": { "readarr": {
"wanted": "Розшукується", "wanted": "Розшукується",
@ -32,76 +32,76 @@
"books": "Книжки" "books": "Книжки"
}, },
"wmo": { "wmo": {
"55-day": "Heavy Drizzle", "55-day": "Сильна мряка",
"55-night": "Heavy Drizzle", "55-night": "Сильна мряка",
"56-day": "Light Freezing Drizzle", "56-day": "Невеликий морозний дощ",
"56-night": "Light Freezing Drizzle", "56-night": "Невеликий морозний дощ",
"0-day": "Sunny", "0-day": "Сонячно",
"0-night": "Clear", "0-night": "Ясно",
"1-day": "Mainly Sunny", "1-day": "Переважно сонячно",
"1-night": "Mainly Clear", "1-night": "Переважно ясно",
"2-day": "Partly Cloudy", "2-day": "Частково хмарно",
"2-night": "Partly Cloudy", "2-night": "Частково хмарно",
"3-day": "Cloudy", "3-day": "Хмарно",
"3-night": "Cloudy", "3-night": "Хмарно",
"53-day": "Drizzle", "53-day": "Мряка",
"45-day": "Foggy", "45-day": "Туманно",
"45-night": "Foggy", "45-night": "Туманно",
"48-day": "Foggy", "48-day": "Туманно",
"48-night": "Foggy", "48-night": "Туманно",
"51-day": "Light Drizzle", "51-day": "Легка мряка",
"51-night": "Light Drizzle", "51-night": "Легка мряка",
"53-night": "Drizzle", "53-night": "Мряка",
"57-day": "Freezing Drizzle", "57-day": "Морозний дощ",
"57-night": "Freezing Drizzle", "57-night": "Морозний дощ",
"61-day": "Light Rain", "61-day": "Невеликий дощ",
"61-night": "Light Rain", "61-night": "Невеликий дощ",
"63-day": "Rain", "63-day": "Дощ",
"63-night": "Rain", "63-night": "Дощ",
"65-day": "Heavy Rain", "65-day": "Сильний дощ",
"65-night": "Heavy Rain", "65-night": "Сильний дощ",
"66-day": "Freezing Rain", "66-day": "Холодний дощ",
"66-night": "Freezing Rain", "66-night": "Холодний дощ",
"67-day": "Freezing Rain", "67-day": "Холодний дощ",
"67-night": "Freezing Rain", "67-night": "Холодний дощ",
"71-day": "Light Snow", "71-day": "Невеликий сніг",
"71-night": "Light Snow", "71-night": "Невеликий сніг",
"73-day": "Snow", "73-day": "Сніг",
"73-night": "Snow", "73-night": "Сніг",
"75-day": "Heavy Snow", "75-day": "Снігопад",
"75-night": "Heavy Snow", "75-night": "Снігопад",
"77-day": "Snow Grains", "77-day": "Снігові зерна",
"77-night": "Snow Grains", "77-night": "Снігові зерна",
"80-day": "Light Showers", "80-day": "Невелика злива",
"80-night": "Light Showers", "80-night": "Невелика злива",
"81-day": "Showers", "81-day": "Злива",
"82-day": "Heavy Showers", "82-day": "Сильна злива",
"82-night": "Heavy Showers", "82-night": "Сильна злива",
"81-night": "Showers", "81-night": "Злива",
"85-day": "Snow Showers", "85-day": "Дощ зі снігом",
"85-night": "Snow Showers", "85-night": "Дощ зі снігом",
"86-day": "Snow Showers", "86-day": "Дощ зі снігом",
"86-night": "Snow Showers", "86-night": "Дощ зі снігом",
"95-day": "Thunderstorm", "95-day": "Гроза",
"95-night": "Thunderstorm", "95-night": "Гроза",
"96-day": "Thunderstorm With Hail", "96-day": "Гроза з градом",
"96-night": "Thunderstorm With Hail", "96-night": "Гроза з градом",
"99-day": "Thunderstorm With Hail", "99-day": "Гроза з градом",
"99-night": "Thunderstorm With Hail" "99-night": "Гроза з градом"
}, },
"pyload": { "pyload": {
"speed": "Speed", "speed": "Швидкість",
"active": "Active", "active": "Активно",
"queue": "Queue", "queue": "Черга",
"total": "Total" "total": "Всього"
}, },
"gluetun": { "gluetun": {
"country": "Country", "country": "Країна",
"public_ip": "Public IP", "public_ip": "Публічний IP",
"region": "Region" "region": "Регіон"
}, },
"hdhomerun": { "hdhomerun": {
"channels": "Channels", "channels": "Канали",
"hd": "HD" "hd": "HD"
}, },
"widget": { "widget": {
@ -167,8 +167,8 @@
"flood": { "flood": {
"download": "Завантаження", "download": "Завантаження",
"upload": "Відправлення", "upload": "Відправлення",
"leech": "Leech", "leech": "Ліч",
"seed": "Seed" "seed": "Сід"
}, },
"changedetectionio": { "changedetectionio": {
"totalObserved": "Всього спостережень", "totalObserved": "Всього спостережень",
@ -193,20 +193,20 @@
"transmission": { "transmission": {
"download": "Завантаження", "download": "Завантаження",
"upload": "Відправлення", "upload": "Відправлення",
"leech": "Leech", "leech": "Ліч",
"seed": "Seed" "seed": "Сід"
}, },
"qbittorrent": { "qbittorrent": {
"download": "Завантаження", "download": "Завантаження",
"upload": "Відправлення", "upload": "Відправлення",
"leech": "Leech", "leech": "Ліч",
"seed": "Seed" "seed": "Сід"
}, },
"downloadstation": { "downloadstation": {
"download": "Завантаження", "download": "Завантаження",
"upload": "Відправлення", "upload": "Відправлення",
"leech": "Leech", "leech": "Ліч",
"seed": "Seed" "seed": "Сід"
}, },
"sonarr": { "sonarr": {
"wanted": "Розшукується", "wanted": "Розшукується",
@ -225,13 +225,13 @@
"albums": "Альбоми" "albums": "Альбоми"
}, },
"traefik": { "traefik": {
"middleware": "Middleware", "middleware": "Проміжне програмне забезпечення",
"routers": "Роутери", "routers": "Роутери",
"services": "Сервіси" "services": "Сервіси"
}, },
"navidrome": { "navidrome": {
"nothing_streaming": "No Active Streams", "nothing_streaming": "Немає активних потоків",
"please_wait": "Please Wait" "please_wait": "Будь ласка, зачекайте"
}, },
"bazarr": { "bazarr": {
"missingEpisodes": "Відсутні епізоди", "missingEpisodes": "Відсутні епізоди",
@ -281,127 +281,133 @@
"saved": "Збережено" "saved": "Збережено"
}, },
"npm": { "npm": {
"enabled": "Enabled", "enabled": "Увімкнено",
"disabled": "Disabled", "disabled": "Вимкнено",
"total": "Total" "total": "Всього"
}, },
"coinmarketcap": { "coinmarketcap": {
"configure": "Configure one or more crypto currencies to track", "configure": "Налаштуйте одну або кілька криптовалют для відстеження",
"1hour": "1 Hour", "1hour": "1 година",
"1day": "1 Day", "1day": "1 день",
"7days": "7 Days", "7days": "7 днів",
"30days": "30 Days" "30days": "30 днів"
}, },
"mastodon": { "mastodon": {
"domain_count": "Domains", "domain_count": "Домени",
"user_count": "Users", "user_count": "Користувачі",
"status_count": "Posts" "status_count": "Пости"
}, },
"miniflux": { "miniflux": {
"read": "Read", "read": "Прочитано",
"unread": "Unread" "unread": "Не прочитано"
}, },
"gotify": { "gotify": {
"apps": "Applications", "apps": "Застосунки",
"clients": "Clients", "clients": "Клієнти",
"messages": "Messages" "messages": "Повідомлення"
}, },
"prowlarr": { "prowlarr": {
"enableIndexers": "Indexers", "enableIndexers": "Індексатори",
"numberOfGrabs": "Grabs", "numberOfGrabs": "Захоплення",
"numberOfQueries": "Queries", "numberOfQueries": "Запити",
"numberOfFailGrabs": "Fail Grabs", "numberOfFailGrabs": "Невдалі захоплення",
"numberOfFailQueries": "Fail Queries" "numberOfFailQueries": "Невдалі запити"
}, },
"jackett": { "jackett": {
"configured": "Configured", "configured": "Налаштовано",
"errored": "Errored" "errored": "Помилка"
}, },
"strelaysrv": { "strelaysrv": {
"numActiveSessions": "Sessions", "numActiveSessions": "Сесії",
"numConnections": "Connections", "numConnections": "Підключення",
"dataRelayed": "Relayed", "dataRelayed": "Ретрансльовано",
"transferRate": "Rate" "transferRate": "Швидкість"
}, },
"authentik": { "authentik": {
"users": "Users", "users": "Користувачі",
"loginsLast24H": "Logins (24h)", "loginsLast24H": "Вхід (24 години)",
"failedLoginsLast24H": "Failed Logins (24h)" "failedLoginsLast24H": "Невдалі входи (24 години)"
}, },
"proxmox": { "proxmox": {
"mem": "MEM", "mem": "Пам'ять",
"cpu": "CPU", "cpu": "CPU",
"vms": "VMs", "vms": "Віртуальні машини",
"lxc": "LXC" "lxc": "Контейнери Linux"
}, },
"glances": { "glances": {
"cpu": "CPU", "cpu": "CPU",
"mem": "MEM", "mem": "Пам'ять",
"wait": "Please wait" "wait": "Будь ласка, зачекайте"
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Закладка",
"service": "Service" "service": "Сервіс"
}, },
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "Система",
"updates": "Updates", "updates": "Оновлення",
"child_bridges_status": "{{ok}}/{{total}}", "child_bridges_status": "{{ok}}/{{total}}",
"update_available": "Update Available", "update_available": "Доступне оновлення",
"up_to_date": "Up to Date", "up_to_date": "Актуально",
"child_bridges": "Child Bridges" "child_bridges": "Дитячі мости"
}, },
"watchtower": { "watchtower": {
"containers_scanned": "Scanned", "containers_scanned": "Відскановано",
"containers_updated": "Updated", "containers_updated": "Оновлено",
"containers_failed": "Failed" "containers_failed": "Невдача"
}, },
"autobrr": { "autobrr": {
"approvedPushes": "Approved", "approvedPushes": "Схвалено",
"rejectedPushes": "Rejected", "rejectedPushes": "Відхилено",
"filters": "Filters", "filters": "Фільтри",
"indexers": "Indexers" "indexers": "Індексатори"
}, },
"tubearchivist": { "tubearchivist": {
"downloads": "Queue", "downloads": "Черга",
"videos": "Videos", "videos": "Відео",
"channels": "Channels", "channels": "Канали",
"playlists": "Playlists" "playlists": "Плейлисти"
}, },
"truenas": { "truenas": {
"load": "System Load", "load": "Завантаження системи",
"uptime": "Uptime", "uptime": "Час роботи",
"alerts": "Alerts", "alerts": "Сповіщення",
"time": "{{value, number(style: unit; unitDisplay: long;)}}" "time": "{{value, number(style: unit; unitDisplay: long;)}}"
}, },
"scrutiny": { "scrutiny": {
"passed": "Passed", "passed": "Пройшов",
"failed": "Failed", "failed": "Невдача",
"unknown": "Unknown" "unknown": "Невідомо"
}, },
"paperlessngx": { "paperlessngx": {
"inbox": "Inbox", "inbox": "Вхідні",
"total": "Total" "total": "Всього"
}, },
"nextdns": { "nextdns": {
"wait": "Please Wait", "wait": "Будь ласка, зачекайте",
"no_devices": "No Device Data Received" "no_devices": "Дані про пристрій не отримано"
}, },
"mikrotik": { "mikrotik": {
"cpuLoad": "CPU Load", "cpuLoad": "Завантаження CPU",
"memoryUsed": "Memory Used", "memoryUsed": "Використана пам'ять",
"uptime": "Uptime", "uptime": "Час роботи",
"numberOfLeases": "Leases" "numberOfLeases": "Оренди"
}, },
"xteve": { "xteve": {
"streams_all": "All Streams", "streams_all": "Всі потоки",
"streams_active": "Active Streams", "streams_active": "Активні потоки",
"streams_xepg": "XEPG Channels" "streams_xepg": "Канали XEPG"
}, },
"opnsense": { "opnsense": {
"cpu": "CPU Load", "cpu": "Завантаження CPU",
"memory": "Active Memory", "memory": "Активна пам'ять",
"wanUpload": "WAN Upload", "wanUpload": "Вивантаження WAN",
"wanDownload": "WAN Download" "wanDownload": "Завантаження WAN"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"print_progress": "Progress",
"layers": "Layers",
"printer_state": "Printer State",
"print_status": "Print Status"
} }
} }

View File

@ -403,5 +403,11 @@
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN Upload",
"wanDownload": "WAN Download" "wanDownload": "WAN Download"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -1,407 +1,413 @@
{ {
"widget": { "widget": {
"missing_type": "Missing Widget Type: {{type}}", "missing_type": "遺失小工具的類型: {{type}}",
"api_error": "API Error", "api_error": "API錯誤",
"status": "Status", "status": "狀態",
"information": "Information", "information": "資訊",
"url": "URL", "url": "URL",
"raw_error": "Raw Error", "raw_error": "Raw Error",
"response_data": "Response Data" "response_data": "Response Data"
}, },
"weather": { "weather": {
"current": "Current Location", "current": "目前位置",
"allow": "Click to allow", "allow": "點擊以允許",
"updating": "Updating", "updating": "更新中",
"wait": "Please wait" "wait": "請稍後"
}, },
"docker": { "docker": {
"rx": "RX", "rx": "接收",
"offline": "Offline", "offline": "離線",
"tx": "TX", "tx": "發送",
"mem": "MEM", "mem": "記憶體",
"cpu": "CPU", "cpu": "處理器",
"error": "Error", "error": "錯誤",
"unknown": "Unknown" "unknown": "未知的"
}, },
"emby": { "emby": {
"playing": "Playing", "playing": "正在播放",
"transcoding": "Transcoding", "transcoding": "轉碼",
"bitrate": "Bitrate", "bitrate": "位元率",
"no_active": "No Active Streams" "no_active": "無播放活動"
}, },
"tautulli": { "tautulli": {
"playing": "Playing", "playing": "正在播放",
"transcoding": "Transcoding", "transcoding": "轉碼",
"bitrate": "Bitrate", "bitrate": "位元率",
"no_active": "No Active Streams" "no_active": "無播放活動"
}, },
"jellyseerr": { "jellyseerr": {
"pending": "Pending", "pending": "待定",
"approved": "Approved", "approved": "已接受",
"available": "Available" "available": "可用的"
}, },
"search": { "search": {
"placeholder": "Search…" "placeholder": "搜尋…"
}, },
"resources": { "resources": {
"total": "Total", "total": "全部",
"free": "Free", "free": "剩餘",
"used": "Used", "used": "已使用",
"load": "Load", "load": "負載",
"cpu": "CPU" "cpu": "CPU"
}, },
"nzbget": { "nzbget": {
"rate": "Rate", "rate": "速率",
"remaining": "Remaining", "remaining": "剩餘",
"downloaded": "Downloaded" "downloaded": "已下載"
}, },
"sabnzbd": { "sabnzbd": {
"rate": "Rate", "rate": "速率",
"queue": "Queue", "queue": "佇列",
"timeleft": "Time Left" "timeleft": "剩餘時間"
}, },
"rutorrent": { "rutorrent": {
"active": "Active", "active": "Active",
"upload": "Upload", "upload": "上傳",
"download": "Download" "download": "下載"
}, },
"radarr": { "radarr": {
"movies": "Movies", "movies": "電影",
"wanted": "Wanted", "wanted": "關注中",
"queued": "Queued", "queued": "已加入佇列",
"missing": "Missing" "missing": "遺失"
}, },
"sonarr": { "sonarr": {
"wanted": "Wanted", "wanted": "關注中",
"queued": "Queued", "queued": "已加入佇列",
"series": "Series" "series": "系列"
}, },
"readarr": { "readarr": {
"wanted": "Wanted", "wanted": "關注中",
"queued": "Queued", "queued": "已加入佇列",
"books": "Books" "books": "書籍"
}, },
"ombi": { "ombi": {
"pending": "Pending", "pending": "待定",
"approved": "Approved", "approved": "已接受",
"available": "Available" "available": "可用的"
}, },
"overseerr": { "overseerr": {
"pending": "Pending", "pending": "待定",
"approved": "Approved", "approved": "已接受",
"available": "Available", "available": "可用的",
"processing": "Processing" "processing": "處理中"
}, },
"pihole": { "pihole": {
"queries": "Queries", "queries": "查詢數",
"blocked": "Blocked", "blocked": "已阻擋",
"gravity": "Gravity" "gravity": "Gravity"
}, },
"speedtest": { "speedtest": {
"upload": "Upload", "upload": "上行",
"download": "Download", "download": "下行",
"ping": "Ping" "ping": "Ping"
}, },
"portainer": { "portainer": {
"running": "Running", "running": "運行中",
"stopped": "Stopped", "stopped": "未運行",
"total": "Total" "total": "全部"
}, },
"traefik": { "traefik": {
"routers": "Routers", "routers": "路由器",
"services": "Services", "services": "服務",
"middleware": "Middleware" "middleware": "中介軟體"
}, },
"gotify": { "gotify": {
"clients": "Clients", "clients": "客戶端",
"apps": "Applications", "apps": "應用程式",
"messages": "Messages" "messages": "訊息"
}, },
"npm": { "npm": {
"enabled": "Enabled", "enabled": "已啟用",
"disabled": "Disabled", "disabled": "已停用",
"total": "Total" "total": "全部"
}, },
"coinmarketcap": { "coinmarketcap": {
"configure": "Configure one or more crypto currencies to track", "configure": "請設定一個或多個欲追蹤的加密貨幣",
"1hour": "1 Hour", "1hour": "1小時",
"1day": "1 Day", "1day": "1",
"7days": "7 Days", "7days": "7",
"30days": "30 Days" "30days": "30"
}, },
"prowlarr": { "prowlarr": {
"enableIndexers": "Indexers", "enableIndexers": "索引器",
"numberOfGrabs": "Grabs", "numberOfGrabs": "抓取",
"numberOfQueries": "Queries", "numberOfQueries": "查詢數",
"numberOfFailGrabs": "Fail Grabs", "numberOfFailGrabs": "抓取失敗",
"numberOfFailQueries": "Fail Queries" "numberOfFailQueries": "查詢失敗"
}, },
"transmission": { "transmission": {
"download": "Download", "download": "下載",
"upload": "Upload", "upload": "上傳",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
}, },
"jackett": { "jackett": {
"configured": "Configured", "configured": "已配置",
"errored": "Errored" "errored": "發生錯誤"
}, },
"bazarr": { "bazarr": {
"missingEpisodes": "Missing Episodes", "missingEpisodes": "缺失的劇集",
"missingMovies": "Missing Movies" "missingMovies": "缺失的電影"
}, },
"lidarr": { "lidarr": {
"wanted": "Wanted", "wanted": "關注中",
"queued": "Queued", "queued": "已加入佇列",
"albums": "Albums" "albums": "專輯"
}, },
"adguard": { "adguard": {
"queries": "Queries", "queries": "查詢數",
"blocked": "Blocked", "blocked": "已阻擋",
"filtered": "Filtered", "filtered": "已過濾",
"latency": "Latency" "latency": "延遲"
}, },
"qbittorrent": { "qbittorrent": {
"download": "Download", "download": "下載",
"upload": "Upload", "upload": "上傳",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
}, },
"mastodon": { "mastodon": {
"user_count": "Users", "user_count": "使用者",
"status_count": "Posts", "status_count": "文章",
"domain_count": "Domains" "domain_count": "網域"
}, },
"strelaysrv": { "strelaysrv": {
"numActiveSessions": "Sessions", "numActiveSessions": "工作階段",
"numConnections": "Connections", "numConnections": "連線",
"dataRelayed": "Relayed", "dataRelayed": "中繼",
"transferRate": "Rate" "transferRate": "速率"
}, },
"authentik": { "authentik": {
"users": "Users", "users": "使用者",
"loginsLast24H": "Logins (24h)", "loginsLast24H": "登錄(24h)",
"failedLoginsLast24H": "Failed Logins (24h)" "failedLoginsLast24H": "登錄失敗(24h)"
}, },
"proxmox": { "proxmox": {
"mem": "MEM", "mem": "記憶體",
"cpu": "CPU", "cpu": "CPU",
"lxc": "LXC", "lxc": "LXC",
"vms": "VMs" "vms": "VMs"
}, },
"unifi": { "unifi": {
"users": "Users", "users": "使用者",
"uptime": "System Uptime", "uptime": "系統運行時間",
"days": "Days", "days": "",
"wan": "WAN", "wan": "WAN",
"lan_users": "LAN Users", "lan_users": "LAN使用者",
"wlan_users": "WLAN Users", "wlan_users": "WLAN使用者",
"up": "UP", "up": "UP",
"down": "DOWN", "down": "DOWN",
"wait": "Please wait", "wait": "請稍後",
"lan": "LAN", "lan": "LAN",
"wlan": "WLAN", "wlan": "WLAN",
"devices": "Devices", "devices": "設備",
"lan_devices": "LAN Devices", "lan_devices": "LAN設備",
"wlan_devices": "WLAN Devices" "wlan_devices": "WLAN設備"
}, },
"plex": { "plex": {
"streams": "Active Streams", "streams": "正在播放",
"movies": "Movies", "movies": "電影",
"tv": "TV Shows" "tv": "影集"
}, },
"glances": { "glances": {
"cpu": "CPU", "cpu": "CPU",
"mem": "MEM", "mem": "記憶體",
"wait": "Please wait" "wait": "請稍後"
}, },
"changedetectionio": { "changedetectionio": {
"totalObserved": "Total Observed", "totalObserved": "Total Observed",
"diffsDetected": "Diffs Detected" "diffsDetected": "Diffs Detected"
}, },
"wmo": { "wmo": {
"0-day": "Sunny", "0-day": "",
"0-night": "Clear", "0-night": "晴朗",
"71-day": "Light Snow", "71-day": "小雪",
"71-night": "Light Snow", "71-night": "小雪",
"1-day": "Mainly Sunny", "1-day": "晴時多雲",
"1-night": "Mainly Clear", "1-night": "晴時多雲",
"2-day": "Partly Cloudy", "2-day": "多雲時陰",
"2-night": "Partly Cloudy", "2-night": "多雲時陰",
"3-day": "Cloudy", "3-day": "陰天",
"3-night": "Cloudy", "3-night": "陰天",
"45-day": "Foggy", "45-day": "有霧",
"45-night": "Foggy", "45-night": "有霧",
"48-day": "Foggy", "48-day": "有霧",
"48-night": "Foggy", "48-night": "有霧",
"51-day": "Light Drizzle", "51-day": "小毛雨",
"51-night": "Light Drizzle", "51-night": "小毛雨",
"53-day": "Drizzle", "53-day": "毛雨",
"53-night": "Drizzle", "53-night": "毛雨",
"55-day": "Heavy Drizzle", "55-day": "大毛雨",
"55-night": "Heavy Drizzle", "55-night": "大毛雨",
"56-day": "Light Freezing Drizzle", "56-day": "小凍毛雨",
"56-night": "Light Freezing Drizzle", "56-night": "小凍毛雨",
"57-day": "Freezing Drizzle", "57-day": "凍毛雨",
"57-night": "Freezing Drizzle", "57-night": "凍毛雨",
"61-day": "Light Rain", "61-day": "小雨",
"61-night": "Light Rain", "61-night": "小雨",
"63-day": "Rain", "63-day": "",
"63-night": "Rain", "63-night": "",
"65-day": "Heavy Rain", "65-day": "大雨",
"65-night": "Heavy Rain", "65-night": "大雨",
"66-day": "Freezing Rain", "66-day": "凍雨",
"66-night": "Freezing Rain", "66-night": "凍雨",
"67-day": "Freezing Rain", "67-day": "凍雨",
"67-night": "Freezing Rain", "67-night": "凍雨",
"73-day": "Snow", "73-day": "",
"73-night": "Snow", "73-night": "",
"75-day": "Heavy Snow", "75-day": "大雪",
"75-night": "Heavy Snow", "75-night": "大雪",
"77-day": "Snow Grains", "77-day": "雪粒",
"77-night": "Snow Grains", "77-night": "雪粒",
"80-day": "Light Showers", "80-day": "微陣雨",
"80-night": "Light Showers", "80-night": "微陣雨",
"81-day": "Showers", "81-day": "陣雨",
"81-night": "Showers", "81-night": "陣雨",
"82-day": "Heavy Showers", "82-day": "強陣雨",
"82-night": "Heavy Showers", "82-night": "強陣雨",
"85-day": "Snow Showers", "85-day": "陣雪",
"85-night": "Snow Showers", "85-night": "陣雪",
"86-day": "Snow Showers", "86-day": "陣雪",
"86-night": "Snow Showers", "86-night": "陣雪",
"95-day": "Thunderstorm", "95-day": "雷雨",
"95-night": "Thunderstorm", "95-night": "雷雨",
"96-day": "Thunderstorm With Hail", "96-day": "雷雨伴隨冰雹",
"96-night": "Thunderstorm With Hail", "96-night": "雷雨伴隨冰雹",
"99-day": "Thunderstorm With Hail", "99-day": "雷雨伴隨冰雹",
"99-night": "Thunderstorm With Hail" "99-night": "雷雨伴隨冰雹"
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "書籤",
"service": "Service" "service": "服務"
}, },
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "系統",
"updates": "Updates", "updates": "更新",
"update_available": "Update Available", "update_available": "有可用的更新",
"up_to_date": "Up to Date", "up_to_date": "已更新至最新",
"child_bridges": "Child Bridges", "child_bridges": "Child Bridges",
"child_bridges_status": "{{ok}}/{{total}}" "child_bridges_status": "{{ok}}/{{total}}"
}, },
"autobrr": { "autobrr": {
"approvedPushes": "Approved", "approvedPushes": "接受",
"rejectedPushes": "Rejected", "rejectedPushes": "拒絕",
"filters": "Filters", "filters": "篩選器",
"indexers": "Indexers" "indexers": "索引器"
}, },
"watchtower": { "watchtower": {
"containers_scanned": "Scanned", "containers_scanned": "已掃描",
"containers_updated": "Updated", "containers_updated": "已更新",
"containers_failed": "Failed" "containers_failed": "失敗"
}, },
"tubearchivist": { "tubearchivist": {
"downloads": "Queue", "downloads": "佇列",
"videos": "Videos", "videos": "影片",
"channels": "Channels", "channels": "頻道",
"playlists": "Playlists" "playlists": "播放清單"
}, },
"truenas": { "truenas": {
"load": "System Load", "load": "系統負載",
"uptime": "Uptime", "uptime": "運行時間",
"alerts": "Alerts", "alerts": "警示",
"time": "{{value, number(style: unit; unitDisplay: long;)}}" "time": "{{value, number(style: unit; unitDisplay: long;)}}"
}, },
"navidrome": { "navidrome": {
"nothing_streaming": "No Active Streams", "nothing_streaming": "無播放活動",
"please_wait": "Please Wait" "please_wait": "請稍後"
}, },
"pyload": { "pyload": {
"speed": "Speed", "speed": "速度",
"active": "Active", "active": "運行中",
"queue": "Queue", "queue": "佇列",
"total": "Total" "total": "全部"
}, },
"gluetun": { "gluetun": {
"public_ip": "Public IP", "public_ip": "公用IP",
"region": "Region", "region": "地區",
"country": "Country" "country": "國家"
}, },
"hdhomerun": { "hdhomerun": {
"channels": "Channels", "channels": "頻道",
"hd": "HD" "hd": "高畫質"
}, },
"ping": { "ping": {
"error": "Error", "error": "錯誤",
"ping": "Ping" "ping": "Ping"
}, },
"scrutiny": { "scrutiny": {
"passed": "Passed", "passed": "通過",
"failed": "Failed", "failed": "失敗",
"unknown": "Unknown" "unknown": "未知的"
}, },
"paperlessngx": { "paperlessngx": {
"inbox": "Inbox", "inbox": "收件箱",
"total": "Total" "total": "全部"
}, },
"deluge": { "deluge": {
"download": "Download", "download": "下載",
"upload": "Upload", "upload": "上傳",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
}, },
"flood": { "flood": {
"download": "Download", "download": "下載",
"upload": "Upload", "upload": "上傳",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
}, },
"tdarr": { "tdarr": {
"queue": "Queue", "queue": "佇列",
"processed": "Processed", "processed": "已處理",
"errored": "Errored", "errored": "發生錯誤",
"saved": "Saved" "saved": "已儲存"
}, },
"miniflux": { "miniflux": {
"read": "Read", "read": "已讀",
"unread": "Unread" "unread": "未讀"
}, },
"nextdns": { "nextdns": {
"wait": "Please Wait", "wait": "請稍後",
"no_devices": "No Device Data Received" "no_devices": "未收到裝置資料"
}, },
"common": { "common": {
"bibyterate": "{{value, rate(bits: false; binary: true)}}", "bibyterate": "{{value, rate(bits: false; binary: true)}}",
"bibitrate": "{{value, rate(bits: true; binary: true)}}" "bibitrate": "{{value, rate(bits: true; binary: true)}}"
}, },
"omada": { "omada": {
"connectedAp": "Connected APs", "connectedAp": "已連接的存取點",
"activeUser": "Active devices", "activeUser": "在線裝置",
"alerts": "Alerts", "alerts": "警示",
"connectedGateway": "Connected gateways", "connectedGateway": "已連接的閘道",
"connectedSwitches": "Connected switches" "connectedSwitches": "已連接的交換器"
}, },
"downloadstation": { "downloadstation": {
"download": "Download", "download": "下載",
"upload": "Upload", "upload": "上傳",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
}, },
"mikrotik": { "mikrotik": {
"cpuLoad": "CPU Load", "cpuLoad": "CPU負載",
"memoryUsed": "Memory Used", "memoryUsed": "已使用的記憶體",
"uptime": "Uptime", "uptime": "運行時間",
"numberOfLeases": "Leases" "numberOfLeases": "租約"
}, },
"xteve": { "xteve": {
"streams_all": "All Streams", "streams_all": "所有播放活動",
"streams_active": "Active Streams", "streams_active": "正在播放",
"streams_xepg": "XEPG Channels" "streams_xepg": "XEPG頻道"
}, },
"opnsense": { "opnsense": {
"cpu": "CPU Load", "cpu": "CPU負載",
"memory": "Active Memory", "memory": "Active Memory",
"wanUpload": "WAN Upload", "wanUpload": "WAN上傳",
"wanDownload": "WAN Download" "wanDownload": "WAN下載"
},
"moonraker": {
"printer_state": "Printer State",
"print_status": "Print Status",
"print_progress": "Progress",
"layers": "Layers"
} }
} }

View File

@ -19,7 +19,7 @@ export default function Item({ bookmark }) {
<div className="flex-shrink-0 flex items-center justify-center w-11 bg-theme-500/10 dark:bg-theme-900/50 text-theme-700 hover:text-theme-700 dark:text-theme-200 text-sm font-medium rounded-l-md"> <div className="flex-shrink-0 flex items-center justify-center w-11 bg-theme-500/10 dark:bg-theme-900/50 text-theme-700 hover:text-theme-700 dark:text-theme-200 text-sm font-medium rounded-l-md">
{bookmark.icon && {bookmark.icon &&
<div className="flex-shrink-0 w-5 h-5"> <div className="flex-shrink-0 w-5 h-5">
<ResolvedIcon icon={bookmark.icon} /> <ResolvedIcon icon={bookmark.icon} alt={bookmark.abbr} />
</div> </div>
} }
{!bookmark.icon && bookmark.abbr} {!bookmark.icon && bookmark.abbr}

View File

@ -1,9 +1,9 @@
import Image from "next/future/image"; import Image from "next/future/image";
export default function ResolvedIcon({ icon, width = 32, height = 32 }) { export default function ResolvedIcon({ icon, width = 32, height = 32, alt = "logo" }) {
// direct or relative URLs // direct or relative URLs
if (icon.startsWith("http") || icon.startsWith("/")) { if (icon.startsWith("http") || icon.startsWith("/")) {
return <Image src={`${icon}`} width={width} height={height} alt="logo" />; return <Image src={`${icon}`} width={width} height={height} alt={alt} />;
} }
// mdi- prefixed, material design icons // mdi- prefixed, material design icons
@ -31,7 +31,7 @@ export default function ResolvedIcon({ icon, width = 32, height = 32 }) {
src={`https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/${iconName}.png`} src={`https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/${iconName}.png`}
width={width} width={width}
height={height} height={height}
alt="logo" alt={alt}
/> />
); );
} }

View File

@ -99,7 +99,7 @@ function Index({ initialSettings, fallback }) {
localStorage.setItem("hash", hashData.hash); localStorage.setItem("hash", hashData.hash);
} }
if (previousHash && previousHash !== hashData.hash) { if (!initialSettings.isValid || (previousHash && previousHash !== hashData.hash)) {
setStale(true); setStale(true);
localStorage.setItem("hash", hashData.hash); localStorage.setItem("hash", hashData.hash);
@ -111,7 +111,7 @@ function Index({ initialSettings, fallback }) {
} }
} }
} }
}, [hashData]); }, [hashData, initialSettings]);
if (stale) { if (stale) {
return ( return (

View File

@ -1,6 +1,6 @@
/* eslint-disable no-console */ /* eslint-disable no-console */
import { join } from "path"; import { join } from "path";
import { existsSync, copyFile, readFileSync } from "fs"; import { existsSync, copyFile, readFileSync, statSync } from "fs";
import yaml from "js-yaml"; import yaml from "js-yaml";
@ -32,5 +32,18 @@ export function getSettings() {
const settingsYaml = join(process.cwd(), "config", "settings.yaml"); const settingsYaml = join(process.cwd(), "config", "settings.yaml");
const fileContents = readFileSync(settingsYaml, "utf8"); const fileContents = readFileSync(settingsYaml, "utf8");
return yaml.load(fileContents) ?? {};
let stats;
try {
stats = statSync(settingsYaml);
} catch (e) {
stats = {};
}
const yamlLoaded = yaml.load(fileContents) ?? {};
return {
...yamlLoaded,
isValid: fileContents !== "-\n" && stats.size !== 2 // see https://github.com/benphelps/homepage/pull/609
};
} }

View File

@ -30,6 +30,8 @@ export default async function credentialedProxyHandler(req, res, map) {
headers["X-gotify-Key"] = `${widget.key}`; headers["X-gotify-Key"] = `${widget.key}`;
} else if (widget.type === "authentik") { } else if (widget.type === "authentik") {
headers.Authorization = `Bearer ${widget.key}`; headers.Authorization = `Bearer ${widget.key}`;
} else if (widget.type === "truenas") {
headers.Authorization = `Bearer ${widget.key}`;
} else if (widget.type === "proxmox") { } else if (widget.type === "proxmox") {
headers.Authorization = `PVEAPIToken=${widget.username}=${widget.password}`; headers.Authorization = `PVEAPIToken=${widget.username}=${widget.password}`;
} else if (widget.type === "autobrr") { } else if (widget.type === "autobrr") {

View File

@ -4,8 +4,8 @@ import { formatProxyUrl } from "./api-helpers";
export default function useWidgetAPI(widget, ...options) { export default function useWidgetAPI(widget, ...options) {
const config = {}; const config = {};
if (options?.refreshInterval) { if (options && options[1]?.refreshInterval) {
config.refreshInterval = options.refreshInterval; config.refreshInterval = options[1].refreshInterval;
} }
const { data, error } = useSWR(formatProxyUrl(widget, ...options), config); const { data, error } = useSWR(formatProxyUrl(widget, ...options), config);
// make the data error the top-level error // make the data error the top-level error

View File

@ -23,6 +23,7 @@ const components = {
mastodon: dynamic(() => import("./mastodon/component")), mastodon: dynamic(() => import("./mastodon/component")),
miniflux: dynamic(() => import("./miniflux/component")), miniflux: dynamic(() => import("./miniflux/component")),
mikrotik: dynamic(() => import("./mikrotik/component")), mikrotik: dynamic(() => import("./mikrotik/component")),
moonraker: dynamic(() => import("./moonraker/component")),
navidrome: dynamic(() => import("./navidrome/component")), navidrome: dynamic(() => import("./navidrome/component")),
nextdns: dynamic(() => import("./nextdns/component")), nextdns: dynamic(() => import("./nextdns/component")),
npm: dynamic(() => import("./npm/component")), npm: dynamic(() => import("./npm/component")),

View File

@ -0,0 +1,51 @@
import { useTranslation } from "next-i18next";
import Container from "components/services/widget/container";
import Block from "components/services/widget/block";
import useWidgetAPI from "utils/proxy/use-widget-api";
export default function Component({ service }) {
const { t } = useTranslation();
const { widget } = service;
const { data: printStats, error: printStatsError } = useWidgetAPI(widget, "print_stats");
const { data: displayStatus, error: displayStatsError } = useWidgetAPI(widget, "display_status");
const { data: webHooks, error: webHooksError } = useWidgetAPI(widget, "webhooks");
if (printStatsError || displayStatsError || webHooksError) {
const finalError = printStatsError ?? displayStatsError ?? webHooksError;
return <Container error={finalError} />;
}
if (!printStats || !displayStatus || !webHooks) {
return (
<Container service={service}>
<Block label="moonraker.printer_state" />
</Container>
);
}
if (webHooks.result.status.webhooks.state === "shutdown") {
return (
<Container service={service}>
<Block label="moonraker.printer_state" value={webHooks.result.status.webhooks.state} />
</Container>
);
}
let currentLayer = "-";
let totalLayer = "-";
if (printStats.result.status.print_stats.info.total_layer !== null) {
currentLayer = printStats.result.status.print_stats.info.current_layer;
totalLayer = printStats.result.status.print_stats.info.total_layer;
}
return (
<Container service={service}>
<Block label="moonraker.layers" value={`${currentLayer} / ${totalLayer}`} />
<Block label="moonraker.print_progress" value={t("common.percent", { value: (displayStatus.result.status.display_status.progress * 100) })} />
<Block label="moonraker.print_status" value={printStats.result.status.print_stats.state} />
</Container>
);
}

View File

@ -0,0 +1,20 @@
import genericProxyHandler from "utils/proxy/handlers/generic";
const widget = {
api: "{url}/printer/objects/query?{endpoint}",
proxyHandler: genericProxyHandler,
mappings: {
print_stats: {
endpoint: "print_stats",
},
display_status: {
endpoint: "display_status",
},
webhooks: {
endpoint: "webhooks",
},
},
};
export default widget;

View File

@ -1,9 +1,31 @@
import { jsonArrayFilter } from "utils/proxy/api-helpers"; import { jsonArrayFilter } from "utils/proxy/api-helpers";
import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
import genericProxyHandler from "utils/proxy/handlers/generic"; import genericProxyHandler from "utils/proxy/handlers/generic";
import getServiceWidget from "utils/config/service-helpers";
const widget = { const widget = {
api: "{url}/api/v2.0/{endpoint}", api: "{url}/api/v2.0/{endpoint}",
proxyHandler: genericProxyHandler, proxyHandler: async (req, res, map) => { // choose proxy handler based on widget settings
const { group, service } = req.query;
if (group && service) {
const widgetOpts = await getServiceWidget(group, service);
let handler;
if (widgetOpts.username && widgetOpts.password) {
handler = genericProxyHandler;
} else if (widgetOpts.key) {
handler = credentialedProxyHandler;
}
if (handler) {
return handler(req, res, map);
}
return res.status(500).json({ error: "Username / password or API key required" });
}
return res.status(500).json({ error: "Error parsing widget request" });
},
mappings: { mappings: {
alerts: { alerts: {

View File

@ -18,6 +18,7 @@ import lidarr from "./lidarr/widget";
import mastodon from "./mastodon/widget"; import mastodon from "./mastodon/widget";
import miniflux from "./miniflux/widget"; import miniflux from "./miniflux/widget";
import mikrotik from "./mikrotik/widget"; import mikrotik from "./mikrotik/widget";
import moonraker from "./moonraker/widget";
import navidrome from "./navidrome/widget"; import navidrome from "./navidrome/widget";
import nextdns from "./nextdns/widget"; import nextdns from "./nextdns/widget";
import npm from "./npm/widget"; import npm from "./npm/widget";
@ -75,6 +76,7 @@ const widgets = {
mastodon, mastodon,
miniflux, miniflux,
mikrotik, mikrotik,
moonraker,
navidrome, navidrome,
nextdns, nextdns,
npm, npm,