diff --git a/.dockerignore b/.dockerignore index edbf8525..698137cb 100644 --- a/.dockerignore +++ b/.dockerignore @@ -16,11 +16,11 @@ **/compose* **/Dockerfile* **/node_modules +!.next/standalone/node_modules **/npm-debug.log **/obj **/secrets.dev.yaml **/values.dev.yaml -**/.next README.md config/ k3d/ diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index f3c90cf3..7edb1b10 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -2,8 +2,8 @@ name: Crowdin Action on: workflow_dispatch: - schedule: - - cron: '2 */12 * * *' + # schedule: + # - cron: '2 */12 * * *' push: paths: [ '/public/locales/en/**', diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index c7d36f33..855f7af3 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -1,20 +1,16 @@ -name: Docker - -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. +name: Docker CI on: - schedule: - - cron: '20 0 * * *' + # schedule: + # - cron: '20 0 * * *' push: branches: - main - feature/** - dev + - homepage-plus # Publish semver tags as releases. - tags: [ 'v*.*.*' ] + tags: [ 'v*.*.*-plus' ] paths-ignore: - 'docs/**' - 'mkdocs.yml' @@ -24,91 +20,58 @@ on: - 'docs/**' - 'mkdocs.yml' merge_group: + workflow_dispatch: env: - # github.repository as / IMAGE_NAME: ${{ github.repository }} - jobs: pre-commit: name: Linting Checks runs-on: ubuntu-22.04 steps: - - - name: Checkout repository + - name: Checkout repository uses: actions/checkout@v4 - - - name: Install python + + - name: Install python uses: actions/setup-python@v5 with: python-version: 3.x - - - name: Check files + + - name: Check files uses: pre-commit/action@v3.0.1 - - - name: Install pnpm + + - name: Install pnpm uses: pnpm/action-setup@v4 with: version: 10 run_install: false - - - name: Install Node.js + + - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 20 cache: 'pnpm' - - - name: Install dependencies + + - name: Install dependencies run: pnpm install - - - name: Lint frontend + + - name: Lint frontend run: pnpm run lint build: name: Docker Build & Push - if: github.repository == 'gethomepage/homepage' - runs-on: self-hosted + runs-on: ubuntu-latest needs: - pre-commit permissions: contents: read packages: write - # This is used to complete the identity challenge - # with sigstore/fulcio when running outside of PRs. - id-token: write steps: - name: Checkout repository uses: actions/checkout@v4 - # Login to Docker Registry - # https://github.com/docker/login-action - - name: Log into registry ${{ env.REGISTRY }} - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - name: Login to Docker Hub - if: github.event_name != 'pull_request' - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} - - # Setup QEMU - # https://github.com/marketplace/actions/docker-setup-buildx#with-qemu - - name: Setup QEMU - uses: docker/setup-qemu-action@v3.6.0 - - # Workaround: https://github.com/docker/build-push-action/issues/461 - - name: Setup Docker buildx - uses: docker/setup-buildx-action@v3 - - # Extract metadata (tags, labels) for Docker - # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta uses: docker/metadata-action@v5 @@ -116,11 +79,69 @@ jobs: images: | ${{ env.IMAGE_NAME }} ghcr.io/${{ env.IMAGE_NAME }} + tags: | + # Default tags + type=schedule,pattern=nightly + type=ref,event=branch + type=ref,event=tag + # Versioning tags + type=semver,pattern=v{{version}} + type=semver,pattern=v{{major}}.{{minor}} + type=semver,pattern=v{{major}} flavor: | latest=auto - # Build and push Docker image with Buildx (don't push on PR) - # https://github.com/docker/build-push-action + - name: Next.js build cache + uses: actions/cache@v4 + with: + path: .next/cache + key: nextjs-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ hashFiles('**/*.js', '**/*.jsx') }} + restore-keys: | + nextjs-${{ runner.os }}-${{ hashFiles('pnpm-lock.yaml') }} + + - name: Install pnpm + uses: pnpm/action-setup@v4 + with: + version: 10 + run_install: false + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'pnpm' + + - name: Install dependencies + run: pnpm install + + - name: Build app + run: | + NEXT_PUBLIC_BUILDTIME="${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }}" \ + NEXT_PUBLIC_VERSION="${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }}" \ + NEXT_PUBLIC_REVISION="${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }}" \ + pnpm run build + + - name: Log into registry ${{ env.REGISTRY }} + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to Docker Hub + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Setup QEMU + uses: docker/setup-qemu-action@v3.6.0 + + - name: Setup Docker buildx + uses: docker/setup-buildx-action@v3 + - name: Build and push Docker image id: build-and-push uses: docker/build-push-action@v6 @@ -130,18 +151,15 @@ jobs: tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} build-args: | + CI=true BUILDTIME=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.created'] }} VERSION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.version'] }} REVISION=${{ fromJSON(steps.meta.outputs.json).labels['org.opencontainers.image.revision'] }} - # https://github.com/docker/setup-qemu-action#about - # platforms: linux/amd64,linux/arm64,linux/riscv64,linux/ppc64le,linux/s390x,linux/386,linux/mips64le,linux/mips64,linux/arm/v7,linux/arm/v6 platforms: linux/amd64,linux/arm64 cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache-new,mode=max - # Temp fix - # https://github.com/docker/build-push-action/issues/252 - # https://github.com/moby/buildkit/issues/1896 + # https://github.com/docker/build-push-action/issues/252 / https://github.com/moby/buildkit/issues/1896 - name: Move cache run: | rm -rf /tmp/.buildx-cache diff --git a/.github/workflows/docs-publish.yml b/.github/workflows/docs-publish.yml index def1ee1e..5479e492 100644 --- a/.github/workflows/docs-publish.yml +++ b/.github/workflows/docs-publish.yml @@ -55,7 +55,7 @@ jobs: run: MKINSIDERS=false mkdocs build deploy: name: Build & Deploy - if: github.repository == 'gethomepage/homepage' && github.event_name != 'pull_request' + if: github.repository == 'gethomepage/homepage' && github.event_name != 'pull_request' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest needs: - pre-commit diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6cc46b47..0b4f5624 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,11 +9,14 @@ repos: - id: check-yaml exclude: "(^mkdocs\\.yml$)" - id: check-added-large-files -- repo: https://github.com/pre-commit/mirrors-prettier - rev: 'v3.0.3' +- repo: https://github.com/rbubley/mirrors-prettier + rev: 'v3.3.3' hooks: - id: prettier types_or: - javascript - markdown - jsx + additional_dependencies: + - prettier@3.3.3 + - 'prettier-plugin-organize-imports@4.1.0' diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 0967ef42..00000000 --- a/.prettierrc +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 00000000..b48ef007 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,5 @@ +const config = { + plugins: [require("prettier-plugin-organize-imports")], +}; + +module.exports = config; diff --git a/Dockerfile b/Dockerfile index 3c87c46f..76008113 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,66 +1,63 @@ -# Install dependencies only when needed -FROM docker.io/node:22-alpine AS deps - -WORKDIR /app - -COPY --link package.json pnpm-lock.yaml* ./ - -SHELL ["/bin/ash", "-xeo", "pipefail", "-c"] -RUN apk add --no-cache libc6-compat \ - && apk add --no-cache --virtual .gyp python3 make g++ \ - && npm install -g pnpm - -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 install -r --offline - -# Rebuild the source code only when needed -FROM docker.io/node:22-alpine AS builder +# ========================= +# Builder Stage +# ========================= +FROM node:22-slim AS builder WORKDIR /app +# Setup RUN mkdir config +COPY . . +ARG CI ARG BUILDTIME ARG VERSION ARG REVISION +ENV CI=$CI -COPY --link --from=deps /app/node_modules ./node_modules/ -COPY . . +# Install and build only outside CI +RUN if [ "$CI" != "true" ]; then \ + corepack enable && corepack prepare pnpm@latest --activate && \ + pnpm install --frozen-lockfile --prefer-offline && \ + NEXT_TELEMETRY_DISABLED=1 \ + NEXT_PUBLIC_BUILDTIME=$BUILDTIME \ + NEXT_PUBLIC_VERSION=$VERSION \ + NEXT_PUBLIC_REVISION=$REVISION \ + pnpm run build; \ + else \ + echo "✅ Using prebuilt app from CI context"; \ + fi -SHELL ["/bin/ash", "-xeo", "pipefail", "-c"] -RUN npm install -g pnpm \ - && pnpm run telemetry \ - && NEXT_PUBLIC_BUILDTIME=$BUILDTIME NEXT_PUBLIC_VERSION=$VERSION NEXT_PUBLIC_REVISION=$REVISION pnpm run build - -# Production image, copy all the files and run next -FROM docker.io/node:22-alpine AS runner -LABEL org.opencontainers.image.title "Homepage" -LABEL org.opencontainers.image.description "A self-hosted services landing page, with docker and service integrations." -LABEL org.opencontainers.image.url="https://github.com/gethomepage/homepage" +# ========================= +# Runtime Stage +# ========================= +FROM node:22-alpine AS runner +LABEL org.opencontainers.image.title="Homepage" +LABEL org.opencontainers.image.description="A self-hosted services landing page, with docker and service integrations." +LABEL org.opencontainers.image.url="https://github.com/di0ik/homepage-plus" LABEL org.opencontainers.image.documentation='https://github.com/gethomepage/homepage/wiki' -LABEL org.opencontainers.image.source='https://github.com/gethomepage/homepage' +LABEL org.opencontainers.image.source='https://github.com/di0ik/homepage-plus' LABEL org.opencontainers.image.licenses='Apache-2.0' -ENV NODE_ENV=production - +# Setup WORKDIR /app -# Copy files from context (this allows the files to copy before the builder stage is done). -COPY --link --chown=1000:1000 package.json next.config.js ./ +# Copy some files from context COPY --link --chown=1000:1000 /public ./public/ - -# Copy files from builder -COPY --link --from=builder --chown=1000:1000 /app/.next/standalone ./ -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 +# Copy only necessary files from the build stage +COPY --link --from=builder --chown=1000:1000 /app/.next/standalone/ ./ +COPY --link --from=builder --chown=1000:1000 /app/.next/static/ ./.next/static +RUN apk add --no-cache su-exec iputils-ping + +ENV NODE_ENV=production +ENV HOSTNAME=0.0.0.0 ENV PORT=3000 EXPOSE $PORT 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 http://127.0.0.1:$PORT/api/healthcheck || exit 1 ENTRYPOINT ["docker-entrypoint.sh"] CMD ["node", "server.js"] diff --git a/README.md b/README.md index fff2dfa4..090973bd 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ services: image: ghcr.io/gethomepage/homepage:latest container_name: homepage environment: - HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port + HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts PUID: 1000 # optional, your user id PGID: 1000 # optional, your group id ports: diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index c2858808..9890fbee 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -15,7 +15,7 @@ export HOMEPAGE_BUILDTIME=$(date +%s) # 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 +[ "$(id -u)" == "0" ] && [ "${PUID}" != "0" ] && chown -R ${PUID}:${PGID} /app/config /app/public # Drop privileges (when asked to) if root, otherwise run as current user if [ "$(id -u)" == "0" ] && [ "${PUID}" != "0" ]; then diff --git a/docs/assets/custom.css b/docs/assets/custom.css deleted file mode 100644 index f959128e..00000000 --- a/docs/assets/custom.css +++ /dev/null @@ -1,3 +0,0 @@ -.md-typeset[data-page-id="landing"] .md-header-anchor { - display: none; -} diff --git a/docs/configs/kubernetes.md b/docs/configs/kubernetes.md index 718095ef..49158e6b 100644 --- a/docs/configs/kubernetes.md +++ b/docs/configs/kubernetes.md @@ -25,13 +25,13 @@ To configure Kubernetes gateway-api, ingress or ingressRoute service discovery, Example settings: ```yaml -ingress: true # enable ingress only +ingress: true # default, enable ingress only ``` or ```yaml -ingress: true # enable ingress +ingress: true # default, enable ingress traefik: true # enable traefik ingressRoute gateway: true # enable gateway-api ``` diff --git a/docs/configs/settings.md b/docs/configs/settings.md index 93aa7f8f..513597b6 100644 --- a/docs/configs/settings.md +++ b/docs/configs/settings.md @@ -78,7 +78,7 @@ background: You can apply a blur filter to the service & bookmark cards. Note this option is incompatible with the background blur, saturate and brightness filters. ```yaml -cardBlur: sm # sm, "", md, etc... see https://tailwindcss.com/docs/backdrop-blur +cardBlur: xs # xs, md, etc... see https://tailwindcss.com/docs/backdrop-blur ``` ## Favicon @@ -254,15 +254,29 @@ layout: columns: 4 ``` -### Five Columns +### Full Width -You can add a fifth column to services (when `style: columns` which is default) by adding: +You can make homepage take up the entire window width by adding: ```yaml -fiveColumns: true +fullWidth: true ``` -By default homepage will max out at 4 columns for services with `columns` style +### Maximum Group Columns + +You can set the maximum number of columns of groups on larger screen sizes (note this is only for groups with the default `style: columns`, not groups with `stle: row`) by adding: + +```yaml +maxGroupColumns: 8 # default is 4 for services, 6 for bookmarks, max 8 +``` + +By default homepage will max out at 4 columns for services and 6 for bookmarks, thus the minimum for this setting is _5_. Of course, if you're setting this to higher numbers, you may want to consider enabling the [fullWidth](#full-width) option as well. + +If you want to set the maximum columns for bookmark groups separately, you can do so by adding: + +```yaml +maxBookmarkGroupColumns: 6 # default is 6, max 8 +``` ### Collapsible sections @@ -542,3 +556,42 @@ or per service widget (`services.yaml`) with: ``` If either value is set to true, the error message will be hidden. + +## Identity Based Visibiltiy + +Basic user identity integration is implemeted via an `identity` section. An identity provider can be configured using the `provider` section with the given type. Currently the only provider supported is `proxy`, where the users identification and group membership are passed via HTTP Request headers (in plaintext). The expectation is that the application will be accessed only via an authenticating proxy (i.e traefik or nginx). + +The group and user headers are both configurable like so: + +```yaml +identity: + provider: + type: proxy + groupHeader: "X-group-header" + userHeader: "X-user-header" +``` + +Identity based visibility can be configured on the service, bookmark, and widget level using the `allowUsers` and `allowGroups` list. The default is to allow all users and groups. + +```yaml +- Example Servie: + allowGroups: + - Group1 + - Group2 + - Group3 + allowUsers: + - User1 + - User2 + - User3 +``` + +Identity visibility for groups can be set in the `groups` under `identity`. In general the `groups` tag follows the format of the `layout` section. For example: + +```yaml +identity: + groups: + - My Service Group: + allowGroups: ["Group1", "Group2"] + - My Other Group: + allowGroups: ["Group1"] +``` diff --git a/docs/installation/docker.md b/docs/installation/docker.md index f2498fab..6d9148dd 100644 --- a/docs/installation/docker.md +++ b/docs/installation/docker.md @@ -16,7 +16,7 @@ services: - /path/to/config:/app/config # Make sure your local config directory exists - /var/run/docker.sock:/var/run/docker.sock # (optional) For docker integrations environment: - HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port + HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts ``` ### Running as non-root @@ -38,7 +38,7 @@ services: - /path/to/config:/app/config # Make sure your local config directory exists - /var/run/docker.sock:/var/run/docker.sock # (optional) For docker integrations, see alternative methods environment: - HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port + HOMEPAGE_ALLOWED_HOSTS: gethomepage.dev # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts PUID: $PUID PGID: $PGID ``` diff --git a/docs/installation/index.md b/docs/installation/index.md index 0037b61e..f082845b 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -13,20 +13,28 @@ You have a few options for deploying homepage, depending on your needs. We offer
-:simple-docker: [  Install on Docker :octicons-arrow-right-24:](docker.md) +[:simple-docker:   Install on Docker :octicons-arrow-right-24:](docker.md) { .card } -:simple-kubernetes: [  Install on Kubernetes :octicons-arrow-right-24:](k8s.md) +[:simple-kubernetes:   Install on Kubernetes :octicons-arrow-right-24:](k8s.md) { .card } -:simple-unraid: [  Install on UNRAID :octicons-arrow-right-24:](unraid.md) +[:simple-unraid:   Install on UNRAID :octicons-arrow-right-24:](unraid.md) { .card } -:simple-nextdotjs: [  Building from source :octicons-arrow-right-24:](source.md) +[:simple-nextdotjs:   Building from source :octicons-arrow-right-24:](source.md) { .card }
### `HOMEPAGE_ALLOWED_HOSTS` -As of v1.0 there is one required environment variable when deploying via a public URL, HOMEPAGE_ALLOWED_HOSTS. This is a comma separated list of allowed hosts (sometimes with the port) that can access your homepage. See the [docker](docker.md) and [source](source.md) installation pages for examples. +As of v1.0 there is one required environment variable to access homepage via a URL other than `localhost`, HOMEPAGE_ALLOWED_HOSTS. The setting helps prevent certain kinds of attacks when retrieving data from the homepage API proxy. + +The value is a comma-separated (no spaces) list of allowed hosts (sometimes with the port) that can host your homepage install. See the [docker](docker.md), [kubernetes](k8s.md) and [source](source.md) installation pages for more information about where / how to set the variable. + +`localhost:3000` and `127.0.0.1:3000` are always included, but you can add a domain or IP address to this list to allow that host such as `HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev,192.168.1.2:1234`, etc. + +If you are seeing errors about host validation, check the homepage logs and ensure that the host exactly as output in the logs is in the `HOMEPAGE_ALLOWED_HOSTS` list. + +This can be disabled by setting `HOMEPAGE_ALLOWED_HOSTS` to `*` but this is not recommended. diff --git a/docs/installation/k8s.md b/docs/installation/k8s.md index cd9184ee..172b9b29 100644 --- a/docs/installation/k8s.md +++ b/docs/installation/k8s.md @@ -3,85 +3,6 @@ title: Kubernetes Installation description: Install on Kubernetes --- -## Install with Helm - -There is an [unofficial helm chart](https://github.com/jameswynn/helm-charts/tree/main/charts/homepage) that creates all the necessary manifests, including the service account and RBAC entities necessary for service discovery. - -```sh -helm repo add jameswynn https://jameswynn.github.io/helm-charts -helm install homepage jameswynn/homepage -f values.yaml -``` - -The helm chart allows for all the configurations to be inlined directly in your `values.yaml`: - -```yaml -config: - bookmarks: - - Developer: - - Github: - - abbr: GH - href: https://github.com/ - services: - - My First Group: - - My First Service: - href: http://localhost/ - description: Homepage is awesome - - - My Second Group: - - My Second Service: - href: http://localhost/ - description: Homepage is the best - - - My Third Group: - - My Third Service: - href: http://localhost/ - description: Homepage is 😎 - widgets: - # show the kubernetes widget, with the cluster summary and individual nodes - - kubernetes: - cluster: - show: true - cpu: true - memory: true - showLabel: true - label: "cluster" - nodes: - show: true - cpu: true - memory: true - showLabel: true - - search: - provider: duckduckgo - target: _blank - kubernetes: - mode: cluster - settings: - -# The service account is necessary to allow discovery of other services -serviceAccount: - create: true - name: homepage - -# This enables the service account to access the necessary resources -enableRbac: true - -ingress: - main: - enabled: true - annotations: - # Example annotations to add Homepage to your Homepage! - gethomepage.dev/enabled: "true" - gethomepage.dev/name: "Homepage" - gethomepage.dev/description: "Dynamically Detected Homepage" - gethomepage.dev/group: "Dynamic" - gethomepage.dev/icon: "homepage.png" - hosts: - - host: homepage.example.com - paths: - - path: / - pathType: Prefix -``` - ## Install with Kubernetes Manifests If you don't want to use the unofficial Helm chart, you can also create your own Kubernetes manifest(s) and apply them with `kubectl apply -f filename.yaml`. @@ -302,6 +223,9 @@ spec: - name: homepage image: "ghcr.io/gethomepage/homepage:latest" imagePullPolicy: Always + env: + - name: HOMEPAGE_ALLOWED_HOSTS + value: gethomepage.dev # required, may need port. See gethomepage.dev/installation/#homepage_allowed_hosts ports: - name: http containerPort: 3000 diff --git a/docs/installation/source.md b/docs/installation/source.md index f0f07140..fd0275a7 100644 --- a/docs/installation/source.md +++ b/docs/installation/source.md @@ -9,7 +9,13 @@ First, clone the repository: git clone https://github.com/gethomepage/homepage.git ``` -Then install dependencies and build the production bundle (I'm using pnpm here, you can use npm or yarn if you like): +If `pnpm` is not installed, install it: + +```bash +npm install -g pnpm +``` + +Then install dependencies and build the production bundle: ```bash pnpm install @@ -25,3 +31,5 @@ HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev:1234 pnpm start ``` When updating homepage versions you will need to re-build the static files i.e. repeat the process above. + +See [HOMEPAGE_ALLOWED_HOSTS](index.md#homepage_allowed_hosts) for more information on this environment variable. diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index eb1ddd25..7f299d2e 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -286,3 +286,13 @@ body[data-md-color-scheme="default"] { .md-tabs__link { transform: translateZ(0); } + +.grid.cards .card { + padding: 0; +} + +.grid.cards .card a { + display: block; + padding: 0.8rem; + text-decoration: none; +} diff --git a/docs/troubleshooting/index.md b/docs/troubleshooting/index.md index 1c72ba31..81550439 100644 --- a/docs/troubleshooting/index.md +++ b/docs/troubleshooting/index.md @@ -12,6 +12,7 @@ hide: - Check config/logs/homepage.log, on docker simply e.g. `docker logs homepage`. This may provide some insight into the reason for an error. - Check the browser error console, this can also sometimes provide useful information. - Consider setting the `ENV` variable `LOG_LEVEL` to `debug`. +- If certain widgets are failing when connecting to public APIs, consider [disabling IPv6](#disabling-ipv6). ## Service Widget Errors @@ -66,3 +67,17 @@ All service widgets work essentially the same, that is, homepage makes a proxied ## Missing custom icons If, after correctly adding and mapping your custom icons via the [Icons](../configs/services.md#icons) instructions, you are still unable to see your icons please try recreating your container. + +## Disabling IPv6 + +If you are having issues with certain widgets that are unable to reach public APIs (e.g. weather), in certain setups you may need to disable IPv6. You can set the environment variable `HOMEPAGE_PROXY_DISABLE_IPV6` to `true` to disable IPv6 for the homepage proxy. + +Alternatively, you can use the `sysctls` option in your docker-compose file to disable IPv6 for the homepage container completely: + +```yaml +services: + homepage: + ... + sysctls: + - net.ipv6.conf.all.disable_ipv6=1 +``` diff --git a/docs/widgets/services/customapi.md b/docs/widgets/services/customapi.md index 0deb8294..37a48fd8 100644 --- a/docs/widgets/services/customapi.md +++ b/docs/widgets/services/customapi.md @@ -19,27 +19,22 @@ widget: requestBody: # optional, can be string or object, see below display: # optional, default to block, see below mappings: - - field: key # needs to be YAML string or object + - field: key label: Field 1 format: text # optional - defaults to text - - field: # needs to be YAML string or object - path: - to: key2 + - field: path.to.key2 format: number # optional - defaults to text label: Field 2 - - field: # needs to be YAML string or object - path: - to: - another: key3 + - field: path.to.another.key3 label: Field 3 format: percent # optional - defaults to text - - field: key # needs to be YAML string or object + - field: key label: Field 4 format: date # optional - defaults to text locale: nl # optional dateStyle: long # optional - defaults to "long". Allowed values: `["full", "long", "medium", "short"]`. timeStyle: medium # optional - Allowed values: `["full", "long", "medium", "short"]`. - - field: key # needs to be YAML string or object + - field: key label: Field 5 format: relativeDate # optional - defaults to text locale: nl # optional @@ -49,9 +44,7 @@ widget: label: Field 6 format: text additionalField: # optional - field: - hourly: - time: other key + field: hourly.time.key color: theme # optional - defaults to "". Allowed values: `["theme", "adaptive", "black", "white"]`. format: date # optional - field: key @@ -103,9 +96,16 @@ mappings: label: Name - field: status # Alive label: Status - - field: - origin: name # Earth (C-137) + - field: origin.name # Earth (C-137) label: Origin + - field: locations.1.name # Citadel of Ricks + label: Location +``` + +Note that older versions of the widget accepted fields as a yaml object, which is still supported. E.g.: + +```yaml +mappings: - field: locations: 1: name # Citadel of Ricks @@ -138,7 +138,15 @@ You can manipulate data with the following tools `remap`, `scale`, `prefix` and prefix: "$" ``` -## List View +## Display Options + +The widget supports different display modes that can be set using the `display` property. + +### Block View (Default) + +The default display mode is `block`, which shows fields in a block format. + +### List View You can change the default block view to a list view by setting the `display` option to `list`. @@ -162,13 +170,54 @@ The list view can optionally display an additional field next to the primary fie - any: true # will map all other values to: Unknown additionalField: - field: - hourly: - time: key + field: hourly.time.key color: theme format: date ``` +### Dynamic List View + +To display a list of items from an array in the API response, set the `display` property to `dynamic-list` and configure the `mappings` object with the following properties: + +```yaml +widget: + type: customapi + url: https://example.com/api/servers + display: dynamic-list + mappings: + items: data # optional, the path to the array in the API response. Omit this option if the array is at the root level + name: id # required, field in each item to use as the item name (left side) + label: ip_address # required, field in each item to use as the item label (right side) + limit: 5 # optional, limit the number of items to display + format: text # optional - format of the label field + target: https://example.com/server/{id} # optional, makes items clickable with template support +``` + +This configuration would work with an API that returns a response like: + +```json +{ + "data": [ + { "id": "server1", "name": "Server 1", "ip_address": "192.168.0.1" }, + { "id": "server2", "name": "Server 2", "ip_address": "192.168.0.2" } + ] +} +``` + +The widget would display a list with two items: + +- "Server 1" on the left and "192.168.0.1" on the right, clickable to "https://example.com/server/server1" +- "Server 2" on the left and "192.168.0.2" on the right, clickable to "https://example.com/server/server2" + +For nested fields in the items, you can use dot notation: + +```yaml +mappings: + items: data.results.servers + name: details.id + label: details.name +``` + ## Custom Headers Pass custom headers using the `headers` option, for example: diff --git a/docs/widgets/services/gitea.md b/docs/widgets/services/gitea.md index 140c4ee7..eb47849d 100644 --- a/docs/widgets/services/gitea.md +++ b/docs/widgets/services/gitea.md @@ -7,7 +7,7 @@ Learn more about [Gitea](https://gitea.com). API token requires `notifications`, `repository` and `issue` permissions. See the [gitea documentation](https://docs.gitea.com/development/api-usage#generating-and-listing-api-tokens) for details on generating tokens. -Allowed fields: `["notifications", "issues", "pulls"]`. +Allowed fields: `["repositories", "notifications", "issues", "pulls"]`. ```yaml widget: diff --git a/docs/widgets/services/hoarder.md b/docs/widgets/services/hoarder.md deleted file mode 100644 index 3e8c82ad..00000000 --- a/docs/widgets/services/hoarder.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: Hoarder -description: Hoarder Widget Configuration ---- - -Learn more about [Hoarder](https://hoarder.app). - -Generate an API key for your user at `User Settings > API Keys`. - -Allowed fields: `["bookmarks", "favorites", "archived", "highlights", "lists", "tags"]` (maximum of 4). - -```yaml -widget: - type: hoarder - url: http[s]://hoarder.host.or.ip[:port] - key: hoarderapikey -``` diff --git a/docs/widgets/services/index.md b/docs/widgets/services/index.md index 15caadc2..80ff72ba 100644 --- a/docs/widgets/services/index.md +++ b/docs/widgets/services/index.md @@ -51,7 +51,7 @@ You can also find a list of all available service widgets in the sidebar navigat - [HDHomeRun](hdhomerun.md) - [Headscale](headscale.md) - [Healthchecks](healthchecks.md) -- [Hoarder](hoarder.md) +- [Karakeep](karakeep.md) - [Home Assistant](homeassistant.md) - [HomeBox](homebox.md) - [Homebridge](homebridge.md) @@ -117,6 +117,7 @@ You can also find a list of all available service widgets in the sidebar navigat - [ruTorrent](rutorrent.md) - [SABnzbd](sabnzbd.md) - [Scrutiny](scrutiny.md) +- [Slskd](slskd.md) - [Sonarr](sonarr.md) - [Speedtest Tracker](speedtest-tracker.md) - [Stash](stash.md) diff --git a/docs/widgets/services/karakeep.md b/docs/widgets/services/karakeep.md new file mode 100644 index 00000000..a2902315 --- /dev/null +++ b/docs/widgets/services/karakeep.md @@ -0,0 +1,17 @@ +--- +title: Karakeep +description: Karakeep Widget Configuration +--- + +Learn more about [Karakeep](https://karakeep.app) (formerly known as Hoarder). + +Generate an API key for your user at `User Settings > API Keys`. + +Allowed fields: `["bookmarks", "favorites", "archived", "highlights", "lists", "tags"]` (maximum of 4). + +```yaml +widget: + type: karakeep + url: http[s]://karakeep.host.or.ip[:port] + key: karakeep_api_key +``` diff --git a/docs/widgets/services/komga.md b/docs/widgets/services/komga.md index fc76127f..e71ae19a 100644 --- a/docs/widgets/services/komga.md +++ b/docs/widgets/services/komga.md @@ -20,4 +20,5 @@ widget: url: http://komga.host.or.ip:port username: username password: password + key: komgaapikey # optional ``` diff --git a/docs/widgets/services/slskd.md b/docs/widgets/services/slskd.md new file mode 100644 index 00000000..7afb0760 --- /dev/null +++ b/docs/widgets/services/slskd.md @@ -0,0 +1,25 @@ +--- +title: Slskd +description: Slskd Widget Configuration +--- + +Learn more about [Slskd](https://github.com/slskd/slskd). + +Generate an API key for slskd with `openssl rand -base64 48`. +Add it to your `path/to/config/slskd.yml` in `web > authentication > api_keys`: + +```yaml +homepage_widget: + key: + role: readonly + cidr: +``` + +Allowed fields: `["slskStatus", "updateStatus", "downloads", "uploads", "sharedFiles"]` (maximum of 4). + +```yaml +widget: + type: slskd + url: http[s]://slskd.host.or.ip[:5030] + key: generatedapikey +``` diff --git a/k3d/k3d-helm-values.yaml b/k3d/k3d-helm-values.yaml index 60b6fe38..13bb9229 100644 --- a/k3d/k3d-helm-values.yaml +++ b/k3d/k3d-helm-values.yaml @@ -46,6 +46,10 @@ config: docker: settings: +env: + - name: HOMEPAGE_ALLOWED_HOSTS + value: "homepage.k3d.localhost:8080" + serviceAccount: create: true name: homepage diff --git a/mkdocs.yml b/mkdocs.yml index 01a5295b..04b888c6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -4,9 +4,9 @@ site_name: Homepage site_url: https://gethomepage.dev/ # Repository -repo_name: gethomepage/homepage -repo_url: https://github.com/gethomepage/homepage -edit_uri: https://github.com/gethomepage/homepage/tree/main/docs/ +repo_name: di0ik/homepage-plus +repo_url: https://github.com/di0ik/homepage-plus +edit_uri: https://github.com/di0ik/homepage-plus/tree/main/docs/ nav: - "Home": @@ -74,7 +74,7 @@ nav: - widgets/services/hdhomerun.md - widgets/services/headscale.md - widgets/services/healthchecks.md - - widgets/services/hoarder.md + - widgets/services/karakeep.md - widgets/services/homeassistant.md - widgets/services/homebox.md - widgets/services/homebridge.md diff --git a/next-i18next.config.js b/next-i18next.config.js index a1b5c7b3..f6968dc3 100644 --- a/next-i18next.config.js +++ b/next-i18next.config.js @@ -131,8 +131,8 @@ module.exports = { ? BIBIT_UNITS : BIT_UNITS : options.binary - ? BIBYTE_UNITS - : BYTE_UNITS; + ? BIBYTE_UNITS + : BYTE_UNITS; if (value === 0) return `0 ${sizes[0]}/s`; diff --git a/package.json b/package.json index 065f97d4..9ac85840 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homepage", - "version": "1.0.1", + "version": "1.2.0", "private": true, "scripts": { "preinstall": "npx only-allow pnpm", @@ -19,13 +19,13 @@ "dockerode": "^4.0.4", "follow-redirects": "^1.15.9", "gamedig": "^5.2.0", - "i18next": "^21.10.0", + "i18next": "^24.2.3", "js-yaml": "^4.1.0", "json-rpc-2.0": "^1.7.0", "luxon": "^3.5.0", "memory-cache": "^0.2.0", - "minecraftstatuspinger": "^1.2.1", - "next": "^15.1.7", + "minecraftstatuspinger": "^1.2.2", + "next": "^15.2.4", "next-i18next": "^12.1.0", "ping": "^0.4.4", "pretty-bytes": "^6.1.1", @@ -36,7 +36,7 @@ "react-icons": "^5.4.0", "recharts": "^2.15.1", "rrule": "^2.8.1", - "swr": "^1.3.0", + "swr": "^2.3.3", "systeminformation": "^5.25.11", "tough-cookie": "^5.1.2", "urbackup-server-api": "^0.8.9", @@ -47,15 +47,16 @@ "@tailwindcss/forms": "^0.5.10", "@tailwindcss/postcss": "^4.0.9", "eslint": "^9.21.0", - "eslint-config-next": "^15.1.7", - "eslint-config-prettier": "^10.0.2", + "eslint-config-next": "^15.2.4", + "eslint-config-prettier": "^10.1.1", "eslint-plugin-import": "^2.31.0", "eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-prettier": "^5.2.3", "eslint-plugin-react": "^7.37.4", "eslint-plugin-react-hooks": "^5.1.0", - "postcss": "^8.5.2", + "postcss": "^8.5.3", "prettier": "^3.5.2", + "prettier-plugin-organize-imports": "^4.1.0", "tailwind-scrollbar": "^4.0.1", "tailwindcss": "^4.0.9", "typescript": "^5.7.3" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6100111b..170e380e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,8 +33,8 @@ importers: specifier: ^5.2.0 version: 5.2.0 i18next: - specifier: ^21.10.0 - version: 21.10.0 + specifier: ^24.2.3 + version: 24.2.3(typescript@5.7.3) js-yaml: specifier: ^4.1.0 version: 4.1.0 @@ -48,14 +48,14 @@ importers: specifier: ^0.2.0 version: 0.2.0 minecraftstatuspinger: - specifier: ^1.2.1 - version: 1.2.1 + specifier: ^1.2.2 + version: 1.2.2 next: - specifier: ^15.1.7 - version: 15.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: ^15.2.4 + version: 15.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) next-i18next: specifier: ^12.1.0 - version: 12.1.0(next@15.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 12.1.0(next@15.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) ping: specifier: ^0.4.4 version: 0.4.4 @@ -73,7 +73,7 @@ importers: version: 18.3.1(react@18.3.1) react-i18next: specifier: ^11.18.6 - version: 11.18.6(i18next@21.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 11.18.6(i18next@24.2.3(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-icons: specifier: ^5.4.0 version: 5.4.0(react@18.3.1) @@ -84,8 +84,8 @@ importers: specifier: ^2.8.1 version: 2.8.1 swr: - specifier: ^1.3.0 - version: 1.3.0(react@18.3.1) + specifier: ^2.3.3 + version: 2.3.3(react@18.3.1) systeminformation: specifier: ^5.25.11 version: 5.25.11 @@ -116,20 +116,20 @@ importers: specifier: ^9.21.0 version: 9.21.0(jiti@2.4.2) eslint-config-next: - specifier: ^15.1.7 - version: 15.1.7(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + specifier: ^15.2.4 + version: 15.2.4(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) eslint-config-prettier: - specifier: ^10.0.2 - version: 10.0.2(eslint@9.21.0(jiti@2.4.2)) + specifier: ^10.1.1 + version: 10.1.1(eslint@9.21.0(jiti@2.4.2)) eslint-plugin-import: specifier: ^2.31.0 - version: 2.31.0(@typescript-eslint/parser@8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.8.2)(eslint@9.21.0(jiti@2.4.2)) + version: 2.31.0(@typescript-eslint/parser@8.29.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.10.0)(eslint@9.21.0(jiti@2.4.2)) eslint-plugin-jsx-a11y: specifier: ^6.10.2 version: 6.10.2(eslint@9.21.0(jiti@2.4.2)) eslint-plugin-prettier: specifier: ^5.2.3 - version: 5.2.3(eslint-config-prettier@10.0.2(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2))(prettier@3.5.2) + version: 5.2.3(eslint-config-prettier@10.1.1(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2))(prettier@3.5.2) eslint-plugin-react: specifier: ^7.37.4 version: 7.37.4(eslint@9.21.0(jiti@2.4.2)) @@ -137,11 +137,14 @@ importers: specifier: ^5.1.0 version: 5.1.0(eslint@9.21.0(jiti@2.4.2)) postcss: - specifier: ^8.5.2 - version: 8.5.2 + specifier: ^8.5.3 + version: 8.5.3 prettier: specifier: ^3.5.2 version: 3.5.2 + prettier-plugin-organize-imports: + specifier: ^4.1.0 + version: 4.1.0(prettier@3.5.2)(typescript@5.7.3) tailwind-scrollbar: specifier: ^4.0.1 version: 4.0.1(react@18.3.1)(tailwindcss@4.0.9) @@ -162,6 +165,10 @@ packages: resolution: {integrity: sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==} engines: {node: '>=6.9.0'} + '@babel/runtime@7.27.0': + resolution: {integrity: sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==} + engines: {node: '>=6.9.0'} + '@balena/dockerignore@1.0.2': resolution: {integrity: sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==} @@ -172,8 +179,14 @@ packages: '@dabh/diagnostics@2.0.3': resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} - '@emnapi/runtime@1.3.1': - resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} + '@emnapi/core@1.4.0': + resolution: {integrity: sha512-H+N/FqT07NmLmt6OFFtDfwe8PNygprzBikrEMyQfgqSmT0vzE515Pz7R8izwB9q/zsH/MA64AKoul3sA6/CzVg==} + + '@emnapi/runtime@1.4.0': + resolution: {integrity: sha512-64WYIf4UYcdLnbKn/umDlNjQDSS8AgZrI/R9+x5ilkUVFxXcA1Ebl+gQLc/6mERA4407Xof0R7wEyEuj091CVw==} + + '@emnapi/wasi-threads@1.0.1': + resolution: {integrity: sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==} '@eslint-community/eslint-utils@4.4.1': resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} @@ -181,6 +194,12 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/eslint-utils@4.5.1': + resolution: {integrity: sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/regexpp@4.12.1': resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -376,56 +395,59 @@ packages: '@kubernetes/client-node@1.0.0': resolution: {integrity: sha512-a8NSvFDSHKFZ0sR1hbPSf8IDFNJwctEU5RodSCNiq/moRXWmrdmqhb1RRQzF+l+TSBaDgHw3YsYNxxE92STBzw==} - '@next/env@15.1.7': - resolution: {integrity: sha512-d9jnRrkuOH7Mhi+LHav2XW91HOgTAWHxjMPkXMGBc9B2b7614P7kjt8tAplRvJpbSt4nbO1lugcT/kAaWzjlLQ==} + '@napi-rs/wasm-runtime@0.2.8': + resolution: {integrity: sha512-OBlgKdX7gin7OIq4fadsjpg+cp2ZphvAIKucHsNfTdJiqdOmOEwQd/bHi0VwNrcw5xpBJyUw6cK/QilCqy1BSg==} - '@next/eslint-plugin-next@15.1.7': - resolution: {integrity: sha512-kRP7RjSxfTO13NE317ek3mSGzoZlI33nc/i5hs1KaWpK+egs85xg0DJ4p32QEiHnR0mVjuUfhRIun7awqfL7pQ==} + '@next/env@15.2.4': + resolution: {integrity: sha512-+SFtMgoiYP3WoSswuNmxJOCwi06TdWE733D+WPjpXIe4LXGULwEaofiiAy6kbS0+XjM5xF5n3lKuBwN2SnqD9g==} - '@next/swc-darwin-arm64@15.1.7': - resolution: {integrity: sha512-hPFwzPJDpA8FGj7IKV3Yf1web3oz2YsR8du4amKw8d+jAOHfYHYFpMkoF6vgSY4W6vB29RtZEklK9ayinGiCmQ==} + '@next/eslint-plugin-next@15.2.4': + resolution: {integrity: sha512-O8ScvKtnxkp8kL9TpJTTKnMqlkZnS+QxwoQnJwPGBxjBbzd6OVVPEJ5/pMNrktSyXQD/chEfzfFzYLM6JANOOQ==} + + '@next/swc-darwin-arm64@15.2.4': + resolution: {integrity: sha512-1AnMfs655ipJEDC/FHkSr0r3lXBgpqKo4K1kiwfUf3iE68rDFXZ1TtHdMvf7D0hMItgDZ7Vuq3JgNMbt/+3bYw==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@next/swc-darwin-x64@15.1.7': - resolution: {integrity: sha512-2qoas+fO3OQKkU0PBUfwTiw/EYpN+kdAx62cePRyY1LqKtP09Vp5UcUntfZYajop5fDFTjSxCHfZVRxzi+9FYQ==} + '@next/swc-darwin-x64@15.2.4': + resolution: {integrity: sha512-3qK2zb5EwCwxnO2HeO+TRqCubeI/NgCe+kL5dTJlPldV/uwCnUgC7VbEzgmxbfrkbjehL4H9BPztWOEtsoMwew==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@next/swc-linux-arm64-gnu@15.1.7': - resolution: {integrity: sha512-sKLLwDX709mPdzxMnRIXLIT9zaX2w0GUlkLYQnKGoXeWUhcvpCrK+yevcwCJPdTdxZEUA0mOXGLdPsGkudGdnA==} + '@next/swc-linux-arm64-gnu@15.2.4': + resolution: {integrity: sha512-HFN6GKUcrTWvem8AZN7tT95zPb0GUGv9v0d0iyuTb303vbXkkbHDp/DxufB04jNVD+IN9yHy7y/6Mqq0h0YVaQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-arm64-musl@15.1.7': - resolution: {integrity: sha512-zblK1OQbQWdC8fxdX4fpsHDw+VSpBPGEUX4PhSE9hkaWPrWoeIJn+baX53vbsbDRaDKd7bBNcXRovY1hEhFd7w==} + '@next/swc-linux-arm64-musl@15.2.4': + resolution: {integrity: sha512-Oioa0SORWLwi35/kVB8aCk5Uq+5/ZIumMK1kJV+jSdazFm2NzPDztsefzdmzzpx5oGCJ6FkUC7vkaUseNTStNA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@next/swc-linux-x64-gnu@15.1.7': - resolution: {integrity: sha512-GOzXutxuLvLHFDAPsMP2zDBMl1vfUHHpdNpFGhxu90jEzH6nNIgmtw/s1MDwpTOiM+MT5V8+I1hmVFeAUhkbgQ==} + '@next/swc-linux-x64-gnu@15.2.4': + resolution: {integrity: sha512-yb5WTRaHdkgOqFOZiu6rHV1fAEK0flVpaIN2HB6kxHVSy/dIajWbThS7qON3W9/SNOH2JWkVCyulgGYekMePuw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-linux-x64-musl@15.1.7': - resolution: {integrity: sha512-WrZ7jBhR7ATW1z5iEQ0ZJfE2twCNSXbpCSaAunF3BKcVeHFADSI/AW1y5Xt3DzTqPF1FzQlwQTewqetAABhZRQ==} + '@next/swc-linux-x64-musl@15.2.4': + resolution: {integrity: sha512-Dcdv/ix6srhkM25fgXiyOieFUkz+fOYkHlydWCtB0xMST6X9XYI3yPDKBZt1xuhOytONsIFJFB08xXYsxUwJLw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@next/swc-win32-arm64-msvc@15.1.7': - resolution: {integrity: sha512-LDnj1f3OVbou1BqvvXVqouJZKcwq++mV2F+oFHptToZtScIEnhNRJAhJzqAtTE2dB31qDYL45xJwrc+bLeKM2Q==} + '@next/swc-win32-arm64-msvc@15.2.4': + resolution: {integrity: sha512-dW0i7eukvDxtIhCYkMrZNQfNicPDExt2jPb9AZPpL7cfyUo7QSNl1DjsHjmmKp6qNAqUESyT8YFl/Aw91cNJJg==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@next/swc-win32-x64-msvc@15.1.7': - resolution: {integrity: sha512-dC01f1quuf97viOfW05/K8XYv2iuBgAxJZl7mbCKEjMgdQl5JjAKJ0D2qMKZCgPWDeFbFT0Q0nYWwytEW0DWTQ==} + '@next/swc-win32-x64-msvc@15.2.4': + resolution: {integrity: sha512-SbnWkJmkS7Xl3kre8SdMF6F/XDh1DTFEhp0jRTj/uB8iPKoU2bb2NDfcu+iifv1+mxQEd1g2vvSxcZbXSKyWiQ==} engines: {node: '>= 10'} cpu: [x64] os: [win32] @@ -487,8 +509,8 @@ packages: '@rtsao/scc@1.1.0': resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} - '@rushstack/eslint-patch@1.10.5': - resolution: {integrity: sha512-kkKUDVlII2DQiKy7UstOR1ErJP8kUKAQ4oa+SQtM0K+lPdmmjj0YnnxBgtTVYH7mUKtbsxeFC9y0AmK7Yb78/A==} + '@rushstack/eslint-patch@1.11.0': + resolution: {integrity: sha512-zxnHvoMQVqewTJr/W4pKjF0bMGiKJv1WX7bSrkl46Hg0QjESbzBROWK0Wg4RphzSOS5Jiy7eFimmM3UgMrMZbQ==} '@sindresorhus/is@5.6.0': resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} @@ -594,6 +616,9 @@ packages: '@tanstack/virtual-core@3.13.0': resolution: {integrity: sha512-NBKJP3OIdmZY3COJdWkSonr50FMVIi+aj5ZJ7hI/DTpEKg2RMfo/KvP8A3B/zOSpMgIe52B5E2yn7rryULzA6g==} + '@tybys/wasm-util@0.9.0': + resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} + '@types/d3-array@3.2.1': resolution: {integrity: sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==} @@ -663,53 +688,128 @@ packages: '@types/ws@8.5.14': resolution: {integrity: sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw==} - '@typescript-eslint/eslint-plugin@8.24.1': - resolution: {integrity: sha512-ll1StnKtBigWIGqvYDVuDmXJHVH4zLVot1yQ4fJtLpL7qacwkxJc1T0bptqw+miBQ/QfUbhl1TcQ4accW5KUyA==} + '@typescript-eslint/eslint-plugin@8.29.0': + resolution: {integrity: sha512-PAIpk/U7NIS6H7TEtN45SPGLQaHNgB7wSjsQV/8+KYokAb2T/gloOA/Bee2yd4/yKVhPKe5LlaUGhAZk5zmSaQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/parser@8.24.1': - resolution: {integrity: sha512-Tqoa05bu+t5s8CTZFaGpCH2ub3QeT9YDkXbPd3uQ4SfsLoh1/vv2GEYAioPoxCWJJNsenXlC88tRjwoHNts1oQ==} + '@typescript-eslint/parser@8.29.0': + resolution: {integrity: sha512-8C0+jlNJOwQso2GapCVWWfW/rzaq7Lbme+vGUFKE31djwNncIpgXD7Cd4weEsDdkoZDjH0lwwr3QDQFuyrMg9g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/scope-manager@8.24.1': - resolution: {integrity: sha512-OdQr6BNBzwRjNEXMQyaGyZzgg7wzjYKfX2ZBV3E04hUCBDv3GQCHiz9RpqdUIiVrMgJGkXm3tcEh4vFSHreS2Q==} + '@typescript-eslint/scope-manager@8.29.0': + resolution: {integrity: sha512-aO1PVsq7Gm+tcghabUpzEnVSFMCU4/nYIgC2GOatJcllvWfnhrgW0ZEbnTxm36QsikmCN1K/6ZgM7fok2I7xNw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@8.24.1': - resolution: {integrity: sha512-/Do9fmNgCsQ+K4rCz0STI7lYB4phTtEXqqCAs3gZW0pnK7lWNkvWd5iW545GSmApm4AzmQXmSqXPO565B4WVrw==} + '@typescript-eslint/type-utils@8.29.0': + resolution: {integrity: sha512-ahaWQ42JAOx+NKEf5++WC/ua17q5l+j1GFrbbpVKzFL/tKVc0aYY8rVSYUpUvt2hUP1YBr7mwXzx+E/DfUWI9Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/types@8.24.1': - resolution: {integrity: sha512-9kqJ+2DkUXiuhoiYIUvIYjGcwle8pcPpdlfkemGvTObzgmYfJ5d0Qm6jwb4NBXP9W1I5tss0VIAnWFumz3mC5A==} + '@typescript-eslint/types@8.29.0': + resolution: {integrity: sha512-wcJL/+cOXV+RE3gjCyl/V2G877+2faqvlgtso/ZRbTCnZazh0gXhe+7gbAnfubzN2bNsBtZjDvlh7ero8uIbzg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.24.1': - resolution: {integrity: sha512-UPyy4MJ/0RE648DSKQe9g0VDSehPINiejjA6ElqnFaFIhI6ZEiZAkUI0D5MCk0bQcTf/LVqZStvQ6K4lPn/BRg==} + '@typescript-eslint/typescript-estree@8.29.0': + resolution: {integrity: sha512-yOfen3jE9ISZR/hHpU/bmNvTtBW1NjRbkSFdZOksL1N+ybPEE7UVGMwqvS6CP022Rp00Sb0tdiIkhSCe6NI8ow==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/utils@8.24.1': - resolution: {integrity: sha512-OOcg3PMMQx9EXspId5iktsI3eMaXVwlhC8BvNnX6B5w9a4dVgpkQZuU8Hy67TolKcl+iFWq0XX+jbDGN4xWxjQ==} + '@typescript-eslint/utils@8.29.0': + resolution: {integrity: sha512-gX/A0Mz9Bskm8avSWFcK0gP7cZpbY4AIo6B0hWYFCaIsz750oaiWR4Jr2CI+PQhfW1CpcQr9OlfPS+kMFegjXA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 - typescript: '>=4.8.4 <5.8.0' + typescript: '>=4.8.4 <5.9.0' - '@typescript-eslint/visitor-keys@8.24.1': - resolution: {integrity: sha512-EwVHlp5l+2vp8CoqJm9KikPZgi3gbdZAtabKT9KPShGeOcJhsv4Zdo3oc8T8I0uKEmYoU4ItyxbptjF08enaxg==} + '@typescript-eslint/visitor-keys@8.29.0': + resolution: {integrity: sha512-Sne/pVz8ryR03NFK21VpN88dZ2FdQXOlq3VIklbrTYEt8yXtRFr9tvUhqvCeKjqYk5FSim37sHbooT6vzBTZcg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@unrs/resolver-binding-darwin-arm64@1.3.3': + resolution: {integrity: sha512-EpRILdWr3/xDa/7MoyfO7JuBIJqpBMphtu4+80BK1bRfFcniVT74h3Z7q1+WOc92FuIAYatB1vn9TJR67sORGw==} + cpu: [arm64] + os: [darwin] + + '@unrs/resolver-binding-darwin-x64@1.3.3': + resolution: {integrity: sha512-ntj/g7lPyqwinMJWZ+DKHBse8HhVxswGTmNgFKJtdgGub3M3zp5BSZ3bvMP+kBT6dnYJLSVlDqdwOq1P8i0+/g==} + cpu: [x64] + os: [darwin] + + '@unrs/resolver-binding-freebsd-x64@1.3.3': + resolution: {integrity: sha512-l6BT8f2CU821EW7U8hSUK8XPq4bmyTlt9Mn4ERrfjJNoCw0/JoHAh9amZZtV3cwC3bwwIat+GUnrcHTG9+qixw==} + cpu: [x64] + os: [freebsd] + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.3.3': + resolution: {integrity: sha512-8ScEc5a4y7oE2BonRvzJ+2GSkBaYWyh0/Ko4Q25e/ix6ANpJNhwEPZvCR6GVRmsQAYMIfQvYLdM6YEN+qRjnAQ==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm-musleabihf@1.3.3': + resolution: {integrity: sha512-8qQ6l1VTzLNd3xb2IEXISOKwMGXDCzY/UNy/7SovFW2Sp0K3YbL7Ao7R18v6SQkLqQlhhqSBIFRk+u6+qu5R5A==} + cpu: [arm] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-gnu@1.3.3': + resolution: {integrity: sha512-v81R2wjqcWXJlQY23byqYHt9221h4anQ6wwN64oMD/WAE+FmxPHFZee5bhRkNVtzqO/q7wki33VFWlhiADwUeQ==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-arm64-musl@1.3.3': + resolution: {integrity: sha512-cAOx/j0u5coMg4oct/BwMzvWJdVciVauUvsd+GQB/1FZYKQZmqPy0EjJzJGbVzFc6gbnfEcSqvQE6gvbGf2N8Q==} + cpu: [arm64] + os: [linux] + + '@unrs/resolver-binding-linux-ppc64-gnu@1.3.3': + resolution: {integrity: sha512-mq2blqwErgDJD4gtFDlTX/HZ7lNP8YCHYFij2gkXPtMzrXxPW1hOtxL6xg4NWxvnj4bppppb0W3s/buvM55yfg==} + cpu: [ppc64] + os: [linux] + + '@unrs/resolver-binding-linux-s390x-gnu@1.3.3': + resolution: {integrity: sha512-u0VRzfFYysarYHnztj2k2xr+eu9rmgoTUUgCCIT37Nr+j0A05Xk2c3RY8Mh5+DhCl2aYibihnaAEJHeR0UOFIQ==} + cpu: [s390x] + os: [linux] + + '@unrs/resolver-binding-linux-x64-gnu@1.3.3': + resolution: {integrity: sha512-OrVo5ZsG29kBF0Ug95a2KidS16PqAMmQNozM6InbquOfW/udouk063e25JVLqIBhHLB2WyBnixOQ19tmeC/hIg==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-linux-x64-musl@1.3.3': + resolution: {integrity: sha512-PYnmrwZ4HMp9SkrOhqPghY/aoL+Rtd4CQbr93GlrRTjK6kDzfMfgz3UH3jt6elrQAfupa1qyr1uXzeVmoEAxUA==} + cpu: [x64] + os: [linux] + + '@unrs/resolver-binding-wasm32-wasi@1.3.3': + resolution: {integrity: sha512-81AnQY6fShmktQw4hWDUIilsKSdvr/acdJ5azAreu2IWNlaJOKphJSsUVWE+yCk6kBMoQyG9ZHCb/krb5K0PEA==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@unrs/resolver-binding-win32-arm64-msvc@1.3.3': + resolution: {integrity: sha512-X/42BMNw7cW6xrB9syuP5RusRnWGoq+IqvJO8IDpp/BZg64J1uuIW6qA/1Cl13Y4LyLXbJVYbYNSKwR/FiHEng==} + cpu: [arm64] + os: [win32] + + '@unrs/resolver-binding-win32-ia32-msvc@1.3.3': + resolution: {integrity: sha512-EGNnNGQxMU5aTN7js3ETYvuw882zcO+dsVjs+DwO2j/fRVKth87C8e2GzxW1L3+iWAXMyJhvFBKRavk9Og1Z6A==} + cpu: [ia32] + os: [win32] + + '@unrs/resolver-binding-win32-x64-msvc@1.3.3': + resolution: {integrity: sha512-GraLbYqOJcmW1qY3osB+2YIiD62nVf2/bVLHZmrb4t/YSUwE03l7TwcDJl08T/Tm3SVhepX8RQkpzWbag/Sb4w==} + cpu: [x64] + os: [win32] + acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: @@ -882,8 +982,8 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - caniuse-lite@1.0.30001700: - resolution: {integrity: sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==} + caniuse-lite@1.0.30001712: + resolution: {integrity: sha512-MBqPpGYYdQ7/hfKiet9SCI+nmN5/hp4ZzveOJubl5DTAMa5oggjAuoi0Z4onBpKPFI2ePGnQuQIzF3VxDjDJig==} chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -1087,6 +1187,10 @@ packages: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + detect-libc@1.0.3: resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} engines: {node: '>=0.10'} @@ -1191,8 +1295,8 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - eslint-config-next@15.1.7: - resolution: {integrity: sha512-zXoMnYUIy3XHaAoOhrcYkT9UQWvXqWju2K7NNsmb5wd/7XESDwof61eUdW4QhERr3eJ9Ko/vnXqIrj8kk/drYw==} + eslint-config-next@15.2.4: + resolution: {integrity: sha512-v4gYjd4eYIme8qzaJItpR5MMBXJ0/YV07u7eb50kEnlEmX7yhOjdUdzz70v4fiINYRjLf8X8TbogF0k7wlz6sA==} peerDependencies: eslint: ^7.23.0 || ^8.0.0 || ^9.0.0 typescript: '>=3.3.1' @@ -1200,8 +1304,8 @@ packages: typescript: optional: true - eslint-config-prettier@10.0.2: - resolution: {integrity: sha512-1105/17ZIMjmCOJOPNfVdbXafLCLj3hPmkmB7dLgt7XsQ/zkxSuDerE/xgO3RxoHysR1N1whmquY0lSn2O0VLg==} + eslint-config-prettier@10.1.1: + resolution: {integrity: sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==} hasBin: true peerDependencies: eslint: '>=7.0.0' @@ -1209,8 +1313,8 @@ packages: eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} - eslint-import-resolver-typescript@3.8.2: - resolution: {integrity: sha512-o0nvXxsatYCDTzI1K5b3aYGQ6PjpDGJEVN86zqJw5SEewhmmggfRTotd2dqWr2t2zbeYpIEWGTCkgtUpIEIcaQ==} + eslint-import-resolver-typescript@3.10.0: + resolution: {integrity: sha512-aV3/dVsT0/H9BtpNwbaqvl+0xGMRGzncLyhm793NFGvbwGGvzyAykqWZ8oZlZuGwuHkwJjhWJkG1cM3ynvd2pQ==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: eslint: '*' @@ -1358,8 +1462,8 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - fastq@1.19.0: - resolution: {integrity: sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==} + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} fdir@6.4.3: resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==} @@ -1551,6 +1655,14 @@ packages: i18next@21.10.0: resolution: {integrity: sha512-YeuIBmFsGjUfO3qBmMOc0rQaun4mIpGKET5WDwvu8lU7gvwpcariZLNtL0Fzj+zazcHUrlXHiptcFhBMFaxzfg==} + i18next@24.2.3: + resolution: {integrity: sha512-lfbf80OzkocvX7nmZtu7nSTNbrTYR52sLWxPtlXX1zAhVw8WEnFk4puUkCR4B1dNQwbSpEHHHemcZu//7EcB7A==} + peerDependencies: + typescript: ^5 + peerDependenciesMeta: + typescript: + optional: true + ical-date-parser@4.0.0: resolution: {integrity: sha512-XRCK/FU1akC2ZaJOdKIeZI6BLLgzWUuE0pegSrrkEva89GOan5mNkLVqCU4EMhCJ9nkG5TLWdMXrVX1fNAkFzw==} @@ -1603,8 +1715,8 @@ packages: resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} engines: {node: '>= 0.4'} - is-bun-module@1.3.0: - resolution: {integrity: sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==} + is-bun-module@2.0.0: + resolution: {integrity: sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==} is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} @@ -1911,9 +2023,9 @@ packages: resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - minecraftstatuspinger@1.2.1: - resolution: {integrity: sha512-Qo/3TzV0UeULbVyqMqS9sUPbNKGFK7U7as1xlS/xeXryQQEwitOz5SkVhVphY4fCTacl5a+E4VXiTq6TPKYDKw==} - engines: {node: '>=16.0.0'} + minecraftstatuspinger@1.2.2: + resolution: {integrity: sha512-3PDWcifjw6cliGnGqw0+nJVWWPOcpLDyNLh4D84vCNzPD2h9REbN5Ne11I//CMkIu5xJiIuyGwI44gyRYYbpuw==} + engines: {node: '>=14.0.0'} mini-svg-data-uri@1.4.4: resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==} @@ -1955,8 +2067,8 @@ packages: nan@2.22.0: resolution: {integrity: sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==} - nanoid@3.3.8: - resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -1970,8 +2082,8 @@ packages: next: '>= 10.0.0' react: '>= 16.8.0' - next@15.1.7: - resolution: {integrity: sha512-GNeINPGS9c6OZKCvKypbL8GTsT5GhWPp4DM0fzkXJuXMilOO2EeFxuAY6JZbtk6XIl6Ws10ag3xRINDjSO5+wg==} + next@15.2.4: + resolution: {integrity: sha512-VwL+LAaPSxEkd3lU2xWbgEOtrM8oedmyhBqaVNmgKB+GvZlCy9rgaEc+y2on0wv+l0oSFqLtYD6dcC1eAedUaQ==} engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0} hasBin: true peerDependencies: @@ -2127,8 +2239,8 @@ packages: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} - postcss@8.5.2: - resolution: {integrity: sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==} + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} engines: {node: ^10 || ^12 || >=14} prelude-ls@1.2.1: @@ -2139,6 +2251,16 @@ packages: resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} engines: {node: '>=6.0.0'} + prettier-plugin-organize-imports@4.1.0: + resolution: {integrity: sha512-5aWRdCgv645xaa58X8lOxzZoiHAldAPChljr/MT0crXVOWTZ+Svl4hIWlz+niYSlO6ikE5UXkN1JrRvIP2ut0A==} + peerDependencies: + prettier: '>=2.0' + typescript: '>=2.9' + vue-tsc: ^2.1.0 + peerDependenciesMeta: + vue-tsc: + optional: true + prettier@3.5.2: resolution: {integrity: sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==} engines: {node: '>=14'} @@ -2284,8 +2406,8 @@ packages: resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} engines: {node: '>=14.16'} - reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} rfc4648@1.5.4: @@ -2409,8 +2531,8 @@ packages: resolution: {integrity: sha512-r1X4KsBGedJqo7h8F5c4Ybpcr5RjyP+aWIG007uBPRjmdQWfEiVLzSK71Zji1B9sKxwaCvD8y8cwSkYrlLiRRg==} engines: {node: '>=10.16.0'} - stable-hash@0.0.4: - resolution: {integrity: sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==} + stable-hash@0.0.5: + resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==} stack-trace@0.0.10: resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} @@ -2507,10 +2629,10 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - swr@1.3.0: - resolution: {integrity: sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw==} + swr@2.3.3: + resolution: {integrity: sha512-dshNvs3ExOqtZ6kJBaAsabhPdHyeY4P2cKwRCniDVifBMoG/SVI7tfLWqPXriVspf2Rg4tPzXJTnwaihIeFw2A==} peerDependencies: - react: ^16.11.0 || ^17.0.0 || ^18.0.0 + react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 synckit@0.9.2: resolution: {integrity: sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==} @@ -2552,8 +2674,8 @@ packages: tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} - tinyglobby@0.2.11: - resolution: {integrity: sha512-32TmKeeKUahv0Go8WmQgiEp9Y21NuxjwjqiRC1nrUB51YacfSwuB44xgXD+HdIppmMRgjQNPdrHyA6vIybYZ+g==} + tinyglobby@0.2.12: + resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} engines: {node: '>=12.0.0'} tldts-core@6.1.82: @@ -2589,8 +2711,8 @@ packages: resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} engines: {node: '>= 14.0.0'} - ts-api-utils@2.0.1: - resolution: {integrity: sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==} + ts-api-utils@2.1.0: + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' @@ -2640,12 +2762,20 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} + unrs-resolver@1.3.3: + resolution: {integrity: sha512-PFLAGQzYlyjniXdbmQ3dnGMZJXX5yrl2YS4DLRfR3BhgUsE1zpRIrccp9XMOGRfIHpdFvCn/nr5N1KMVda4x3A==} + urbackup-server-api@0.8.9: resolution: {integrity: sha512-Igu6A0xSZeMsiN6PWT7zG4aD+iJR5fXT/j5+xwAvnD/vCNfvVrettIsXv6MftxOajvTmtlgaYu8KDoH1EJQ6DQ==} uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + use-sync-external-store@1.5.0: + resolution: {integrity: sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -2765,6 +2895,10 @@ snapshots: dependencies: regenerator-runtime: 0.14.1 + '@babel/runtime@7.27.0': + dependencies: + regenerator-runtime: 0.14.1 + '@balena/dockerignore@1.0.2': {} '@colors/colors@1.6.0': {} @@ -2775,7 +2909,18 @@ snapshots: enabled: 2.0.0 kuler: 2.0.0 - '@emnapi/runtime@1.3.1': + '@emnapi/core@1.4.0': + dependencies: + '@emnapi/wasi-threads': 1.0.1 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.4.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.0.1': dependencies: tslib: 2.8.1 optional: true @@ -2785,6 +2930,11 @@ snapshots: eslint: 9.21.0(jiti@2.4.2) eslint-visitor-keys: 3.4.3 + '@eslint-community/eslint-utils@4.5.1(eslint@9.21.0(jiti@2.4.2))': + dependencies: + eslint: 9.21.0(jiti@2.4.2) + eslint-visitor-keys: 3.4.3 + '@eslint-community/regexpp@4.12.1': {} '@eslint/config-array@0.19.2': @@ -2920,7 +3070,7 @@ snapshots: '@img/sharp-wasm32@0.33.5': dependencies: - '@emnapi/runtime': 1.3.1 + '@emnapi/runtime': 1.4.0 optional: true '@img/sharp-win32-ia32@0.33.5': @@ -2977,34 +3127,41 @@ snapshots: - encoding - utf-8-validate - '@next/env@15.1.7': {} + '@napi-rs/wasm-runtime@0.2.8': + dependencies: + '@emnapi/core': 1.4.0 + '@emnapi/runtime': 1.4.0 + '@tybys/wasm-util': 0.9.0 + optional: true - '@next/eslint-plugin-next@15.1.7': + '@next/env@15.2.4': {} + + '@next/eslint-plugin-next@15.2.4': dependencies: fast-glob: 3.3.1 - '@next/swc-darwin-arm64@15.1.7': + '@next/swc-darwin-arm64@15.2.4': optional: true - '@next/swc-darwin-x64@15.1.7': + '@next/swc-darwin-x64@15.2.4': optional: true - '@next/swc-linux-arm64-gnu@15.1.7': + '@next/swc-linux-arm64-gnu@15.2.4': optional: true - '@next/swc-linux-arm64-musl@15.1.7': + '@next/swc-linux-arm64-musl@15.2.4': optional: true - '@next/swc-linux-x64-gnu@15.1.7': + '@next/swc-linux-x64-gnu@15.2.4': optional: true - '@next/swc-linux-x64-musl@15.1.7': + '@next/swc-linux-x64-musl@15.2.4': optional: true - '@next/swc-win32-arm64-msvc@15.1.7': + '@next/swc-win32-arm64-msvc@15.2.4': optional: true - '@next/swc-win32-x64-msvc@15.1.7': + '@next/swc-win32-x64-msvc@15.2.4': optional: true '@nodelib/fs.scandir@2.1.5': @@ -3017,7 +3174,7 @@ snapshots: '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 - fastq: 1.19.0 + fastq: 1.19.1 '@nolyfill/is-core-module@1.0.39': {} @@ -3051,7 +3208,7 @@ snapshots: '@rtsao/scc@1.1.0': {} - '@rushstack/eslint-patch@1.10.5': {} + '@rushstack/eslint-patch@1.11.0': {} '@sindresorhus/is@5.6.0': {} @@ -3129,7 +3286,7 @@ snapshots: '@tailwindcss/node': 4.0.9 '@tailwindcss/oxide': 4.0.9 lightningcss: 1.29.1 - postcss: 8.5.2 + postcss: 8.5.3 tailwindcss: 4.0.9 '@tanstack/react-virtual@3.13.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': @@ -3140,6 +3297,11 @@ snapshots: '@tanstack/virtual-core@3.13.0': {} + '@tybys/wasm-util@0.9.0': + dependencies: + tslib: 2.8.1 + optional: true + '@types/d3-array@3.2.1': {} '@types/d3-color@3.1.3': {} @@ -3209,83 +3371,130 @@ snapshots: dependencies: '@types/node': 22.13.4 - '@typescript-eslint/eslint-plugin@8.24.1(@typescript-eslint/parser@8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3)': + '@typescript-eslint/eslint-plugin@8.29.0(@typescript-eslint/parser@8.29.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) - '@typescript-eslint/scope-manager': 8.24.1 - '@typescript-eslint/type-utils': 8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) - '@typescript-eslint/utils': 8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.24.1 + '@typescript-eslint/parser': 8.29.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/scope-manager': 8.29.0 + '@typescript-eslint/type-utils': 8.29.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/utils': 8.29.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.29.0 eslint: 9.21.0(jiti@2.4.2) graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 - ts-api-utils: 2.0.1(typescript@5.7.3) + ts-api-utils: 2.1.0(typescript@5.7.3) typescript: 5.7.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3)': + '@typescript-eslint/parser@8.29.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3)': dependencies: - '@typescript-eslint/scope-manager': 8.24.1 - '@typescript-eslint/types': 8.24.1 - '@typescript-eslint/typescript-estree': 8.24.1(typescript@5.7.3) - '@typescript-eslint/visitor-keys': 8.24.1 + '@typescript-eslint/scope-manager': 8.29.0 + '@typescript-eslint/types': 8.29.0 + '@typescript-eslint/typescript-estree': 8.29.0(typescript@5.7.3) + '@typescript-eslint/visitor-keys': 8.29.0 debug: 4.4.0 eslint: 9.21.0(jiti@2.4.2) typescript: 5.7.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.24.1': + '@typescript-eslint/scope-manager@8.29.0': dependencies: - '@typescript-eslint/types': 8.24.1 - '@typescript-eslint/visitor-keys': 8.24.1 + '@typescript-eslint/types': 8.29.0 + '@typescript-eslint/visitor-keys': 8.29.0 - '@typescript-eslint/type-utils@8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3)': + '@typescript-eslint/type-utils@8.29.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3)': dependencies: - '@typescript-eslint/typescript-estree': 8.24.1(typescript@5.7.3) - '@typescript-eslint/utils': 8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/typescript-estree': 8.29.0(typescript@5.7.3) + '@typescript-eslint/utils': 8.29.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) debug: 4.4.0 eslint: 9.21.0(jiti@2.4.2) - ts-api-utils: 2.0.1(typescript@5.7.3) + ts-api-utils: 2.1.0(typescript@5.7.3) typescript: 5.7.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.24.1': {} + '@typescript-eslint/types@8.29.0': {} - '@typescript-eslint/typescript-estree@8.24.1(typescript@5.7.3)': + '@typescript-eslint/typescript-estree@8.29.0(typescript@5.7.3)': dependencies: - '@typescript-eslint/types': 8.24.1 - '@typescript-eslint/visitor-keys': 8.24.1 + '@typescript-eslint/types': 8.29.0 + '@typescript-eslint/visitor-keys': 8.29.0 debug: 4.4.0 fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.7.1 - ts-api-utils: 2.0.1(typescript@5.7.3) + ts-api-utils: 2.1.0(typescript@5.7.3) typescript: 5.7.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3)': + '@typescript-eslint/utils@8.29.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3)': dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.21.0(jiti@2.4.2)) - '@typescript-eslint/scope-manager': 8.24.1 - '@typescript-eslint/types': 8.24.1 - '@typescript-eslint/typescript-estree': 8.24.1(typescript@5.7.3) + '@eslint-community/eslint-utils': 4.5.1(eslint@9.21.0(jiti@2.4.2)) + '@typescript-eslint/scope-manager': 8.29.0 + '@typescript-eslint/types': 8.29.0 + '@typescript-eslint/typescript-estree': 8.29.0(typescript@5.7.3) eslint: 9.21.0(jiti@2.4.2) typescript: 5.7.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.24.1': + '@typescript-eslint/visitor-keys@8.29.0': dependencies: - '@typescript-eslint/types': 8.24.1 + '@typescript-eslint/types': 8.29.0 eslint-visitor-keys: 4.2.0 + '@unrs/resolver-binding-darwin-arm64@1.3.3': + optional: true + + '@unrs/resolver-binding-darwin-x64@1.3.3': + optional: true + + '@unrs/resolver-binding-freebsd-x64@1.3.3': + optional: true + + '@unrs/resolver-binding-linux-arm-gnueabihf@1.3.3': + optional: true + + '@unrs/resolver-binding-linux-arm-musleabihf@1.3.3': + optional: true + + '@unrs/resolver-binding-linux-arm64-gnu@1.3.3': + optional: true + + '@unrs/resolver-binding-linux-arm64-musl@1.3.3': + optional: true + + '@unrs/resolver-binding-linux-ppc64-gnu@1.3.3': + optional: true + + '@unrs/resolver-binding-linux-s390x-gnu@1.3.3': + optional: true + + '@unrs/resolver-binding-linux-x64-gnu@1.3.3': + optional: true + + '@unrs/resolver-binding-linux-x64-musl@1.3.3': + optional: true + + '@unrs/resolver-binding-wasm32-wasi@1.3.3': + dependencies: + '@napi-rs/wasm-runtime': 0.2.8 + optional: true + + '@unrs/resolver-binding-win32-arm64-msvc@1.3.3': + optional: true + + '@unrs/resolver-binding-win32-ia32-msvc@1.3.3': + optional: true + + '@unrs/resolver-binding-win32-x64-msvc@1.3.3': + optional: true + acorn-jsx@5.3.2(acorn@8.14.0): dependencies: acorn: 8.14.0 @@ -3486,7 +3695,7 @@ snapshots: callsites@3.1.0: {} - caniuse-lite@1.0.30001700: {} + caniuse-lite@1.0.30001712: {} chalk@4.1.2: dependencies: @@ -3691,6 +3900,8 @@ snapshots: depd@2.0.0: {} + dequal@2.0.3: {} + detect-libc@1.0.3: {} detect-libc@2.0.3: @@ -3723,7 +3934,7 @@ snapshots: dom-helpers@5.2.1: dependencies: - '@babel/runtime': 7.26.9 + '@babel/runtime': 7.27.0 csstype: 3.1.3 dom-serializer@2.0.0: @@ -3871,16 +4082,16 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-next@15.1.7(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3): + eslint-config-next@15.2.4(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3): dependencies: - '@next/eslint-plugin-next': 15.1.7 - '@rushstack/eslint-patch': 1.10.5 - '@typescript-eslint/eslint-plugin': 8.24.1(@typescript-eslint/parser@8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) - '@typescript-eslint/parser': 8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + '@next/eslint-plugin-next': 15.2.4 + '@rushstack/eslint-patch': 1.11.0 + '@typescript-eslint/eslint-plugin': 8.29.0(@typescript-eslint/parser@8.29.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/parser': 8.29.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) eslint: 9.21.0(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.8.2(eslint-plugin-import@2.31.0)(eslint@9.21.0(jiti@2.4.2)) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.8.2)(eslint@9.21.0(jiti@2.4.2)) + eslint-import-resolver-typescript: 3.10.0(eslint-plugin-import@2.31.0)(eslint@9.21.0(jiti@2.4.2)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.29.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.10.0)(eslint@9.21.0(jiti@2.4.2)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.21.0(jiti@2.4.2)) eslint-plugin-react: 7.37.4(eslint@9.21.0(jiti@2.4.2)) eslint-plugin-react-hooks: 5.1.0(eslint@9.21.0(jiti@2.4.2)) @@ -3891,7 +4102,7 @@ snapshots: - eslint-plugin-import-x - supports-color - eslint-config-prettier@10.0.2(eslint@9.21.0(jiti@2.4.2)): + eslint-config-prettier@10.1.1(eslint@9.21.0(jiti@2.4.2)): dependencies: eslint: 9.21.0(jiti@2.4.2) @@ -3903,33 +4114,33 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.8.2(eslint-plugin-import@2.31.0)(eslint@9.21.0(jiti@2.4.2)): + eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0)(eslint@9.21.0(jiti@2.4.2)): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.0 - enhanced-resolve: 5.18.1 eslint: 9.21.0(jiti@2.4.2) get-tsconfig: 4.10.0 - is-bun-module: 1.3.0 - stable-hash: 0.0.4 - tinyglobby: 0.2.11 + is-bun-module: 2.0.0 + stable-hash: 0.0.5 + tinyglobby: 0.2.12 + unrs-resolver: 1.3.3 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.8.2)(eslint@9.21.0(jiti@2.4.2)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.29.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.10.0)(eslint@9.21.0(jiti@2.4.2)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.8.2(eslint-plugin-import@2.31.0)(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2)): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.29.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0)(eslint@9.21.0(jiti@2.4.2)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/parser': 8.29.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) eslint: 9.21.0(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.8.2(eslint-plugin-import@2.31.0)(eslint@9.21.0(jiti@2.4.2)) + eslint-import-resolver-typescript: 3.10.0(eslint-plugin-import@2.31.0)(eslint@9.21.0(jiti@2.4.2)) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.8.2)(eslint@9.21.0(jiti@2.4.2)): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.29.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-typescript@3.10.0)(eslint@9.21.0(jiti@2.4.2)): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -3940,7 +4151,7 @@ snapshots: doctrine: 2.1.0 eslint: 9.21.0(jiti@2.4.2) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.8.2(eslint-plugin-import@2.31.0)(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2)) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.29.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0)(eslint@9.21.0(jiti@2.4.2)) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -3952,7 +4163,7 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.24.1(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) + '@typescript-eslint/parser': 8.29.0(eslint@9.21.0(jiti@2.4.2))(typescript@5.7.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -3977,14 +4188,14 @@ snapshots: safe-regex-test: 1.1.0 string.prototype.includes: 2.0.1 - eslint-plugin-prettier@5.2.3(eslint-config-prettier@10.0.2(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2))(prettier@3.5.2): + eslint-plugin-prettier@5.2.3(eslint-config-prettier@10.1.1(eslint@9.21.0(jiti@2.4.2)))(eslint@9.21.0(jiti@2.4.2))(prettier@3.5.2): dependencies: eslint: 9.21.0(jiti@2.4.2) prettier: 3.5.2 prettier-linter-helpers: 1.0.0 synckit: 0.9.2 optionalDependencies: - eslint-config-prettier: 10.0.2(eslint@9.21.0(jiti@2.4.2)) + eslint-config-prettier: 10.1.1(eslint@9.21.0(jiti@2.4.2)) eslint-plugin-react-hooks@5.1.0(eslint@9.21.0(jiti@2.4.2)): dependencies: @@ -4110,9 +4321,9 @@ snapshots: fast-levenshtein@2.0.6: {} - fastq@1.19.0: + fastq@1.19.1: dependencies: - reusify: 1.0.4 + reusify: 1.1.0 fdir@6.4.3(picomatch@4.0.2): optionalDependencies: @@ -4328,7 +4539,13 @@ snapshots: i18next@21.10.0: dependencies: - '@babel/runtime': 7.26.9 + '@babel/runtime': 7.27.0 + + i18next@24.2.3(typescript@5.7.3): + dependencies: + '@babel/runtime': 7.27.0 + optionalDependencies: + typescript: 5.7.3 ical-date-parser@4.0.0: {} @@ -4382,7 +4599,7 @@ snapshots: call-bound: 1.0.3 has-tostringtag: 1.0.2 - is-bun-module@1.3.0: + is-bun-module@2.0.0: dependencies: semver: 7.7.1 @@ -4652,7 +4869,7 @@ snapshots: mimic-response@4.0.0: {} - minecraftstatuspinger@1.2.1: {} + minecraftstatuspinger@1.2.2: {} mini-svg-data-uri@1.4.4: {} @@ -4684,11 +4901,11 @@ snapshots: nan@2.22.0: optional: true - nanoid@3.3.8: {} + nanoid@3.3.11: {} natural-compare@1.4.0: {} - next-i18next@12.1.0(next@15.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next-i18next@12.1.0(next@15.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.9 '@types/hoist-non-react-statics': 3.3.6 @@ -4696,33 +4913,33 @@ snapshots: hoist-non-react-statics: 3.3.2 i18next: 21.10.0 i18next-fs-backend: 1.2.0 - next: 15.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + next: 15.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react: 18.3.1 react-i18next: 11.18.6(i18next@21.10.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) transitivePeerDependencies: - react-dom - react-native - next@15.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next@15.2.4(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@next/env': 15.1.7 + '@next/env': 15.2.4 '@swc/counter': 0.1.3 '@swc/helpers': 0.5.15 busboy: 1.6.0 - caniuse-lite: 1.0.30001700 + caniuse-lite: 1.0.30001712 postcss: 8.4.31 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) styled-jsx: 5.1.6(react@18.3.1) optionalDependencies: - '@next/swc-darwin-arm64': 15.1.7 - '@next/swc-darwin-x64': 15.1.7 - '@next/swc-linux-arm64-gnu': 15.1.7 - '@next/swc-linux-arm64-musl': 15.1.7 - '@next/swc-linux-x64-gnu': 15.1.7 - '@next/swc-linux-x64-musl': 15.1.7 - '@next/swc-win32-arm64-msvc': 15.1.7 - '@next/swc-win32-x64-msvc': 15.1.7 + '@next/swc-darwin-arm64': 15.2.4 + '@next/swc-darwin-x64': 15.2.4 + '@next/swc-linux-arm64-gnu': 15.2.4 + '@next/swc-linux-arm64-musl': 15.2.4 + '@next/swc-linux-x64-gnu': 15.2.4 + '@next/swc-linux-x64-musl': 15.2.4 + '@next/swc-win32-arm64-msvc': 15.2.4 + '@next/swc-win32-x64-msvc': 15.2.4 sharp: 0.33.5 transitivePeerDependencies: - '@babel/core' @@ -4860,13 +5077,13 @@ snapshots: postcss@8.4.31: dependencies: - nanoid: 3.3.8 + nanoid: 3.3.11 picocolors: 1.1.1 source-map-js: 1.2.1 - postcss@8.5.2: + postcss@8.5.3: dependencies: - nanoid: 3.3.8 + nanoid: 3.3.11 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -4876,6 +5093,11 @@ snapshots: dependencies: fast-diff: 1.3.0 + prettier-plugin-organize-imports@4.1.0(prettier@3.5.2)(typescript@5.7.3): + dependencies: + prettier: 3.5.2 + typescript: 5.7.3 + prettier@3.5.2: {} pretty-bytes@6.1.1: {} @@ -4942,6 +5164,15 @@ snapshots: optionalDependencies: react-dom: 18.3.1(react@18.3.1) + react-i18next@11.18.6(i18next@24.2.3(typescript@5.7.3))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@babel/runtime': 7.26.9 + html-parse-stringify: 3.0.1 + i18next: 24.2.3(typescript@5.7.3) + react: 18.3.1 + optionalDependencies: + react-dom: 18.3.1(react@18.3.1) + react-icons@5.4.0(react@18.3.1): dependencies: react: 18.3.1 @@ -4960,7 +5191,7 @@ snapshots: react-transition-group@4.4.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@babel/runtime': 7.26.9 + '@babel/runtime': 7.27.0 dom-helpers: 5.2.1 loose-envify: 1.4.0 prop-types: 15.8.1 @@ -5057,7 +5288,7 @@ snapshots: dependencies: lowercase-keys: 3.0.0 - reusify@1.0.4: {} + reusify@1.1.0: {} rfc4648@1.5.4: {} @@ -5219,7 +5450,7 @@ snapshots: cpu-features: 0.0.10 nan: 2.22.0 - stable-hash@0.0.4: {} + stable-hash@0.0.5: {} stack-trace@0.0.10: {} @@ -5329,9 +5560,11 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - swr@1.3.0(react@18.3.1): + swr@2.3.3(react@18.3.1): dependencies: + dequal: 2.0.3 react: 18.3.1 + use-sync-external-store: 1.5.0(react@18.3.1) synckit@0.9.2: dependencies: @@ -5379,7 +5612,7 @@ snapshots: tiny-invariant@1.3.3: {} - tinyglobby@0.2.11: + tinyglobby@0.2.12: dependencies: fdir: 6.4.3(picomatch@4.0.2) picomatch: 4.0.2 @@ -5410,7 +5643,7 @@ snapshots: triple-beam@1.4.1: {} - ts-api-utils@2.0.1(typescript@5.7.3): + ts-api-utils@2.1.0(typescript@5.7.3): dependencies: typescript: 5.7.3 @@ -5475,6 +5708,24 @@ snapshots: unpipe@1.0.0: {} + unrs-resolver@1.3.3: + optionalDependencies: + '@unrs/resolver-binding-darwin-arm64': 1.3.3 + '@unrs/resolver-binding-darwin-x64': 1.3.3 + '@unrs/resolver-binding-freebsd-x64': 1.3.3 + '@unrs/resolver-binding-linux-arm-gnueabihf': 1.3.3 + '@unrs/resolver-binding-linux-arm-musleabihf': 1.3.3 + '@unrs/resolver-binding-linux-arm64-gnu': 1.3.3 + '@unrs/resolver-binding-linux-arm64-musl': 1.3.3 + '@unrs/resolver-binding-linux-ppc64-gnu': 1.3.3 + '@unrs/resolver-binding-linux-s390x-gnu': 1.3.3 + '@unrs/resolver-binding-linux-x64-gnu': 1.3.3 + '@unrs/resolver-binding-linux-x64-musl': 1.3.3 + '@unrs/resolver-binding-wasm32-wasi': 1.3.3 + '@unrs/resolver-binding-win32-arm64-msvc': 1.3.3 + '@unrs/resolver-binding-win32-ia32-msvc': 1.3.3 + '@unrs/resolver-binding-win32-x64-msvc': 1.3.3 + urbackup-server-api@0.8.9: dependencies: async-mutex: 0.3.2 @@ -5486,6 +5737,10 @@ snapshots: dependencies: punycode: 2.3.1 + use-sync-external-store@1.5.0(react@18.3.1): + dependencies: + react: 18.3.1 + util-deprecate@1.0.2: {} uuid@10.0.0: {} diff --git a/public/locales/af/common.json b/public/locales/af/common.json index 20f3d170..fa71b238 100644 --- a/public/locales/af/common.json +++ b/public/locales/af/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Kennisgewings", "issues": "Kwessies", - "pulls": "Trek Versoeke" + "pulls": "Trek Versoeke", + "repositories": "Bewaarplekke" }, "stash": { "scenes": "Tonele", @@ -1023,12 +1024,23 @@ "bcharge": "Batterylading", "timeleft": "Oorblywende Tyd" }, - "hoarder": { - "bookmarks": "Bookmarks", - "favorites": "Favorites", - "archived": "Archived", - "highlights": "Highlights", - "lists": "Lists", + "karakeep": { + "bookmarks": "Boekmerke", + "favorites": "Gunstelinge", + "archived": "Geargiveer", + "highlights": "Hoogtepunte", + "lists": "Lyste", "tags": "Merkers" + }, + "slskd": { + "slskStatus": "Netwerk", + "connected": "Gekoppel", + "disconnected": "Ontkoppel", + "updateStatus": "Opdateer", + "update_yes": "Beskikbaar", + "update_no": "Op Datum", + "downloads": "Aflaaie", + "uploads": "Oplaaie", + "sharedFiles": "Lêers" } } diff --git a/public/locales/ar/common.json b/public/locales/ar/common.json index 7c7344f8..dbe892aa 100644 --- a/public/locales/ar/common.json +++ b/public/locales/ar/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "الإشعارات", "issues": "المُشكِلات", - "pulls": "طلبات السحب" + "pulls": "طلبات السحب", + "repositories": "Repositories" }, "stash": { "scenes": "المشاهد", @@ -1023,12 +1024,23 @@ "bcharge": "شحن البطارية", "timeleft": "الوقت المتبقي" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "التصنيفات" + }, + "slskd": { + "slskStatus": "الشبكة", + "connected": "متصل", + "disconnected": "غير متصل", + "updateStatus": "Update", + "update_yes": "متاح", + "update_no": "حتى الآن", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "ملفات" } } diff --git a/public/locales/bg/common.json b/public/locales/bg/common.json index 74505cc6..ccb6f5bb 100644 --- a/public/locales/bg/common.json +++ b/public/locales/bg/common.json @@ -394,7 +394,7 @@ "strelaysrv": { "numActiveSessions": "Сесии", "numConnections": "Connections", - "dataRelayed": "Relayed", + "dataRelayed": "", "transferRate": "Скорост" }, "mastodon": { @@ -885,7 +885,8 @@ "gitea": { "notifications": "Известия", "issues": "Издания", - "pulls": "Заявки за сливане" + "pulls": "Заявки за сливане", + "repositories": "Repositories" }, "stash": { "scenes": "Сцени", @@ -1001,7 +1002,7 @@ "argocd": { "apps": "Приложения", "synced": "Synced", - "outOfSync": "Out Of Sync", + "outOfSync": "", "healthy": "Здрав", "degraded": "Деградирани", "progressing": "Progressing", @@ -1023,12 +1024,23 @@ "bcharge": "Заряд на батерията", "timeleft": "Оставащо Време" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Тагове" + }, + "slskd": { + "slskStatus": "Мрежа", + "connected": "Свързан", + "disconnected": "Не е свързан", + "updateStatus": "Update", + "update_yes": "Наличен", + "update_no": "Актуално", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Файлове" } } diff --git a/public/locales/ca/common.json b/public/locales/ca/common.json index 620a0df5..b70794b3 100644 --- a/public/locales/ca/common.json +++ b/public/locales/ca/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notificacions", "issues": "Problemes", - "pulls": "Sol·licitud de Canvis" + "pulls": "Sol·licitud de Canvis", + "repositories": "Repositories" }, "stash": { "scenes": "Escenes", @@ -1023,12 +1024,23 @@ "bcharge": "Càrrega de la bateria", "timeleft": "Temps restant" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Etiquetes" + }, + "slskd": { + "slskStatus": "Xarxa", + "connected": "Connectat", + "disconnected": "Desconnectat", + "updateStatus": "Update", + "update_yes": "Disponible", + "update_no": "Actualitzat", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Fitxers" } } diff --git a/public/locales/cs/common.json b/public/locales/cs/common.json index 31c7921a..1d99ec95 100644 --- a/public/locales/cs/common.json +++ b/public/locales/cs/common.json @@ -85,16 +85,16 @@ "ping": { "error": "Chyba", "ping": "Odezva", - "down": "Down", - "up": "Up", + "down": "Výpadek", + "up": "Běží", "not_available": "Není k dispozici" }, "siteMonitor": { "http_status": "Stav HTTP", "error": "Chyba", "response": "Odpověď", - "down": "Down", - "up": "Up", + "down": "Výpadek", + "up": "Běží", "not_available": "Není k dispozici" }, "emby": { @@ -144,13 +144,13 @@ "uptime": "Doba spuštění", "maxDown": "Max. Down", "maxUp": "Max. Up", - "down": "Down", - "up": "Up", + "down": "Výpadek", + "up": "Běží", "received": "Přijaté", "sent": "Odeslané", "externalIPAddress": "Ext. IP", - "externalIPv6Address": "Ext. IPv6", - "externalIPv6Prefix": "Ext. IPv6-Prefix" + "externalIPv6Address": "Veřejná IPv6", + "externalIPv6Prefix": "Věřejná IPv6 prefix" }, "caddy": { "upstreams": "Odesílání dat", @@ -178,7 +178,7 @@ "connectedAp": "Připojené APs", "activeUser": "Aktivní zařízení", "alerts": "Upozornění", - "connectedGateways": "Connected gateways", + "connectedGateways": "Připojené brány", "connectedSwitches": "Připojené přepínače" }, "nzbget": { @@ -229,8 +229,8 @@ "seed": "Seedované" }, "develancacheui": { - "cachehitbytes": "Cache Hit Bytes", - "cachemissbytes": "Cache Miss Bytes" + "cachehitbytes": "Byty nalezené v mezipaměti", + "cachemissbytes": "Byty nenalezené v mezipaměti" }, "downloadstation": { "download": "Stahování", @@ -287,7 +287,7 @@ "total": "Celkem", "connected": "", "new_devices": "", - "down_alerts": "Down Alerts" + "down_alerts": "Upozornění na výpadek" }, "pihole": { "queries": "Dotazy", @@ -313,13 +313,13 @@ }, "suwayomi": { "download": "Staženo", - "nondownload": "Non-Downloaded", + "nondownload": "Nestaženo", "read": "Přečteno", "unread": "Nepřečteno", - "downloadedread": "Downloaded & Read", - "downloadedunread": "Downloaded & Unread", - "nondownloadedread": "Non-Downloaded & Read", - "nondownloadedunread": "Non-Downloaded & Unread" + "downloadedread": "Staženo a přečteno", + "downloadedunread": "Staženo a nepřečteno", + "nondownloadedread": "Nestaženo a přečteno", + "nondownloadedunread": "Nestaženo a nepřečteno" }, "tailscale": { "address": "Adresa", @@ -337,15 +337,15 @@ }, "technitium": { "totalQueries": "Dotazy", - "totalNoError": "Success", - "totalServerFailure": "Failures", - "totalNxDomain": "NX Domains", - "totalRefused": "Refused", - "totalAuthoritative": "Authoritative", - "totalRecursive": "Recursive", - "totalCached": "Cached", + "totalNoError": "Úspěšně", + "totalServerFailure": "Chyby", + "totalNxDomain": "NX domény", + "totalRefused": "Odmítnuto", + "totalAuthoritative": "Autoritativní", + "totalRecursive": "Rekurzivní", + "totalCached": "V mezipaměti", "totalBlocked": "Blokováno", - "totalDropped": "Dropped", + "totalDropped": "Vynecháno", "totalClients": "Klienti" }, "tdarr": { @@ -434,7 +434,7 @@ "load": "Zatížení", "wait": "Počkejte prosím", "temp": "TEPLOTA", - "_temp": "Temp", + "_temp": "Teplota", "warn": "Varováni", "uptime": "BĚŽÍ", "total": "Celkem", @@ -442,12 +442,12 @@ "used": "Využité", "days": "d", "hours": "h", - "crit": "Crit", + "crit": "Kritické", "read": "Přečteno", - "write": "Write", - "gpu": "GPU", - "mem": "Mem", - "swap": "Swap" + "write": "Zápis", + "gpu": "Grafická karta", + "mem": "Pamět RAM", + "swap": "Swap RAM" }, "quicklaunch": { "bookmark": "Záložka", @@ -456,7 +456,7 @@ "custom": "Vlastní", "visit": "Navštivte", "url": "Odkaz", - "searchsuggestion": "Suggestion" + "searchsuggestion": "Doporučení" }, "wmo": { "0-day": "Slunečno", @@ -523,15 +523,15 @@ "up_to_date": "Žádné", "child_bridges": "Podřízené můstky", "child_bridges_status": "{{ok}}/{{total}}", - "up": "Up", + "up": "Běží", "pending": "Čeká", - "down": "Down" + "down": "Výpadek" }, "healthchecks": { "new": "Nové", - "up": "Up", + "up": "Běží", "grace": "V období odkladu", - "down": "Down", + "down": "Výpadek", "paused": "Pozastaveno", "status": "Stav", "last_ping": "Poslední ping", @@ -573,14 +573,14 @@ "hdhomerun": { "channels": "Kanály", "hd": "HD", - "tunerCount": "Tuners", - "channelNumber": "Channel", - "channelNetwork": "Network", - "signalStrength": "Strength", - "signalQuality": "Quality", - "symbolQuality": "Quality", + "tunerCount": "Tuner", + "channelNumber": "Kanál", + "channelNetwork": "Síť", + "signalStrength": "Síla", + "signalQuality": "Kvalita", + "symbolQuality": "Kvalita", "networkRate": "Přenosová rychlost", - "clientIP": "Client" + "clientIP": "Klient" }, "scrutiny": { "passed": "Úspěšné", @@ -592,12 +592,12 @@ "total": "Celkem" }, "peanut": { - "battery_charge": "Battery Charge", - "ups_load": "UPS Load", - "ups_status": "UPS Status", + "battery_charge": "Úroveň baterie", + "ups_load": "Zítěž UPS", + "ups_status": "Stav UPS", "online": "Online", - "on_battery": "On Battery", - "low_battery": "Low Battery" + "on_battery": "Na baterii", + "low_battery": "Nízký stav baterie" }, "nextdns": { "wait": "Čekejte prosím", @@ -615,9 +615,9 @@ "streams_xepg": "Kanály XEPG" }, "opendtu": { - "yieldDay": "Today", - "absolutePower": "Power", - "relativePower": "Power %", + "yieldDay": "Dnes", + "absolutePower": "Výkon", + "relativePower": "Výkon %", "limit": "Limit" }, "opnsense": { @@ -646,9 +646,9 @@ "load": "Prům. zatížení", "memory": "Využití paměti", "wanStatus": "Stav WAN", - "up": "Up", - "down": "Down", - "temp": "Temp", + "up": "Běží", + "down": "Výpadek", + "temp": "Teplota", "disk": "Využití disku", "wanIP": "IP WAN" }, @@ -668,14 +668,14 @@ "up": "Stránky Up", "down": "Stránky Down", "uptime": "Doba spuštění", - "incident": "Incident", + "incident": "Událost", "m": "m" }, "atsumeru": { "series": "Seriály", - "archives": "Archives", - "chapters": "Chapters", - "categories": "Categories" + "archives": "Archivy", + "chapters": "Kapitoly", + "categories": "Kategorie" }, "komga": { "libraries": "Knihovny", @@ -705,13 +705,13 @@ "time": "Čas" }, "firefly": { - "networth": "Net Worth", - "budget": "Budget" + "networth": "Čisté jmění", + "budget": "Rozpočet" }, "grafana": { "dashboards": "Nástěnky", "datasources": "Zdroje dat", - "totalalerts": "Celkový počet upozornění", + "totalalerts": "Celkový počet upozornění2", "alertstriggered": "Spuštěné výstrahy" }, "nextcloud": { @@ -749,7 +749,7 @@ "uptime": "Doba spuštění" }, "ghostfolio": { - "gross_percent_today": "Today", + "gross_percent_today": "Dnes", "gross_percent_1y": "Jeden rok", "gross_percent_max": "Za celou dobu" }, @@ -770,8 +770,8 @@ }, "calibreweb": { "books": "Knihy", - "authors": "Authors", - "categories": "Categories", + "authors": "Autoři", + "categories": "Kategorie", "series": "Seriály" }, "jdownloader": { @@ -785,44 +785,44 @@ "totalFiles": "Soubory" }, "azuredevops": { - "result": "Result", + "result": "Výsledek", "status": "Stav", - "buildId": "Build ID", - "succeeded": "Succeeded", - "notStarted": "Not Started", + "buildId": "ID sestavení", + "succeeded": "Úspěšně", + "notStarted": "Nezahájeno", "failed": "Selhalo", - "canceled": "Canceled", - "inProgress": "In Progress", - "totalPrs": "Total PRs", - "myPrs": "My PRs", + "canceled": "Zrušeno", + "inProgress": "Probíhá", + "totalPrs": "Celkem PR", + "myPrs": "Moje PR", "approved": "Schváleno" }, "gamedig": { "status": "Stav", "online": "Online", "offline": "Offline", - "name": "Name", - "map": "Map", - "currentPlayers": "Current players", + "name": "Jméno", + "map": "Mapa", + "currentPlayers": "Počet hráčů", "players": "Hráči", - "maxPlayers": "Max players", - "bots": "Bots", + "maxPlayers": "Maximální počet hráčů", + "bots": "Boti", "ping": "Odezva" }, "urbackup": { "ok": "Ok", - "errored": "Errors", - "noRecent": "Out of Date", - "totalUsed": "Used Storage" + "errored": "Chyby", + "noRecent": "Zastaralý", + "totalUsed": "Využití úložiště" }, "mealie": { - "recipes": "Recipes", + "recipes": "Recepty", "users": "Uživatelé", - "categories": "Categories", - "tags": "Tags" + "categories": "Kategorie", + "tags": "Štítky" }, "openmediavault": { - "downloading": "Downloading", + "downloading": "Stahování", "total": "Celkem", "running": "Běží", "stopped": "Zastaveno", @@ -831,94 +831,95 @@ }, "openwrt": { "uptime": "Doba spuštění", - "cpuLoad": "CPU Load Avg (5m)", - "up": "Up", - "down": "Down", - "bytesTx": "Transmitted", + "cpuLoad": "Prům. zatížení procesoru (5m)", + "up": "Běží", + "down": "Výpadek", + "bytesTx": "Přeneseno", "bytesRx": "Přijaté" }, "uptimerobot": { "status": "Stav", "uptime": "Doba spuštění", - "lastDown": "Last Downtime", - "downDuration": "Downtime Duration", + "lastDown": "Poslední výpadek", + "downDuration": "Trvání výpadku", "sitesUp": "Stránky Up", "sitesDown": "Stránky Down", "paused": "Pozastaveno", - "notyetchecked": "Not Yet Checked", - "up": "Up", - "seemsdown": "Seems Down", - "down": "Down", + "notyetchecked": "Zatím nezkontrolováno", + "up": "Běží", + "seemsdown": "Zdá se nedostupný", + "down": "Výpadek", "unknown": "Neznámý" }, "calendar": { - "inCinemas": "In cinemas", - "physicalRelease": "Physical release", - "digitalRelease": "Digital release", - "noEventsToday": "No events for today!", - "noEventsFound": "No events found" + "inCinemas": "V kinech", + "physicalRelease": "Fyzické vydání", + "digitalRelease": "Digitální vydání", + "noEventsToday": "Pro dnešek žádné události!", + "noEventsFound": "Nemáte žádné události" }, "romm": { - "platforms": "Platforms", - "totalRoms": "Games", - "saves": "Saves", - "states": "States", - "screenshots": "Screenshots", - "totalfilesize": "Total Size" + "platforms": "Platformy", + "totalRoms": "Hry", + "saves": "Uložené", + "states": "Stavy", + "screenshots": "Snímky obrazovky", + "totalfilesize": "Celková velikost" }, "mailcow": { "domains": "Domény", - "mailboxes": "Mailboxes", - "mails": "Mails", + "mailboxes": "E-mailové schránky", + "mails": "Maily", "storage": "Úložiště" }, "netdata": { - "warnings": "Warnings", - "criticals": "Criticals" + "warnings": "Upozornění", + "criticals": "Kritické" }, "plantit": { - "events": "Events", - "plants": "Plants", + "events": "Události", + "plants": "Rostliny", "photos": "Fotografie", - "species": "Species" + "species": "Druhy" }, "gitea": { - "notifications": "Notifications", + "notifications": "Oznámení", "issues": "Problémy", - "pulls": "Pull Requests" + "pulls": "Pull Requests", + "repositories": "Repozitáře" }, "stash": { - "scenes": "Scenes", - "scenesPlayed": "Scenes Played", - "playCount": "Total Plays", - "playDuration": "Time Watched", - "sceneSize": "Scenes Size", - "sceneDuration": "Scenes Duration", - "images": "Images", - "imageSize": "Images Size", - "galleries": "Galleries", - "performers": "Performers", - "studios": "Studios", + "scenes": "Scény", + "scenesPlayed": "Přehrané scény", + "playCount": "Celkový počet přehrání", + "playDuration": "Čas sledování", + "sceneSize": "Velikost scén", + "sceneDuration": "Délka scény", + "images": "Obrázky", + "imageSize": "Velikost obrázků", + "galleries": "Galerie", + "performers": "Herci", + "studios": "Studia", "movies": "Filmy", - "tags": "Tags", - "oCount": "O Count" + "tags": "Štítky", + "oCount": "Počet O" }, "tandoor": { "users": "Uživatelé", - "recipes": "Recipes", - "keywords": "Keywords" + "recipes": "Recepty", + "keywords": "Klíčová slova" }, "homebox": { - "items": "Items", - "totalWithWarranty": "With Warranty", - "locations": "Locations", - "labels": "Labels", + "items": "Položky", + "totalWithWarranty": "Se zárukou", + "locations": "Lokality", + "labels": "Štítky", "users": "Uživatelé", - "totalValue": "Total Value" + "totalValue": "Celková hodnota" }, "crowdsec": { "alerts": "Upozornění", - "bans": "Bans" + "bans": "Bany" }, "wgeasy": { "connected": "", @@ -927,10 +928,10 @@ "total": "Celkem" }, "swagdashboard": { - "proxied": "Proxied", - "auth": "With Auth", - "outdated": "Outdated", - "banned": "Banned" + "proxied": "Přes proxy", + "auth": "S ověřením", + "outdated": "Zastaralé", + "banned": "Zabanován" }, "myspeed": { "ping": "Odezva", @@ -938,46 +939,46 @@ "upload": "Nahrávání" }, "stocks": { - "stocks": "Stocks", - "loading": "Loading", - "open": "Open - US Market", - "closed": "Closed - US Market", - "invalidConfiguration": "Invalid Configuration" + "stocks": "Akcie", + "loading": "Načítání", + "open": "Otevřeno - US trh", + "closed": "Uzavřeno - US trh", + "invalidConfiguration": "Neplatná konfigurace" }, "frigate": { - "cameras": "Cameras", + "cameras": "Kamery", "uptime": "Doba spuštění", "version": "Verze" }, "linkwarden": { - "links": "Links", - "collections": "Collections", - "tags": "Tags" + "links": "Linky", + "collections": "Sbírky", + "tags": "Štítky" }, "zabbix": { - "unclassified": "Not classified", + "unclassified": "Neklasifikováno", "information": "Informace", - "warning": "Warning", - "average": "Average", - "high": "High", - "disaster": "Disaster" + "warning": "Upozornění", + "average": "Průměr", + "high": "Vysoký", + "disaster": "Katastrofa" }, "lubelogger": { - "vehicle": "Vehicle", - "vehicles": "Vehicles", - "serviceRecords": "Service Records", - "reminders": "Reminders", - "nextReminder": "Next Reminder", - "none": "None" + "vehicle": "Vozidlo", + "vehicles": "Vozidla", + "serviceRecords": "Servisní záznamy", + "reminders": "Připomenutí", + "nextReminder": "Další připomenutí", + "none": "Žádné" }, "vikunja": { - "projects": "Active Projects", - "tasks7d": "Tasks Due This Week", - "tasksOverdue": "Overdue Tasks", - "tasksInProgress": "Tasks In Progress" + "projects": "Aktivní projekty", + "tasks7d": "Úkoly k dokončení tento týden", + "tasksOverdue": "Zpožděné úkoly", + "tasksInProgress": "Probíhají úkoly" }, "headscale": { - "name": "Name", + "name": "Jméno", "address": "Adresa", "last_seen": "Naposledy viděno", "status": "Stav", @@ -985,10 +986,10 @@ "offline": "Offline" }, "beszel": { - "name": "Name", - "systems": "Systems", - "up": "Up", - "down": "Down", + "name": "Jméno", + "systems": "Systém", + "up": "Běží", + "down": "Výpadek", "paused": "Pozastaveno", "pending": "Čeká", "status": "Stav", @@ -996,39 +997,50 @@ "cpu": "CPU", "memory": "RAM", "disk": "Disk", - "network": "NET" + "network": "Síť" }, "argocd": { - "apps": "Apps", - "synced": "Synced", - "outOfSync": "Out Of Sync", + "apps": "Aplikace", + "synced": "Synchronizováno", + "outOfSync": "Nesynchronizováno", "healthy": "Zdravý", - "degraded": "Degraded", - "progressing": "Progressing", + "degraded": "Degradováno", + "progressing": "Probíhá", "missing": "Chybějící", - "suspended": "Suspended" + "suspended": "Pozastaveno" }, "spoolman": { - "loading": "Loading" + "loading": "Načítání" }, "gitlab": { - "groups": "Groups", + "groups": "Skupiny", "issues": "Problémy", - "merges": "Merge Requests", - "projects": "Projects" + "merges": "Žádosti o sloučení", + "projects": "Projekty" }, "apcups": { "status": "Stav", "load": "Zatížení", - "bcharge": "Battery Charge", + "bcharge": "Úroveň baterie", "timeleft": "Zbývající čas" }, - "hoarder": { - "bookmarks": "Bookmarks", - "favorites": "Favorites", - "archived": "Archived", - "highlights": "Highlights", - "lists": "Lists", - "tags": "Tags" + "karakeep": { + "bookmarks": "Záložky", + "favorites": "Oblíbené", + "archived": "Archivováno", + "highlights": "Zvýraznění", + "lists": "Seznamy", + "tags": "Štítky" + }, + "slskd": { + "slskStatus": "Síť", + "connected": "", + "disconnected": "Odpojeno", + "updateStatus": "Aktualizace", + "update_yes": "Dostupné", + "update_no": "Žádné", + "downloads": "Stažení", + "uploads": "Nahrávání", + "sharedFiles": "Soubory" } } diff --git a/public/locales/da/common.json b/public/locales/da/common.json index 8a354b91..c7115af3 100644 --- a/public/locales/da/common.json +++ b/public/locales/da/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notifications", "issues": "Problemer", - "pulls": "Pull Requests" + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Scenes", @@ -1023,12 +1024,23 @@ "bcharge": "Batteriniveau", "timeleft": "Resterende tid" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Tags" + }, + "slskd": { + "slskStatus": "Network", + "connected": "Connected", + "disconnected": "Disconnected", + "updateStatus": "Update", + "update_yes": "Tilgængelig", + "update_no": "Opdateret", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Filer" } } diff --git a/public/locales/de/common.json b/public/locales/de/common.json index 69c0fe7c..6ea5a440 100644 --- a/public/locales/de/common.json +++ b/public/locales/de/common.json @@ -447,7 +447,7 @@ "write": "Schreiben", "gpu": "GPU", "mem": "RAM", - "swap": "Swap" + "swap": "Auslagerung" }, "quicklaunch": { "bookmark": "Lesezeichen", @@ -665,8 +665,8 @@ "storage": "Speicher" }, "uptimekuma": { - "up": "Seiten verfügbar", - "down": "Seiten nicht verfügbar", + "up": "Up", + "down": "Down", "uptime": "Betriebszeit", "incident": "Vorfall", "m": "min" @@ -744,8 +744,8 @@ "targets_total": "Alle Ziele" }, "gatus": { - "up": "Seiten verfügbar", - "down": "Seiten nicht verfügbar", + "up": "Up", + "down": "Down", "uptime": "Betriebszeit" }, "ghostfolio": { @@ -842,8 +842,8 @@ "uptime": "Betriebszeit", "lastDown": "Letzter Ausfall", "downDuration": "Ausfalldauer", - "sitesUp": "Seiten verfügbar", - "sitesDown": "Seiten nicht verfügbar", + "sitesUp": "Up", + "sitesDown": "Down", "paused": "Pausiert", "notyetchecked": "Noch nicht geprüft", "up": "Online", @@ -885,7 +885,8 @@ "gitea": { "notifications": "Benachrichtigungen", "issues": "Probleme", - "pulls": "Pull-Requests" + "pulls": "Pull-Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Szenen", @@ -1023,12 +1024,23 @@ "bcharge": "Akkuladung", "timeleft": "Verbleibende Zeit" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Schlagwörter" + }, + "slskd": { + "slskStatus": "Netzwerk", + "connected": "Verbunden", + "disconnected": "Getrennt", + "updateStatus": "Update", + "update_yes": "Verfügbar", + "update_no": "Aktuell", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Dateien" } } diff --git a/public/locales/el/common.json b/public/locales/el/common.json index c582f49f..ea1539d9 100644 --- a/public/locales/el/common.json +++ b/public/locales/el/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notifications", "issues": "Issues", - "pulls": "Pull Requests" + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Scenes", @@ -1023,12 +1024,23 @@ "bcharge": "Battery Charge", "timeleft": "Χρόνος που απομένει" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Ετικέτες" + }, + "slskd": { + "slskStatus": "Δίκτυο", + "connected": "Συνδέθηκε", + "disconnected": "Αποσυνδέθηκε", + "updateStatus": "Update", + "update_yes": "Διαθέσιμο", + "update_no": "Ενημερωμένο", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Αρχεία" } } diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 2bc4cf9c..09b9c2d3 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -883,9 +883,10 @@ "species": "Species" }, "gitea": { - "notifications": "Notifications", - "issues": "Issues", - "pulls": "Pull Requests" + "notifications": "Notifications", + "issues": "Issues", + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Scenes", @@ -1023,12 +1024,23 @@ "bcharge":"Battery Charge", "timeleft":"Time Left" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Tags" + }, + "slskd": { + "slskStatus": "Network", + "connected": "Connected", + "disconnected": "Disconnected", + "updateStatus": "Update", + "update_yes": "Available", + "update_no": "Up to Date", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Files" } } diff --git a/public/locales/eo/common.json b/public/locales/eo/common.json index 8a7bb831..f943d1c8 100644 --- a/public/locales/eo/common.json +++ b/public/locales/eo/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notifications", "issues": "Issues", - "pulls": "Pull Requests" + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Scenes", @@ -1023,12 +1024,23 @@ "bcharge": "Battery Charge", "timeleft": "Time Left" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Tags" + }, + "slskd": { + "slskStatus": "Network", + "connected": "Connected", + "disconnected": "Disconnected", + "updateStatus": "Update", + "update_yes": "Havebla", + "update_no": "Up to Date", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Files" } } diff --git a/public/locales/es/common.json b/public/locales/es/common.json index 9d23e343..76b03275 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -149,8 +149,8 @@ "received": "Recibido", "sent": "Enviado", "externalIPAddress": "IP ext.", - "externalIPv6Address": "Ext. IPv6", - "externalIPv6Prefix": "Ext. IPv6-Prefix" + "externalIPv6Address": "IPv6 ext.", + "externalIPv6Prefix": "Prefijo IPv6 ext." }, "caddy": { "upstreams": "Upstream (desarrollo de software)", @@ -178,7 +178,7 @@ "connectedAp": "AP conectados", "activeUser": "Dispositivos activos", "alerts": "Alertas", - "connectedGateways": "Connected gateways", + "connectedGateways": "Puertas de enlace conectadas", "connectedSwitches": "Conmutadores conectados" }, "nzbget": { @@ -705,8 +705,8 @@ "time": "Tiempo" }, "firefly": { - "networth": "Net Worth", - "budget": "Budget" + "networth": "Patrimonio neto", + "budget": "Presupuesto" }, "grafana": { "dashboards": "Tableros", @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notificaciones", "issues": "Números", - "pulls": "Solicitudes de cambios" + "pulls": "Solicitudes de cambios", + "repositories": "Repositorios" }, "stash": { "scenes": "Escenas", @@ -1023,12 +1024,23 @@ "bcharge": "Carga de la batería", "timeleft": "Tiempo restante" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Etiquetas" + }, + "slskd": { + "slskStatus": "Red", + "connected": "Conectado", + "disconnected": "Desconectado", + "updateStatus": "Actualización", + "update_yes": "Disponible", + "update_no": "Actualizado", + "downloads": "Descargas", + "uploads": "Subidas", + "sharedFiles": "Archivos" } } diff --git a/public/locales/eu/common.json b/public/locales/eu/common.json index c122d734..02d1150c 100644 --- a/public/locales/eu/common.json +++ b/public/locales/eu/common.json @@ -85,16 +85,16 @@ "ping": { "error": "Error", "ping": "Ping", - "down": "Down", - "up": "Up", + "down": "Behera", + "up": "Gora", "not_available": "Not Available" }, "siteMonitor": { "http_status": "HTTP status", "error": "Error", - "response": "Response", - "down": "Down", - "up": "Up", + "response": "Erantzuna", + "down": "Behera", + "up": "Gora", "not_available": "Not Available" }, "emby": { @@ -102,8 +102,8 @@ "transcoding": "Transcoding", "bitrate": "Bit-tasa", "no_active": "No Active Streams", - "movies": "Movies", - "series": "Series", + "movies": "Filmak", + "series": "Serieak", "episodes": "Episodes", "songs": "Abestiak" }, @@ -115,39 +115,39 @@ "unknown": "Ezezaguna" }, "evcc": { - "pv_power": "Production", - "battery_soc": "Battery", - "grid_power": "Grid", - "home_power": "Consumption", - "charge_power": "Charger", + "pv_power": "Produkzioak", + "battery_soc": "Bateria", + "grid_power": "Sarea", + "home_power": "Kontsumoa", + "charge_power": "Kargagailua", "kilowatt": "kW" }, "flood": { - "download": "Download", - "upload": "Upload", + "download": "Jeitsierak", + "upload": "Kargatu", "leech": "Leech", "seed": "Seed" }, "freshrss": { - "subscriptions": "Subscriptions", - "unread": "Unread" + "subscriptions": "Harpidetzak", + "unread": "Irakurri gabe" }, "fritzbox": { "connectionStatus": "Status", "connectionStatusUnconfigured": "Unconfigured", - "connectionStatusConnecting": "Connecting", + "connectionStatusConnecting": "Konektatzen", "connectionStatusAuthenticating": "Authenticating", "connectionStatusPendingDisconnect": "Pending Disconnect", "connectionStatusDisconnecting": "Disconnecting", - "connectionStatusDisconnected": "Disconnected", - "connectionStatusConnected": "Connected", + "connectionStatusDisconnected": "Deskonektatuta", + "connectionStatusConnected": "Konektatuta", "uptime": "Uptime", "maxDown": "Max. Down", "maxUp": "Max. Up", - "down": "Down", - "up": "Up", + "down": "Behera", + "up": "Gora", "received": "Received", - "sent": "Sent", + "sent": "Bidalita", "externalIPAddress": "Ext. IP", "externalIPv6Address": "Ext. IPv6", "externalIPv6Prefix": "Ext. IPv6-Prefix" @@ -189,7 +189,7 @@ "plex": { "streams": "Active Streams", "albums": "Albums", - "movies": "Movies", + "movies": "Filmak", "tv": "TV Shows" }, "sabnzbd": { @@ -199,18 +199,18 @@ }, "rutorrent": { "active": "Active", - "upload": "Upload", - "download": "Download" + "upload": "Kargatu", + "download": "Jeitsierak" }, "transmission": { - "download": "Download", - "upload": "Upload", + "download": "Jeitsierak", + "upload": "Kargatu", "leech": "Leech", "seed": "Seed" }, "qbittorrent": { - "download": "Download", - "upload": "Upload", + "download": "Jeitsierak", + "upload": "Kargatu", "leech": "Leech", "seed": "Seed" }, @@ -223,8 +223,8 @@ "invalid": "Invalid" }, "deluge": { - "download": "Download", - "upload": "Upload", + "download": "Jeitsierak", + "upload": "Kargatu", "leech": "Leech", "seed": "Seed" }, @@ -233,15 +233,15 @@ "cachemissbytes": "Cache Miss Bytes" }, "downloadstation": { - "download": "Download", - "upload": "Upload", + "download": "Jeitsierak", + "upload": "Kargatu", "leech": "Leech", "seed": "Seed" }, "sonarr": { "wanted": "Wanted", "queued": "Queued", - "series": "Series", + "series": "Serieak", "queue": "Queue", "unknown": "Ezezaguna" }, @@ -249,7 +249,7 @@ "wanted": "Wanted", "missing": "Missing", "queued": "Queued", - "movies": "Movies", + "movies": "Filmak", "queue": "Queue", "unknown": "Ezezaguna" }, @@ -285,7 +285,7 @@ }, "netalertx": { "total": "Guztira", - "connected": "Connected", + "connected": "Konektatuta", "new_devices": "New Devices", "down_alerts": "Down Alerts" }, @@ -302,8 +302,8 @@ "latency": "Latency" }, "speedtest": { - "upload": "Upload", - "download": "Download", + "upload": "Kargatu", + "download": "Jeitsierak", "ping": "Ping" }, "portainer": { @@ -315,7 +315,7 @@ "download": "Downloaded", "nondownload": "Non-Downloaded", "read": "Read", - "unread": "Unread", + "unread": "Irakurri gabe", "downloadedread": "Downloaded & Read", "downloadedunread": "Downloaded & Unread", "nondownloadedread": "Non-Downloaded & Read", @@ -405,7 +405,7 @@ "medusa": { "wanted": "Wanted", "queued": "Queued", - "series": "Series" + "series": "Serieak" }, "minecraft": { "players": "Jokalariak", @@ -416,7 +416,7 @@ }, "miniflux": { "read": "Read", - "unread": "Unread" + "unread": "Irakurri gabe" }, "authentik": { "users": "Users", @@ -523,15 +523,15 @@ "up_to_date": "Up to Date", "child_bridges": "Child Bridges", "child_bridges_status": "{{ok}}/{{total}}", - "up": "Up", + "up": "Gora", "pending": "Pending", - "down": "Down" + "down": "Behera" }, "healthchecks": { "new": "New", - "up": "Up", + "up": "Gora", "grace": "In Grace Period", - "down": "Down", + "down": "Behera", "paused": "Paused", "status": "Status", "last_ping": "Last Ping", @@ -646,8 +646,8 @@ "load": "Load Avg", "memory": "Mem Usage", "wanStatus": "WAN Status", - "up": "Up", - "down": "Down", + "up": "Gora", + "down": "Behera", "temp": "Temp", "disk": "Disk Usage", "wanIP": "WAN IP" @@ -660,7 +660,7 @@ }, "immich": { "users": "Users", - "photos": "Photos", + "photos": "Argazkiak", "videos": "Videos", "storage": "Storage" }, @@ -672,14 +672,14 @@ "m": "m" }, "atsumeru": { - "series": "Series", + "series": "Serieak", "archives": "Archives", "chapters": "Chapters", "categories": "Categories" }, "komga": { "libraries": "Libraries", - "series": "Series", + "series": "Serieak", "books": "Books" }, "diskstation": { @@ -688,13 +688,13 @@ "volumeAvailable": "Available" }, "mylar": { - "series": "Series", - "issues": "Issues", + "series": "Serieak", + "issues": "Arazoak", "wanted": "Wanted" }, "photoprism": { "albums": "Albums", - "photos": "Photos", + "photos": "Argazkiak", "videos": "Videos", "people": "People" }, @@ -772,7 +772,7 @@ "books": "Books", "authors": "Authors", "categories": "Categories", - "series": "Series" + "series": "Serieak" }, "jdownloader": { "downloadCount": "Queue", @@ -781,7 +781,7 @@ "downloadSpeed": "Speed" }, "kavita": { - "seriesCount": "Series", + "seriesCount": "Serieak", "totalFiles": "Files" }, "azuredevops": { @@ -801,8 +801,8 @@ "status": "Status", "online": "Online", "offline": "Offline", - "name": "Name", - "map": "Map", + "name": "Izena", + "map": "Mapa", "currentPlayers": "Current players", "players": "Jokalariak", "maxPlayers": "Max players", @@ -819,10 +819,10 @@ "recipes": "Recipes", "users": "Users", "categories": "Categories", - "tags": "Tags" + "tags": "Etiketak" }, "openmediavault": { - "downloading": "Downloading", + "downloading": "Deskargatzen", "total": "Guztira", "running": "Running", "stopped": "Stopped", @@ -832,8 +832,8 @@ "openwrt": { "uptime": "Uptime", "cpuLoad": "CPU Load Avg (5m)", - "up": "Up", - "down": "Down", + "up": "Gora", + "down": "Behera", "bytesTx": "Transmitted", "bytesRx": "Received" }, @@ -846,9 +846,9 @@ "sitesDown": "Sites Down", "paused": "Paused", "notyetchecked": "Not Yet Checked", - "up": "Up", + "up": "Gora", "seemsdown": "Seems Down", - "down": "Down", + "down": "Behera", "unknown": "Ezezaguna" }, "calendar": { @@ -856,7 +856,7 @@ "physicalRelease": "Physical release", "digitalRelease": "Digital release", "noEventsToday": "No events for today!", - "noEventsFound": "No events found" + "noEventsFound": "Ez da gertaerarik aurkitu." }, "romm": { "platforms": "Platforms", @@ -868,7 +868,7 @@ }, "mailcow": { "domains": "Domains", - "mailboxes": "Mailboxes", + "mailboxes": "Gutunontziak", "mails": "Mails", "storage": "Storage" }, @@ -877,15 +877,16 @@ "criticals": "Criticals" }, "plantit": { - "events": "Events", - "plants": "Plants", - "photos": "Photos", + "events": "Ekitaldiak", + "plants": "Landareak", + "photos": "Argazkiak", "species": "Species" }, "gitea": { - "notifications": "Notifications", - "issues": "Issues", - "pulls": "Pull Requests" + "notifications": "Jakinarazpenak", + "issues": "Arazoak", + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Scenes", @@ -894,34 +895,34 @@ "playDuration": "Time Watched", "sceneSize": "Scenes Size", "sceneDuration": "Scenes Duration", - "images": "Images", - "imageSize": "Images Size", + "images": "Irudia", + "imageSize": "Irudiaren tamaina", "galleries": "Galleries", "performers": "Performers", "studios": "Studios", - "movies": "Movies", - "tags": "Tags", + "movies": "Filmak", + "tags": "Etiketak", "oCount": "O Count" }, "tandoor": { "users": "Users", "recipes": "Recipes", - "keywords": "Keywords" + "keywords": "Hitz gakoak" }, "homebox": { - "items": "Items", + "items": "Elementuak", "totalWithWarranty": "With Warranty", "locations": "Locations", - "labels": "Labels", + "labels": "Etiketak", "users": "Users", - "totalValue": "Total Value" + "totalValue": "Guztira" }, "crowdsec": { "alerts": "Alerts", "bans": "Bans" }, "wgeasy": { - "connected": "Connected", + "connected": "Konektatuta", "enabled": "Enabled", "disabled": "Disabled", "total": "Guztira" @@ -934,8 +935,8 @@ }, "myspeed": { "ping": "Ping", - "download": "Download", - "upload": "Upload" + "download": "Jeitsierak", + "upload": "Kargatu" }, "stocks": { "stocks": "Stocks", @@ -951,23 +952,23 @@ }, "linkwarden": { "links": "Links", - "collections": "Collections", - "tags": "Tags" + "collections": "Bildumak", + "tags": "Etiketak" }, "zabbix": { "unclassified": "Not classified", "information": "Informazioa", - "warning": "Warning", - "average": "Average", - "high": "High", + "warning": "Abisua", + "average": "Batez besteko", + "high": "Altua", "disaster": "Disaster" }, "lubelogger": { "vehicle": "Vehicle", - "vehicles": "Vehicles", + "vehicles": "Ibilgailuak", "serviceRecords": "Service Records", - "reminders": "Reminders", - "nextReminder": "Next Reminder", + "reminders": "Oroigarriak", + "nextReminder": "Hurrengo abisua", "none": "None" }, "vikunja": { @@ -977,7 +978,7 @@ "tasksInProgress": "Tasks In Progress" }, "headscale": { - "name": "Name", + "name": "Izena", "address": "Address", "last_seen": "Last Seen", "status": "Status", @@ -985,10 +986,10 @@ "offline": "Offline" }, "beszel": { - "name": "Name", + "name": "Izena", "systems": "Systems", - "up": "Up", - "down": "Down", + "up": "Gora", + "down": "Behera", "paused": "Paused", "pending": "Pending", "status": "Status", @@ -999,23 +1000,23 @@ "network": "NET" }, "argocd": { - "apps": "Apps", - "synced": "Synced", + "apps": "Aplikazioak", + "synced": "Sinkronizatuta", "outOfSync": "Out Of Sync", "healthy": "Osasuntsu", "degraded": "Degraded", "progressing": "Progressing", "missing": "Missing", - "suspended": "Suspended" + "suspended": "Etenda" }, "spoolman": { "loading": "Loading" }, "gitlab": { - "groups": "Groups", - "issues": "Issues", + "groups": "Taldeak", + "issues": "Arazoak", "merges": "Merge Requests", - "projects": "Projects" + "projects": "Proiektuak" }, "apcups": { "status": "Status", @@ -1023,12 +1024,23 @@ "bcharge": "Battery Charge", "timeleft": "Time Left" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", - "tags": "Tags" + "tags": "Etiketak" + }, + "slskd": { + "slskStatus": "Network", + "connected": "Konektatuta", + "disconnected": "Deskonektatuta", + "updateStatus": "Update", + "update_yes": "Available", + "update_no": "Up to Date", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Files" } } diff --git a/public/locales/fi/common.json b/public/locales/fi/common.json index 782bc2c4..6139aea6 100644 --- a/public/locales/fi/common.json +++ b/public/locales/fi/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notifications", "issues": "Issues", - "pulls": "Pull Requests" + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Scenes", @@ -1023,12 +1024,23 @@ "bcharge": "Battery Charge", "timeleft": "Aikaa jäljellä" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Tags" + }, + "slskd": { + "slskStatus": "Network", + "connected": "Connected", + "disconnected": "Disconnected", + "updateStatus": "Update", + "update_yes": "Saatavilla", + "update_no": "Up to Date", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Files" } } diff --git a/public/locales/fr/common.json b/public/locales/fr/common.json index 191706b2..e7bc248a 100644 --- a/public/locales/fr/common.json +++ b/public/locales/fr/common.json @@ -85,16 +85,16 @@ "ping": { "error": "Erreur", "ping": "Latence", - "down": "Bas", - "up": "Haut", + "down": "Down", + "up": "Up", "not_available": "Non disponible" }, "siteMonitor": { "http_status": "Statut HTTP", "error": "Erreur", "response": "Réponse", - "down": "Bas", - "up": "Haut", + "down": "Down", + "up": "Up", "not_available": "Non disponible" }, "emby": { @@ -142,15 +142,15 @@ "connectionStatusDisconnected": "Déconnecté", "connectionStatusConnected": "Connecté", "uptime": "Démarré depuis", - "maxDown": "Max. Bas", - "maxUp": "Max. Haut", - "down": "Bas", - "up": "Haut", + "maxDown": "Max. Down", + "maxUp": "Max. Up", + "down": "Down", + "up": "Up", "received": "Reçu", "sent": "Envoyé", "externalIPAddress": "IP externe", - "externalIPv6Address": "Ext. IPv6", - "externalIPv6Prefix": "Ext. IPv6-Prefix" + "externalIPv6Address": "IPv6 externe", + "externalIPv6Prefix": "Préfixe IPv6 externe" }, "caddy": { "upstreams": "En amont", @@ -178,7 +178,7 @@ "connectedAp": "AP connectés", "activeUser": "Périphériques actifs", "alerts": "Alertes", - "connectedGateways": "Connected gateways", + "connectedGateways": "Passerelles connectées", "connectedSwitches": "Switchs connectés" }, "nzbget": { @@ -523,15 +523,15 @@ "up_to_date": "À jour", "child_bridges": "Child Bridges", "child_bridges_status": "{{ok}}/{{total}}", - "up": "Haut", + "up": "Up", "pending": "En attente", - "down": "Bas" + "down": "Down" }, "healthchecks": { "new": "Nouveau", - "up": "Haut", + "up": "Up", "grace": "En Période de Grâce", - "down": "Bas", + "down": "Down", "paused": "En Pause", "status": "Statut", "last_ping": "Dernier Ping", @@ -646,8 +646,8 @@ "load": "Charge moy.", "memory": "Util. Mém.", "wanStatus": "Statut WAN", - "up": "Haut", - "down": "Bas", + "up": "Up", + "down": "Down", "temp": "Température", "disk": "Util. Disque", "wanIP": "IP WAN" @@ -832,8 +832,8 @@ "openwrt": { "uptime": "Démarré depuis", "cpuLoad": "Charge moyenne CPU (5 min)", - "up": "Haut", - "down": "Bas", + "up": "Up", + "down": "Down", "bytesTx": "Transmis", "bytesRx": "Reçu" }, @@ -846,9 +846,9 @@ "sitesDown": "Hors ligne", "paused": "En Pause", "notyetchecked": "Non vérifié", - "up": "Haut", + "up": "Up", "seemsdown": "Semble hors ligne", - "down": "Bas", + "down": "Down", "unknown": "Inconnu" }, "calendar": { @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notifications", "issues": "Anomalies", - "pulls": "Demandes de tirage" + "pulls": "Demandes de tirage", + "repositories": "Dépôts" }, "stash": { "scenes": "Scènes", @@ -987,8 +988,8 @@ "beszel": { "name": "Nom", "systems": "Systèmes", - "up": "Haut", - "down": "Bas", + "up": "Up", + "down": "Down", "paused": "En Pause", "pending": "En attente", "status": "Statut", @@ -1023,12 +1024,23 @@ "bcharge": "Charge de la batterie", "timeleft": "Temps restant" }, - "hoarder": { - "bookmarks": "Bookmarks", - "favorites": "Favorites", - "archived": "Archived", + "karakeep": { + "bookmarks": "Marque-pages", + "favorites": "Favoris", + "archived": "Archivé", "highlights": "Highlights", - "lists": "Lists", + "lists": "Listes", "tags": "Étiquettes" + }, + "slskd": { + "slskStatus": "Réseau", + "connected": "Connecté", + "disconnected": "Déconnecté", + "updateStatus": "Mise à jour", + "update_yes": "Disponible", + "update_no": "À jour", + "downloads": "Téléchargements", + "uploads": "Téléversements", + "sharedFiles": "Fichiers" } } diff --git a/public/locales/he/common.json b/public/locales/he/common.json index 57ce66b9..fb338931 100644 --- a/public/locales/he/common.json +++ b/public/locales/he/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notifications", "issues": "Issues", - "pulls": "Pull Requests" + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Scenes", @@ -1023,12 +1024,23 @@ "bcharge": "Battery Charge", "timeleft": "זמן שנותר" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Tags" + }, + "slskd": { + "slskStatus": "Network", + "connected": "Connected", + "disconnected": "Disconnected", + "updateStatus": "Update", + "update_yes": "זמין", + "update_no": "Up to Date", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Files" } } diff --git a/public/locales/hi/common.json b/public/locales/hi/common.json index 0744578a..8897f217 100644 --- a/public/locales/hi/common.json +++ b/public/locales/hi/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notifications", "issues": "Issues", - "pulls": "Pull Requests" + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Scenes", @@ -1023,12 +1024,23 @@ "bcharge": "Battery Charge", "timeleft": "Time Left" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Tags" + }, + "slskd": { + "slskStatus": "Network", + "connected": "Connected", + "disconnected": "Disconnected", + "updateStatus": "Update", + "update_yes": "Available", + "update_no": "Up to Date", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Files" } } diff --git a/public/locales/hr/common.json b/public/locales/hr/common.json index 31f92935..036f746b 100644 --- a/public/locales/hr/common.json +++ b/public/locales/hr/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Obavijesti", "issues": "Problemi", - "pulls": "Zahtjevi za povlačenje" + "pulls": "Zahtjevi za povlačenje", + "repositories": "Repositories" }, "stash": { "scenes": "Scene", @@ -1023,12 +1024,23 @@ "bcharge": "Napunjenost baterije", "timeleft": "Preostalo vrijeme" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Oznake" + }, + "slskd": { + "slskStatus": "Mreža", + "connected": "Povezano", + "disconnected": "Odspojeno", + "updateStatus": "Update", + "update_yes": "Dostupno", + "update_no": "Aktualno", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Datoteke" } } diff --git a/public/locales/hu/common.json b/public/locales/hu/common.json index e21689aa..a3ab6bf8 100644 --- a/public/locales/hu/common.json +++ b/public/locales/hu/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Üzenetek", "issues": "Problémák", - "pulls": "Pull request-ek" + "pulls": "Pull request-ek", + "repositories": "Repositories" }, "stash": { "scenes": "Jelenetek", @@ -1023,12 +1024,23 @@ "bcharge": "Akku töltöttsége", "timeleft": "Hátralévő idő" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Címkék" + }, + "slskd": { + "slskStatus": "Hálózat", + "connected": "Csatlakozva", + "disconnected": "Kapcsolat bontva", + "updateStatus": "Update", + "update_yes": "Elérhető", + "update_no": "Naprakész", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Fájlok" } } diff --git a/public/locales/id/common.json b/public/locales/id/common.json index 7d049bec..9babbe5a 100644 --- a/public/locales/id/common.json +++ b/public/locales/id/common.json @@ -342,7 +342,7 @@ "totalNxDomain": "Domain NX", "totalRefused": "Ditolak", "totalAuthoritative": "Authoritative", - "totalRecursive": "Recursive", + "totalRecursive": "Rekursif", "totalCached": "Cached", "totalBlocked": "Terblokir", "totalDropped": "Dropped", @@ -705,8 +705,8 @@ "time": "Waktu" }, "firefly": { - "networth": "Net Worth", - "budget": "Budget" + "networth": "Kekayaan Bersih", + "budget": "Anggaran" }, "grafana": { "dashboards": "Dasbor", @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notifikasi", "issues": "Isu", - "pulls": "Pull Requests" + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Adegan", @@ -965,7 +966,7 @@ "lubelogger": { "vehicle": "Kendaraan", "vehicles": "Kendaraan", - "serviceRecords": "Service Records", + "serviceRecords": "Catatan Servis", "reminders": "Pengingat", "nextReminder": "Pengingat Berikutnya", "none": "Tidak ada" @@ -1023,12 +1024,23 @@ "bcharge": "Sisa Baterai", "timeleft": "Sisa Waktu" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Tag" + }, + "slskd": { + "slskStatus": "Jaringan", + "connected": "Tersambung", + "disconnected": "Terputus", + "updateStatus": "Update", + "update_yes": "Tersedia", + "update_no": "Terbaru", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "File" } } diff --git a/public/locales/it/common.json b/public/locales/it/common.json index 3d0dc450..6e870a09 100644 --- a/public/locales/it/common.json +++ b/public/locales/it/common.json @@ -149,8 +149,8 @@ "received": "Ricevuti", "sent": "Inviati", "externalIPAddress": "IP Esterno", - "externalIPv6Address": "Ext. IPv6", - "externalIPv6Prefix": "Ext. IPv6-Prefix" + "externalIPv6Address": "IPv6 Esterno", + "externalIPv6Prefix": "Prefisso IPv6 Esterno" }, "caddy": { "upstreams": "Upstream", @@ -178,7 +178,7 @@ "connectedAp": "AP Connessi", "activeUser": "Dispositivi attivi", "alerts": "Allarmi", - "connectedGateways": "Connected gateways", + "connectedGateways": "Gateway connessi", "connectedSwitches": "Switch connessi" }, "nzbget": { @@ -338,7 +338,7 @@ "technitium": { "totalQueries": "Richieste", "totalNoError": "Successo", - "totalServerFailure": "Failures", + "totalServerFailure": "Fallimenti", "totalNxDomain": "NX Domains", "totalRefused": "Refused", "totalAuthoritative": "Authoritative", @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notifiche", "issues": "Problemi", - "pulls": "Richieste di Pull" + "pulls": "Richieste di Pull", + "repositories": "Repositories" }, "stash": { "scenes": "Scene", @@ -942,7 +943,7 @@ "loading": "Caricamento", "open": "Open - US Market", "closed": "Closed - US Market", - "invalidConfiguration": "Invalid Configuration" + "invalidConfiguration": "Configurazione non valida" }, "frigate": { "cameras": "Cameras", @@ -958,7 +959,7 @@ "unclassified": "Not classified", "information": "Informazioni", "warning": "Warning", - "average": "Average", + "average": "Media", "high": "High", "disaster": "Disaster" }, @@ -986,7 +987,7 @@ }, "beszel": { "name": "Nome", - "systems": "Systems", + "systems": "Sistemi", "up": "Up", "down": "Down", "paused": "In Pausa", @@ -995,15 +996,15 @@ "updated": "Aggiornato", "cpu": "CPU", "memory": "MEM", - "disk": "Disk", + "disk": "Disco", "network": "NET" }, "argocd": { - "apps": "Apps", - "synced": "Synced", - "outOfSync": "Out Of Sync", + "apps": "Applicazioni", + "synced": "Sincronizzato", + "outOfSync": "Non Sincronizzato", "healthy": "Sano", - "degraded": "Degraded", + "degraded": "Degradato", "progressing": "Progressing", "missing": "Mancanti", "suspended": "Suspended" @@ -1012,10 +1013,10 @@ "loading": "Caricamento" }, "gitlab": { - "groups": "Groups", + "groups": "Gruppi", "issues": "Problemi", - "merges": "Merge Requests", - "projects": "Projects" + "merges": "Richieste di merge", + "projects": "Progetti" }, "apcups": { "status": "Stato", @@ -1023,12 +1024,23 @@ "bcharge": "Carica Batteria", "timeleft": "Tempo Rimanente" }, - "hoarder": { - "bookmarks": "Bookmarks", - "favorites": "Favorites", + "karakeep": { + "bookmarks": "Segnalibri", + "favorites": "Preferiti", "archived": "Archived", "highlights": "Highlights", - "lists": "Lists", + "lists": "Liste", "tags": "Tag" + }, + "slskd": { + "slskStatus": "Rete", + "connected": "Connesso", + "disconnected": "Disconnesso", + "updateStatus": "Update", + "update_yes": "Disponibili", + "update_no": "Aggiornato", + "downloads": "Download", + "uploads": "Uploads", + "sharedFiles": "File" } } diff --git a/public/locales/ja/common.json b/public/locales/ja/common.json index 020d7d3b..5e963a77 100644 --- a/public/locales/ja/common.json +++ b/public/locales/ja/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "通知", "issues": "課題", - "pulls": "プルリクエスト" + "pulls": "プルリクエスト", + "repositories": "Repositories" }, "stash": { "scenes": "シーン", @@ -1023,12 +1024,23 @@ "bcharge": "バッテリー充電", "timeleft": "残り時間" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "タグ" + }, + "slskd": { + "slskStatus": "ネットワーク", + "connected": "接続済", + "disconnected": "切断されました", + "updateStatus": "Update", + "update_yes": "利用可", + "update_no": "最新", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "ファイル" } } diff --git a/public/locales/ko/common.json b/public/locales/ko/common.json index 00ff2ea1..8bfe4276 100644 --- a/public/locales/ko/common.json +++ b/public/locales/ko/common.json @@ -14,11 +14,11 @@ "date": "{{value, date}}", "relativeDate": "{{value, relativeDate}}", "duration": "{{value, duration}}", - "months": "mo", - "days": "d", - "hours": "h", - "minutes": "m", - "seconds": "s" + "months": "달", + "days": "일", + "hours": "시", + "minutes": "분", + "seconds": "초" }, "widget": { "missing_type": "없는 위젯 유형: {{type}}", @@ -51,7 +51,7 @@ }, "unifi": { "users": "사용자", - "uptime": "Uptime", + "uptime": "가동 시간", "days": "일", "wan": "WAN", "lan": "LAN", @@ -141,7 +141,7 @@ "connectionStatusDisconnecting": "연결을 끊는 중...", "connectionStatusDisconnected": "연결 끊김", "connectionStatusConnected": "연결됨", - "uptime": "Uptime", + "uptime": "가동 시간", "maxDown": "Max. Down", "maxUp": "Max. Up", "down": "Down", @@ -188,7 +188,7 @@ }, "plex": { "streams": "활성 스트림", - "albums": "Albums", + "albums": "앨범", "movies": "영화", "tv": "TV 쇼" }, @@ -440,8 +440,8 @@ "total": "총합", "free": "남음", "used": "사용", - "days": "d", - "hours": "h", + "days": "일", + "hours": "시", "crit": "Crit", "read": "읽음", "write": "쓰기", @@ -556,7 +556,7 @@ }, "truenas": { "load": "System Load", - "uptime": "Uptime", + "uptime": "가동 시간", "alerts": "경고" }, "pyload": { @@ -606,7 +606,7 @@ "mikrotik": { "cpuLoad": "CPU Load", "memoryUsed": "메모리 사용량", - "uptime": "Uptime", + "uptime": "가동 시간", "numberOfLeases": "Leases" }, "xteve": { @@ -667,9 +667,9 @@ "uptimekuma": { "up": "Sites Up", "down": "Sites Down", - "uptime": "Uptime", + "uptime": "가동 시간", "incident": "Incident", - "m": "m" + "m": "분" }, "atsumeru": { "series": "시리즈", @@ -684,7 +684,7 @@ }, "diskstation": { "days": "일", - "uptime": "Uptime", + "uptime": "가동 시간", "volumeAvailable": "이용 가능" }, "mylar": { @@ -693,7 +693,7 @@ "wanted": "요청" }, "photoprism": { - "albums": "Albums", + "albums": "앨범", "photos": "사진", "videos": "동영상", "people": "People" @@ -705,8 +705,8 @@ "time": "Time" }, "firefly": { - "networth": "Net Worth", - "budget": "Budget" + "networth": "순자산", + "budget": "예산" }, "grafana": { "dashboards": "대시보드", @@ -746,7 +746,7 @@ "gatus": { "up": "Sites Up", "down": "Sites Down", - "uptime": "Uptime" + "uptime": "가동 시간" }, "ghostfolio": { "gross_percent_today": "오늘", @@ -816,7 +816,7 @@ "totalUsed": "Used Storage" }, "mealie": { - "recipes": "Recipes", + "recipes": "레시피", "users": "사용자", "categories": "분류", "tags": "태그" @@ -830,7 +830,7 @@ "failed": "Failed" }, "openwrt": { - "uptime": "Uptime", + "uptime": "가동 시간", "cpuLoad": "CPU Load Avg (5m)", "up": "Up", "down": "Down", @@ -839,7 +839,7 @@ }, "uptimerobot": { "status": "상태", - "uptime": "Uptime", + "uptime": "가동 시간", "lastDown": "Last Downtime", "downDuration": "Downtime Duration", "sitesUp": "Sites Up", @@ -885,7 +885,8 @@ "gitea": { "notifications": "알림", "issues": "Issues", - "pulls": "Pull Requests" + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "장면", @@ -905,7 +906,7 @@ }, "tandoor": { "users": "사용자", - "recipes": "Recipes", + "recipes": "레시피", "keywords": "키워드" }, "homebox": { @@ -946,7 +947,7 @@ }, "frigate": { "cameras": "카메라", - "uptime": "Uptime", + "uptime": "가동 시간", "version": "버전" }, "linkwarden": { @@ -1023,12 +1024,23 @@ "bcharge": "배터리 충전 중", "timeleft": "남은 시간" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "태그" + }, + "slskd": { + "slskStatus": "네트워크", + "connected": "연결됨", + "disconnected": "연결 끊김", + "updateStatus": "Update", + "update_yes": "이용 가능", + "update_no": "최신 상태", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "파일" } } diff --git a/public/locales/lv/common.json b/public/locales/lv/common.json index 538febf1..0238d143 100644 --- a/public/locales/lv/common.json +++ b/public/locales/lv/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notifications", "issues": "Issues", - "pulls": "Pull Requests" + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Scenes", @@ -1023,12 +1024,23 @@ "bcharge": "Battery Charge", "timeleft": "Atlikušais laiks" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Tags" + }, + "slskd": { + "slskStatus": "Network", + "connected": "Connected", + "disconnected": "Disconnected", + "updateStatus": "Update", + "update_yes": "Available", + "update_no": "Up to Date", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Files" } } diff --git a/public/locales/ms/common.json b/public/locales/ms/common.json index ba32381f..8c0e5509 100644 --- a/public/locales/ms/common.json +++ b/public/locales/ms/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notifications", "issues": "Issues", - "pulls": "Pull Requests" + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Adegan", @@ -1023,12 +1024,23 @@ "bcharge": "Bateri dicas", "timeleft": "Masa Tinggal" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Tanda nama" + }, + "slskd": { + "slskStatus": "Rangkaian", + "connected": "Connected", + "disconnected": "Sambungan Terputus", + "updateStatus": "Update", + "update_yes": "Sudah Ada", + "update_no": "Terkemaskini", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Files" } } diff --git a/public/locales/nl/common.json b/public/locales/nl/common.json index dfa15f10..63a2d50e 100644 --- a/public/locales/nl/common.json +++ b/public/locales/nl/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notificaties", "issues": "Problemen", - "pulls": "Pull Requests" + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Scènes", @@ -1023,12 +1024,23 @@ "bcharge": "Batterij opladen", "timeleft": "Resterende Tijd" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Label" + }, + "slskd": { + "slskStatus": "Netwerk", + "connected": "Verbonden", + "disconnected": "Verbinding verbroken", + "updateStatus": "Update", + "update_yes": "Beschikbaar", + "update_no": "Bijgewerkt", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Bestanden" } } diff --git a/public/locales/no/common.json b/public/locales/no/common.json index b179110b..dee02141 100644 --- a/public/locales/no/common.json +++ b/public/locales/no/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Varslinger", "issues": "Issues", - "pulls": "Forespørsel" + "pulls": "Forespørsel", + "repositories": "Repositories" }, "stash": { "scenes": "Scener", @@ -1023,12 +1024,23 @@ "bcharge": "Batteriladning", "timeleft": "Gjenstående tid" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Stikkord" + }, + "slskd": { + "slskStatus": "Nettverk", + "connected": "Tilkoblet", + "disconnected": "Frakoblet", + "updateStatus": "Update", + "update_yes": "Tilgjengelig", + "update_no": "Oppdatert", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Files" } } diff --git a/public/locales/pl/common.json b/public/locales/pl/common.json index 9d669f8a..3a956aaf 100644 --- a/public/locales/pl/common.json +++ b/public/locales/pl/common.json @@ -149,8 +149,8 @@ "received": "Odebrane", "sent": "Wysłane", "externalIPAddress": "Pub. IP", - "externalIPv6Address": "Ext. IPv6", - "externalIPv6Prefix": "Ext. IPv6-Prefix" + "externalIPv6Address": "Zewn. IPv6", + "externalIPv6Prefix": "Zewn. prefiks IPv6" }, "caddy": { "upstreams": "Upstreams", @@ -705,8 +705,8 @@ "time": "Czas" }, "firefly": { - "networth": "Net Worth", - "budget": "Budget" + "networth": "Wartość netto", + "budget": "Budżet" }, "grafana": { "dashboards": "Panel główny", @@ -885,7 +885,8 @@ "gitea": { "notifications": "Powiadomienia", "issues": "Zgłoszenia", - "pulls": "Żądania Pull" + "pulls": "Żądania Pull", + "repositories": "Repozytoria" }, "stash": { "scenes": "Sceny", @@ -1023,12 +1024,23 @@ "bcharge": "Stan baterii", "timeleft": "Pozostało" }, - "hoarder": { - "bookmarks": "Bookmarks", - "favorites": "Favorites", - "archived": "Archived", - "highlights": "Highlights", - "lists": "Lists", + "karakeep": { + "bookmarks": "Zakładki", + "favorites": "Ulubione", + "archived": "Zarchiwizowane", + "highlights": "Wyróżnione", + "lists": "Listy", "tags": "Tagi" + }, + "slskd": { + "slskStatus": "Sieć", + "connected": "Połączono", + "disconnected": "Rozłączono", + "updateStatus": "Update", + "update_yes": "Dostępne", + "update_no": "Aktualny", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Pliki" } } diff --git a/public/locales/pt/common.json b/public/locales/pt/common.json index 66439545..c392c17d 100644 --- a/public/locales/pt/common.json +++ b/public/locales/pt/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notificações", "issues": "Problemas", - "pulls": "Solicitar pull" + "pulls": "Solicitar pull", + "repositories": "Repositories" }, "stash": { "scenes": "Cenas", @@ -1023,12 +1024,23 @@ "bcharge": "Carga da bateria", "timeleft": "Tempo Restante" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Etiquetas" + }, + "slskd": { + "slskStatus": "Rede", + "connected": "Conectado", + "disconnected": "Desconectado", + "updateStatus": "Update", + "update_yes": "Disponível", + "update_no": "Atualizado", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Ficheiros" } } diff --git a/public/locales/pt_BR/common.json b/public/locales/pt_BR/common.json index 23c5c3dc..ee426052 100644 --- a/public/locales/pt_BR/common.json +++ b/public/locales/pt_BR/common.json @@ -47,7 +47,7 @@ "load": "Carga", "temp": "TEMP", "max": "Máximo", - "uptime": "CIMA" + "uptime": "ATIVO" }, "unifi": { "users": "Usuários", @@ -61,7 +61,7 @@ "wlan_devices": "Dispositivos WLAN", "lan_users": "Usuários de LAN", "wlan_users": "Usuários de WLAN", - "up": "CIMA", + "up": "ATIVO", "down": "Desligado", "wait": "Por favor, aguarde", "empty_data": "Status do Subsistema desconhecido" @@ -149,8 +149,8 @@ "received": "Recebido", "sent": "Enviado", "externalIPAddress": "IP Externo", - "externalIPv6Address": "Ext. IPv6", - "externalIPv6Prefix": "Ext. IPv6-Prefix" + "externalIPv6Address": "IPv6 Externo", + "externalIPv6Prefix": "Prefixo IPv6 Externo" }, "caddy": { "upstreams": "Streams de Envio", @@ -178,7 +178,7 @@ "connectedAp": "APs Ligados", "activeUser": "Dispositivos ativos", "alerts": "Alertas", - "connectedGateways": "Connected gateways", + "connectedGateways": "Gateways conectados", "connectedSwitches": "Switches conectados" }, "nzbget": { @@ -229,8 +229,8 @@ "seed": "Semente" }, "develancacheui": { - "cachehitbytes": "Cache Hit Bytes", - "cachemissbytes": "Cache Miss Bytes" + "cachehitbytes": "Bytes de Acerto de Cache", + "cachemissbytes": "Bytes de Falha de Cache" }, "downloadstation": { "download": "Descarregar", @@ -313,13 +313,13 @@ }, "suwayomi": { "download": "Baixado", - "nondownload": "Non-Downloaded", + "nondownload": "Não Baixado", "read": "Lido", "unread": "Não lida", - "downloadedread": "Downloaded & Read", - "downloadedunread": "Downloaded & Unread", - "nondownloadedread": "Non-Downloaded & Read", - "nondownloadedunread": "Non-Downloaded & Unread" + "downloadedread": "Baixado e Lido", + "downloadedunread": "Baixado e Não Lido", + "nondownloadedread": "Não Baixado e Lido", + "nondownloadedunread": "Não Baixado e Não Lido" }, "tailscale": { "address": "Endereço", @@ -337,15 +337,15 @@ }, "technitium": { "totalQueries": "Consultas", - "totalNoError": "Success", - "totalServerFailure": "Failures", - "totalNxDomain": "NX Domains", - "totalRefused": "Refused", - "totalAuthoritative": "Authoritative", - "totalRecursive": "Recursive", - "totalCached": "Cached", + "totalNoError": "Sucesso", + "totalServerFailure": "Falhas", + "totalNxDomain": "Domínios NX", + "totalRefused": "Recusado", + "totalAuthoritative": "Autoritativo", + "totalRecursive": "Recursivo", + "totalCached": "Em cache", "totalBlocked": "Bloqueado", - "totalDropped": "Dropped", + "totalDropped": "Perdidos", "totalClients": "Clientes" }, "tdarr": { @@ -436,7 +436,7 @@ "temp": "TEMP", "_temp": "Temperatura", "warn": "Aviso", - "uptime": "CIMA", + "uptime": "ATIVO", "total": "Total", "free": "Livre", "used": "Utilizado", @@ -705,8 +705,8 @@ "time": "Hora" }, "firefly": { - "networth": "Net Worth", - "budget": "Budget" + "networth": "Valor Líquido", + "budget": "Orçamento" }, "grafana": { "dashboards": "Painéis", @@ -860,16 +860,16 @@ }, "romm": { "platforms": "Plataformas", - "totalRoms": "Games", + "totalRoms": "Jogos", "saves": "Saves", - "states": "States", - "screenshots": "Screenshots", - "totalfilesize": "Total Size" + "states": "Estados", + "screenshots": "Capturas de Tela", + "totalfilesize": "Tamanho total" }, "mailcow": { "domains": "Domínios", - "mailboxes": "Mailboxes", - "mails": "Mails", + "mailboxes": "Caixas de e-mail", + "mails": "Mensagens", "storage": "Armazenamento" }, "netdata": { @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notificações", "issues": "Problemas", - "pulls": "Solicitações de Envio" + "pulls": "Solicitações de Envio", + "repositories": "Repositórios" }, "stash": { "scenes": "Cenas", @@ -951,30 +952,30 @@ }, "linkwarden": { "links": "Links", - "collections": "Collections", + "collections": "Coleções", "tags": "Marcadores" }, "zabbix": { - "unclassified": "Not classified", + "unclassified": "Não classificado", "information": "Informação", - "warning": "Warning", - "average": "Average", - "high": "High", - "disaster": "Disaster" + "warning": "Aviso", + "average": "Médio", + "high": "Alto", + "disaster": "Desastre" }, "lubelogger": { - "vehicle": "Vehicle", - "vehicles": "Vehicles", - "serviceRecords": "Service Records", - "reminders": "Reminders", - "nextReminder": "Next Reminder", - "none": "None" + "vehicle": "Veículo", + "vehicles": "Veículos", + "serviceRecords": "Registros de Serviço", + "reminders": "Lembretes", + "nextReminder": "Próximo Lembrete", + "none": "Nenhum" }, "vikunja": { - "projects": "Active Projects", - "tasks7d": "Tasks Due This Week", - "tasksOverdue": "Overdue Tasks", - "tasksInProgress": "Tasks In Progress" + "projects": "Projetos Ativos", + "tasks7d": "Tarefas que vencem nesta semana", + "tasksOverdue": "Tarefas Atrasadas", + "tasksInProgress": "Tarefas em Andamento" }, "headscale": { "name": "Nome", @@ -986,7 +987,7 @@ }, "beszel": { "name": "Nome", - "systems": "Systems", + "systems": "Sistemas", "up": "Ativo", "down": "Inativo", "paused": "Pausado", @@ -995,27 +996,27 @@ "updated": "Atualizado", "cpu": "CPU", "memory": "MEM", - "disk": "Disk", - "network": "NET" + "disk": "Disco", + "network": "Rede" }, "argocd": { - "apps": "Apps", - "synced": "Synced", - "outOfSync": "Out Of Sync", + "apps": "Aplicativos", + "synced": "Sincronizado", + "outOfSync": "Fora de sincronia", "healthy": "Saudável", - "degraded": "Degraded", - "progressing": "Progressing", + "degraded": "Degradado", + "progressing": "Progredindo", "missing": "Faltando", - "suspended": "Suspended" + "suspended": "Suspenso" }, "spoolman": { "loading": "Carregando" }, "gitlab": { - "groups": "Groups", + "groups": "Grupos", "issues": "Problemas", - "merges": "Merge Requests", - "projects": "Projects" + "merges": "Solicitações de mesclagem", + "projects": "Projetos" }, "apcups": { "status": "Status", @@ -1023,12 +1024,23 @@ "bcharge": "Carga da bateria", "timeleft": "Tempo restante" }, - "hoarder": { - "bookmarks": "Bookmarks", - "favorites": "Favorites", - "archived": "Archived", - "highlights": "Highlights", - "lists": "Lists", + "karakeep": { + "bookmarks": "Marcadores", + "favorites": "Favoritos", + "archived": "Arquivados", + "highlights": "Destaques", + "lists": "Listas", "tags": "Marcadores" + }, + "slskd": { + "slskStatus": "Rede", + "connected": "Conectado", + "disconnected": "Desconectado", + "updateStatus": "Atualize", + "update_yes": "Disponível", + "update_no": "Atualizado", + "downloads": "Transferências", + "uploads": "Envios", + "sharedFiles": "Arquivos" } } diff --git a/public/locales/ro/common.json b/public/locales/ro/common.json index 4d38502d..9dcd2921 100644 --- a/public/locales/ro/common.json +++ b/public/locales/ro/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notifications", "issues": "Issues", - "pulls": "Pull Requests" + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Scenes", @@ -1023,12 +1024,23 @@ "bcharge": "Battery Charge", "timeleft": "Timp rămas" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Tags" + }, + "slskd": { + "slskStatus": "Network", + "connected": "Connected", + "disconnected": "Disconnected", + "updateStatus": "Update", + "update_yes": "Disponibile", + "update_no": "Up to Date", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Files" } } diff --git a/public/locales/ru/common.json b/public/locales/ru/common.json index 72785a96..d6cabab4 100644 --- a/public/locales/ru/common.json +++ b/public/locales/ru/common.json @@ -149,8 +149,8 @@ "received": "Получено", "sent": "Отправлено", "externalIPAddress": "Внеш. IP", - "externalIPv6Address": "Ext. IPv6", - "externalIPv6Prefix": "Ext. IPv6-Prefix" + "externalIPv6Address": "Внешний IPv6", + "externalIPv6Prefix": "Внешний IPv6 префикс" }, "caddy": { "upstreams": "Входящие каналы", @@ -178,7 +178,7 @@ "connectedAp": "Подключенные точки доступа", "activeUser": "Активные устройства", "alerts": "Предупреждения", - "connectedGateways": "Connected gateways", + "connectedGateways": "Подключенные шлюзы", "connectedSwitches": "Подключенные коммутаторы" }, "nzbget": { @@ -705,8 +705,8 @@ "time": "Время" }, "firefly": { - "networth": "Net Worth", - "budget": "Budget" + "networth": "Общая средства", + "budget": "Бюджет" }, "grafana": { "dashboards": "Панели", @@ -861,7 +861,7 @@ "romm": { "platforms": "Платформы", "totalRoms": "Игры", - "saves": "Сейвы", + "saves": "Сохранения", "states": "Состояния", "screenshots": "Скриншоты", "totalfilesize": "Общий объем" @@ -885,7 +885,8 @@ "gitea": { "notifications": "Уведомления", "issues": "Вопросы", - "pulls": "Запросы на слияние (Pull Request)" + "pulls": "Запросы на слияние (Pull Request)", + "repositories": "Репозитории" }, "stash": { "scenes": "Сцены", @@ -927,7 +928,7 @@ "total": "Всего" }, "swagdashboard": { - "proxied": "Прокси", + "proxied": "Проксировано", "auth": "С Авторизацией", "outdated": "Устаревшие", "banned": "Заблокированные" @@ -958,17 +959,17 @@ "unclassified": "Не классифицировано", "information": "Информация", "warning": "Предупреждение", - "average": "Средняя", + "average": "Среднее", "high": "Высокая", - "disaster": "Чрезвычайная" + "disaster": "Чрезвычайное" }, "lubelogger": { - "vehicle": "Автомобиль", - "vehicles": "Автомобили", - "serviceRecords": "Сервисные работы", + "vehicle": "Транспорт", + "vehicles": "Транспорты", + "serviceRecords": "Сервисные записи", "reminders": "Напоминания", "nextReminder": "Следующее напоминание", - "none": "Нет" + "none": "Отсутствует" }, "vikunja": { "projects": "Активные Проекты", @@ -1023,12 +1024,23 @@ "bcharge": "Заряд батареи", "timeleft": "Осталось" }, - "hoarder": { - "bookmarks": "Bookmarks", - "favorites": "Favorites", - "archived": "Archived", - "highlights": "Highlights", - "lists": "Lists", + "karakeep": { + "bookmarks": "Закладки", + "favorites": "Избранное", + "archived": "Архив", + "highlights": "События", + "lists": "Список", "tags": "Теги" + }, + "slskd": { + "slskStatus": "Сеть", + "connected": "Подключено", + "disconnected": "Отключено", + "updateStatus": "Обновление", + "update_yes": "Доступно", + "update_no": "Последняя версия", + "downloads": "Скачивания", + "uploads": "Загрузки", + "sharedFiles": "Файлов" } } diff --git a/public/locales/sk/common.json b/public/locales/sk/common.json index 4272c51f..a267ad81 100644 --- a/public/locales/sk/common.json +++ b/public/locales/sk/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Oznámenia", "issues": "Problémy", - "pulls": "Pull requesty" + "pulls": "Pull requesty", + "repositories": "Repositories" }, "stash": { "scenes": "Scény", @@ -1023,12 +1024,23 @@ "bcharge": "Nabitie batérie", "timeleft": "Zostávajúci čas" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Štítky" + }, + "slskd": { + "slskStatus": "Sieť", + "connected": "Pripojené", + "disconnected": "Odpojené", + "updateStatus": "Update", + "update_yes": "Dostupné", + "update_no": "Aktuálny", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Súborov" } } diff --git a/public/locales/sl/common.json b/public/locales/sl/common.json index 34db459d..ba6f07b9 100644 --- a/public/locales/sl/common.json +++ b/public/locales/sl/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Obvestila", "issues": "Težave", - "pulls": "Zahteve za prenos" + "pulls": "Zahteve za prenos", + "repositories": "Repositories" }, "stash": { "scenes": "Scene", @@ -1023,12 +1024,23 @@ "bcharge": "Napolnjenost baterije", "timeleft": "Preostali čas" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Značke" + }, + "slskd": { + "slskStatus": "Omrežje", + "connected": "Povezan", + "disconnected": "Prekinjeno", + "updateStatus": "Update", + "update_yes": "Na voljo", + "update_no": "Posodobljeno", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Datotek" } } diff --git a/public/locales/sr/common.json b/public/locales/sr/common.json index ba50eef1..5314dc2b 100644 --- a/public/locales/sr/common.json +++ b/public/locales/sr/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notifications", "issues": "Issues", - "pulls": "Pull Requests" + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Scenes", @@ -1023,12 +1024,23 @@ "bcharge": "Battery Charge", "timeleft": "Time Left" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Tags" + }, + "slskd": { + "slskStatus": "Network", + "connected": "Connected", + "disconnected": "Disconnected", + "updateStatus": "Update", + "update_yes": "Available", + "update_no": "Up to Date", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Files" } } diff --git a/public/locales/sv/common.json b/public/locales/sv/common.json index ead80b0b..d389a937 100644 --- a/public/locales/sv/common.json +++ b/public/locales/sv/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notifications", "issues": "Issues", - "pulls": "Pull Requests" + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Scenes", @@ -1023,12 +1024,23 @@ "bcharge": "Battery Charge", "timeleft": "Tid kvar" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Tags" + }, + "slskd": { + "slskStatus": "Network", + "connected": "Connected", + "disconnected": "Disconnected", + "updateStatus": "Update", + "update_yes": "Tillgänglig", + "update_no": "Up to Date", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Files" } } diff --git a/public/locales/te/common.json b/public/locales/te/common.json index 2cd066a6..e980d4ba 100644 --- a/public/locales/te/common.json +++ b/public/locales/te/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notifications", "issues": "Issues", - "pulls": "Pull Requests" + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Scenes", @@ -1023,12 +1024,23 @@ "bcharge": "Battery Charge", "timeleft": "మిగిలి వున్న సమయం" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Tags" + }, + "slskd": { + "slskStatus": "Network", + "connected": "Connected", + "disconnected": "Disconnected", + "updateStatus": "Update", + "update_yes": "అందుబాటులో వున్నవి", + "update_no": "తాజాగా", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Files" } } diff --git a/public/locales/th/common.json b/public/locales/th/common.json index 42a0b6a2..1d88948b 100644 --- a/public/locales/th/common.json +++ b/public/locales/th/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notifications", "issues": "Issues", - "pulls": "Pull Requests" + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Scenes", @@ -1023,12 +1024,23 @@ "bcharge": "Battery Charge", "timeleft": "Time Left" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Tags" + }, + "slskd": { + "slskStatus": "Network", + "connected": "Connected", + "disconnected": "Disconnected", + "updateStatus": "Update", + "update_yes": "Available", + "update_no": "Up to Date", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Files" } } diff --git a/public/locales/tr/common.json b/public/locales/tr/common.json index 40611dac..19bd4540 100644 --- a/public/locales/tr/common.json +++ b/public/locales/tr/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Bildirimler", "issues": "Sorunlar", - "pulls": "Değişiklik İstekleri" + "pulls": "Değişiklik İstekleri", + "repositories": "Repositories" }, "stash": { "scenes": "Sahneler", @@ -1023,12 +1024,23 @@ "bcharge": "Pil Yüzdesi", "timeleft": "Kalan Zaman" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Etiketler" + }, + "slskd": { + "slskStatus": "Ağ", + "connected": "Bağlandı", + "disconnected": "Bağlantı kesildi", + "updateStatus": "Update", + "update_yes": "Kullanılabilir", + "update_no": "Güncel", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Dosyalar" } } diff --git a/public/locales/uk/common.json b/public/locales/uk/common.json index 0914c49f..419d77c0 100644 --- a/public/locales/uk/common.json +++ b/public/locales/uk/common.json @@ -120,7 +120,7 @@ "grid_power": "Сітка", "home_power": "Споживання", "charge_power": "Зарядний пристрій", - "kilowatt": "kW" + "kilowatt": "кВт" }, "flood": { "download": "Завантажено", @@ -149,8 +149,8 @@ "received": "Отримано", "sent": "Надіслано", "externalIPAddress": "Зовнішній IP", - "externalIPv6Address": "Ext. IPv6", - "externalIPv6Prefix": "Ext. IPv6-Prefix" + "externalIPv6Address": "Зовнішній IPv6", + "externalIPv6Prefix": "Зовнішній Префікс IPv6-" }, "caddy": { "upstreams": "Потоки", @@ -178,7 +178,7 @@ "connectedAp": "Підключені точки доступу", "activeUser": "Активні пристрої", "alerts": "Оповіщення", - "connectedGateways": "Connected gateways", + "connectedGateways": "Підключені шлюзи", "connectedSwitches": "Підключені перемикачі" }, "nzbget": { @@ -420,8 +420,8 @@ }, "authentik": { "users": "Користувачі", - "loginsLast24H": "Вхід (24 години)", - "failedLoginsLast24H": "Невдалі входи (24 години)" + "loginsLast24H": "Вхід (протягом доби)", + "failedLoginsLast24H": "Невдалі входи (протягом доби)" }, "proxmox": { "mem": "ОЗП", @@ -434,7 +434,7 @@ "load": "Завантаження", "wait": "Будь ласка, зачекайте", "temp": "Температура", - "_temp": "Темп.", + "_temp": "Температура", "warn": "Увага", "uptime": "Онлайн", "total": "Усього", @@ -616,7 +616,7 @@ }, "opendtu": { "yieldDay": "Сьогодні", - "absolutePower": "Абс. потуж.", + "absolutePower": "Потужність", "relativePower": "Заряд %", "limit": "Ліміт" }, @@ -648,13 +648,13 @@ "wanStatus": "Статус WAN", "up": "Онлайн", "down": "Офлайн", - "temp": "Темп.", + "temp": "Температура", "disk": "Використання диска", "wanIP": "WAN IP" }, "proxmoxbackupserver": { "datastore_usage": "Сховище даних", - "failed_tasks_24h": "Невиконані завдання 24 години", + "failed_tasks_24h": "Невиконані завдання за останню добу", "cpu_usage": "ЦП", "memory_usage": "Пам'ять" }, @@ -705,8 +705,8 @@ "time": "Час" }, "firefly": { - "networth": "Net Worth", - "budget": "Budget" + "networth": "Чисті Активи", + "budget": "Бюджет" }, "grafana": { "dashboards": "Інформаційні панелі", @@ -831,7 +831,7 @@ }, "openwrt": { "uptime": "Час роботи", - "cpuLoad": "Сер. навантаження ЦП (5 хв)", + "cpuLoad": "Сер. навантаження ЦП (\"5\" хв)", "up": "Онлайн", "down": "Офлайн", "bytesTx": "Передано", @@ -855,7 +855,7 @@ "inCinemas": "У кінотеатрах", "physicalRelease": "Фізичний реліз", "digitalRelease": "Цифровий реліз", - "noEventsToday": "Події на сьогодні відсутні", + "noEventsToday": "Події на сьогодні відсутні!", "noEventsFound": "Події не знайдено" }, "romm": { @@ -885,7 +885,8 @@ "gitea": { "notifications": "Сповіщення", "issues": "Питання", - "pulls": "Pull-запити" + "pulls": "Pull-запити", + "repositories": "Репозиторії" }, "stash": { "scenes": "Сцени", @@ -1023,12 +1024,23 @@ "bcharge": "Заряд батареї", "timeleft": "Залишилось" }, - "hoarder": { - "bookmarks": "Bookmarks", - "favorites": "Favorites", - "archived": "Archived", - "highlights": "Highlights", - "lists": "Lists", + "karakeep": { + "bookmarks": "Закладки", + "favorites": "Обране", + "archived": "Заархівовані", + "highlights": "Основні моменти", + "lists": "Списки", "tags": "Теги" + }, + "slskd": { + "slskStatus": "Мережа", + "connected": "З'єднано", + "disconnected": "Відключено", + "updateStatus": "Оновити", + "update_yes": "Доступно", + "update_no": "Актуально", + "downloads": "Завантаження", + "uploads": "Вивантаження", + "sharedFiles": "Файли" } } diff --git a/public/locales/vi/common.json b/public/locales/vi/common.json index d2753c97..efe0c9ab 100644 --- a/public/locales/vi/common.json +++ b/public/locales/vi/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "Notifications", "issues": "Issues", - "pulls": "Pull Requests" + "pulls": "Pull Requests", + "repositories": "Repositories" }, "stash": { "scenes": "Scenes", @@ -1023,12 +1024,23 @@ "bcharge": "Battery Charge", "timeleft": "Thời gian còn lại" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Tags" + }, + "slskd": { + "slskStatus": "Network", + "connected": "Connected", + "disconnected": "Disconnected", + "updateStatus": "Update", + "update_yes": "Available", + "update_no": "Up to Date", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Files" } } diff --git a/public/locales/yue/common.json b/public/locales/yue/common.json index 64bc1e72..9dd81cfd 100644 --- a/public/locales/yue/common.json +++ b/public/locales/yue/common.json @@ -5,9 +5,9 @@ "bbytes": "{{value, bytes(binary: true)}}", "bbits": "{{value, bytes(bits: true; binary: true)}}", "byterate": "{{value, rate(bits: false)}}", - "bibyterate": "{{value, rate(bits: false; binary: true)}}", + "bibyterate": "{{value, bytes(bits: true; binary: true)}}", "bitrate": "{{value, rate(bits: true)}}", - "bibitrate": "{{value, rate(bits: true; binary: true)}}", + "bibitrate": "{{value, bytes(bits: true; binary: true)}}", "percent": "{{value, percent}}", "number": "{{value, number}}", "ms": "{{value, number}}", @@ -120,7 +120,7 @@ "grid_power": "電網", "home_power": "電源使用率", "charge_power": "充電", - "kilowatt": "kW" + "kilowatt": "千瓦" }, "flood": { "download": "下載速率", @@ -140,7 +140,7 @@ "connectionStatusPendingDisconnect": "待辦的斷開", "connectionStatusDisconnecting": "正在中斷連線", "connectionStatusDisconnected": "連接已中斷", - "connectionStatusConnected": "Connected", + "connectionStatusConnected": "已連線", "uptime": "運行時間", "maxDown": "最大下載速率", "maxUp": "最大上傳速率", @@ -149,8 +149,8 @@ "received": "已接收", "sent": "已送出", "externalIPAddress": "外部 IP", - "externalIPv6Address": "Ext. IPv6", - "externalIPv6Prefix": "Ext. IPv6-Prefix" + "externalIPv6Address": "外部 IP", + "externalIPv6Prefix": "擴展 IPv-前綴" }, "caddy": { "upstreams": "上行", @@ -178,7 +178,7 @@ "connectedAp": "已連接的存取點", "activeUser": "在線裝置", "alerts": "警示", - "connectedGateways": "Connected gateways", + "connectedGateways": "已連繫的網關", "connectedSwitches": "已連接的交換器" }, "nzbget": { @@ -229,8 +229,8 @@ "seed": "已完成下載" }, "develancacheui": { - "cachehitbytes": "Cache Hit Bytes", - "cachemissbytes": "Cache Miss Bytes" + "cachehitbytes": "快取未命中位元組", + "cachemissbytes": "快取未命中位元組" }, "downloadstation": { "download": "下載速率", @@ -285,9 +285,9 @@ }, "netalertx": { "total": "全部", - "connected": "Connected", - "new_devices": "New Devices", - "down_alerts": "Down Alerts" + "connected": "已連線", + "new_devices": "新裝置", + "down_alerts": "離線警告" }, "pihole": { "queries": "查詢", @@ -313,13 +313,13 @@ }, "suwayomi": { "download": "下載咗", - "nondownload": "Non-Downloaded", + "nondownload": "已下載", "read": "已讀", "unread": "未讀", - "downloadedread": "Downloaded & Read", - "downloadedunread": "Downloaded & Unread", - "nondownloadedread": "Non-Downloaded & Read", - "nondownloadedunread": "Non-Downloaded & Unread" + "downloadedread": "已下載且已閱讀", + "downloadedunread": "已下載且未閱讀", + "nondownloadedread": "未下載但已閱讀", + "nondownloadedunread": "未下載且未閱讀" }, "tailscale": { "address": "位址", @@ -337,15 +337,15 @@ }, "technitium": { "totalQueries": "查詢", - "totalNoError": "Success", - "totalServerFailure": "Failures", - "totalNxDomain": "NX Domains", - "totalRefused": "Refused", - "totalAuthoritative": "Authoritative", - "totalRecursive": "Recursive", - "totalCached": "Cached", + "totalNoError": "成功", + "totalServerFailure": "失敗", + "totalNxDomain": "網域", + "totalRefused": "對方拒投誠信", + "totalAuthoritative": "權威的", + "totalRecursive": "遞迴", + "totalCached": "快取", "totalBlocked": "封鎖", - "totalDropped": "Dropped", + "totalDropped": "丟棄", "totalClients": "客戶端" }, "tdarr": { @@ -705,8 +705,8 @@ "time": "時間" }, "firefly": { - "networth": "Net Worth", - "budget": "Budget" + "networth": "淨值", + "budget": "預算" }, "grafana": { "dashboards": "控制面板", @@ -860,16 +860,16 @@ }, "romm": { "platforms": "平台", - "totalRoms": "Games", - "saves": "Saves", - "states": "States", - "screenshots": "Screenshots", - "totalfilesize": "Total Size" + "totalRoms": "遊戲", + "saves": "已儲存", + "states": "州", + "screenshots": "螢幕截圖", + "totalfilesize": "大小總計" }, "mailcow": { "domains": "域", - "mailboxes": "Mailboxes", - "mails": "Mails", + "mailboxes": "信箱", + "mails": "郵件數", "storage": "儲存空間" }, "netdata": { @@ -885,7 +885,8 @@ "gitea": { "notifications": "信息", "issues": "出版", - "pulls": "提取請求" + "pulls": "提取請求", + "repositories": "套件來源" }, "stash": { "scenes": "場景", @@ -921,16 +922,16 @@ "bans": "禁止" }, "wgeasy": { - "connected": "Connected", + "connected": "已連線", "enabled": "啟用", "disabled": "停用咗", "total": "全部" }, "swagdashboard": { - "proxied": "Proxied", - "auth": "With Auth", - "outdated": "Outdated", - "banned": "Banned" + "proxied": "已代理", + "auth": "已授權", + "outdated": "須更新", + "banned": "已封鎖" }, "myspeed": { "ping": "延遲", @@ -938,43 +939,43 @@ "upload": "上傳速率" }, "stocks": { - "stocks": "Stocks", - "loading": "Loading", - "open": "Open - US Market", - "closed": "Closed - US Market", - "invalidConfiguration": "Invalid Configuration" + "stocks": "股票", + "loading": "載入中 ", + "open": "美國市場已開放", + "closed": "美國市場已關閉", + "invalidConfiguration": "無效的設定" }, "frigate": { - "cameras": "Cameras", + "cameras": " ", "uptime": "運行時間", "version": "版本" }, "linkwarden": { - "links": "Links", - "collections": "Collections", + "links": " ", + "collections": "收藏庫", "tags": "標籤" }, "zabbix": { - "unclassified": "Not classified", + "unclassified": "未分類", "information": "資訊", - "warning": "Warning", - "average": "Average", - "high": "High", - "disaster": "Disaster" + "warning": "警告", + "average": "平均", + "high": "高優先權", + "disaster": "災難" }, "lubelogger": { - "vehicle": "Vehicle", - "vehicles": "Vehicles", - "serviceRecords": "Service Records", - "reminders": "Reminders", - "nextReminder": "Next Reminder", - "none": "None" + "vehicle": "車輛", + "vehicles": "車輛", + "serviceRecords": "保養記錄", + "reminders": "提醒", + "nextReminder": "下一個提醒", + "none": "沒有" }, "vikunja": { - "projects": "Active Projects", - "tasks7d": "Tasks Due This Week", - "tasksOverdue": "Overdue Tasks", - "tasksInProgress": "Tasks In Progress" + "projects": "正在應用的項目", + "tasks7d": "本週到期任務", + "tasksOverdue": "逾期處理", + "tasksInProgress": "正在執行的任務" }, "headscale": { "name": "名稱", @@ -986,7 +987,7 @@ }, "beszel": { "name": "名稱", - "systems": "Systems", + "systems": "系統", "up": "在線", "down": "離線", "paused": "擱置中", @@ -995,27 +996,27 @@ "updated": "已更新", "cpu": "CPU", "memory": "記憶體", - "disk": "Disk", - "network": "NET" + "disk": "儲存空間", + "network": "網路" }, "argocd": { - "apps": "Apps", - "synced": "Synced", - "outOfSync": "Out Of Sync", + "apps": "應用程式", + "synced": "已同步", + "outOfSync": "不同步", "healthy": "健康", - "degraded": "Degraded", - "progressing": "Progressing", + "degraded": "已降級", + "progressing": "進度", "missing": "缺少", - "suspended": "Suspended" + "suspended": "暫停" }, "spoolman": { - "loading": "Loading" + "loading": "載入中 " }, "gitlab": { - "groups": "Groups", + "groups": "群組", "issues": "出版", - "merges": "Merge Requests", - "projects": "Projects" + "merges": "合併請求", + "projects": "專" }, "apcups": { "status": "狀況", @@ -1023,12 +1024,23 @@ "bcharge": "充電", "timeleft": "用時" }, - "hoarder": { - "bookmarks": "Bookmarks", - "favorites": "Favorites", - "archived": "Archived", - "highlights": "Highlights", - "lists": "Lists", + "karakeep": { + "bookmarks": "書籤", + "favorites": "我的最愛", + "archived": "已存檔", + "highlights": "標記", + "lists": "列表", "tags": "標籤" + }, + "slskd": { + "slskStatus": "網絡", + "connected": "已連線", + "disconnected": "連接已中斷", + "updateStatus": "更新", + "update_yes": "可用", + "update_no": "已更新至最新", + "downloads": "下載", + "uploads": "上傳", + "sharedFiles": "檔案" } } diff --git a/public/locales/zh-Hans/common.json b/public/locales/zh-Hans/common.json index 5e54cd8d..be53b16b 100644 --- a/public/locales/zh-Hans/common.json +++ b/public/locales/zh-Hans/common.json @@ -885,7 +885,8 @@ "gitea": { "notifications": "通知", "issues": "问题", - "pulls": "PR" + "pulls": "PR", + "repositories": "Repositories" }, "stash": { "scenes": "场景", @@ -1023,12 +1024,23 @@ "bcharge": "充电中", "timeleft": "剩余时间" }, - "hoarder": { + "karakeep": { "bookmarks": "Bookmarks", "favorites": "Favorites", "archived": "Archived", "highlights": "Highlights", "lists": "Lists", "tags": "Tags" + }, + "slskd": { + "slskStatus": "网络", + "connected": "已连接", + "disconnected": "未连接", + "updateStatus": "Update", + "update_yes": "可用", + "update_no": "Up to Date", + "downloads": "Downloads", + "uploads": "Uploads", + "sharedFiles": "Files" } } diff --git a/public/locales/zh-Hant/common.json b/public/locales/zh-Hant/common.json index 5a356009..7abcd3a2 100644 --- a/public/locales/zh-Hant/common.json +++ b/public/locales/zh-Hant/common.json @@ -5,9 +5,9 @@ "bbytes": "{{value, bytes(binary: true)}}", "bbits": "{{value, bytes(bits: true; binary: true)}}", "byterate": "{{value, rate(bits: false)}}", - "bibyterate": "{{value, rate(bits: false; binary: true)}}", + "bibyterate": "{{value, bytes(bits: true; binary: true)}}", "bitrate": "{{value, rate(bits: true)}}", - "bibitrate": "{{value, rate(bits: true; binary: true)}}", + "bibitrate": "{{value, bytes(bits: true; binary: true)}}", "percent": "{{value, percent}}", "number": "{{value, number}}", "ms": "{{value, number}}", @@ -120,7 +120,7 @@ "grid_power": "電網", "home_power": "電源使用率", "charge_power": "充電", - "kilowatt": "kW" + "kilowatt": "千瓦" }, "flood": { "download": "下載速率", @@ -140,7 +140,7 @@ "connectionStatusPendingDisconnect": "待辦的斷開", "connectionStatusDisconnecting": "正在中斷連線", "connectionStatusDisconnected": "連接已中斷", - "connectionStatusConnected": "Connected", + "connectionStatusConnected": "已連線", "uptime": "運行時間", "maxDown": "最大下載速率", "maxUp": "最大上傳速率", @@ -149,8 +149,8 @@ "received": "已接收", "sent": "已送出", "externalIPAddress": "外部 IP", - "externalIPv6Address": "Ext. IPv6", - "externalIPv6Prefix": "Ext. IPv6-Prefix" + "externalIPv6Address": "外部 IP", + "externalIPv6Prefix": "擴展 IPv-前綴" }, "caddy": { "upstreams": "上行", @@ -178,7 +178,7 @@ "connectedAp": "已連接的存取點", "activeUser": "在線裝置", "alerts": "警示", - "connectedGateways": "Connected gateways", + "connectedGateways": "已連繫的網關", "connectedSwitches": "已連接的交換器" }, "nzbget": { @@ -229,8 +229,8 @@ "seed": "已完成下載" }, "develancacheui": { - "cachehitbytes": "Cache Hit Bytes", - "cachemissbytes": "Cache Miss Bytes" + "cachehitbytes": "快取未命中位元組", + "cachemissbytes": "快取未命中位元組" }, "downloadstation": { "download": "下載速率", @@ -285,9 +285,9 @@ }, "netalertx": { "total": "全部", - "connected": "Connected", - "new_devices": "New Devices", - "down_alerts": "Down Alerts" + "connected": "已連線", + "new_devices": "新裝置", + "down_alerts": "離線警告" }, "pihole": { "queries": "查詢", @@ -313,13 +313,13 @@ }, "suwayomi": { "download": "已下載", - "nondownload": "Non-Downloaded", + "nondownload": "已下載", "read": "已讀", "unread": "未讀", - "downloadedread": "Downloaded & Read", - "downloadedunread": "Downloaded & Unread", - "nondownloadedread": "Non-Downloaded & Read", - "nondownloadedunread": "Non-Downloaded & Unread" + "downloadedread": "已下載且已閱讀", + "downloadedunread": "已下載且未閱讀", + "nondownloadedread": "未下載但已閱讀", + "nondownloadedunread": "未下載且未閱讀" }, "tailscale": { "address": "位址", @@ -337,15 +337,15 @@ }, "technitium": { "totalQueries": "查詢", - "totalNoError": "Success", - "totalServerFailure": "Failures", - "totalNxDomain": "NX Domains", - "totalRefused": "Refused", - "totalAuthoritative": "Authoritative", - "totalRecursive": "Recursive", - "totalCached": "Cached", + "totalNoError": "成功", + "totalServerFailure": "失敗", + "totalNxDomain": "網域", + "totalRefused": "對方拒投誠信", + "totalAuthoritative": "權威的", + "totalRecursive": "遞迴", + "totalCached": "快取", "totalBlocked": "已阻擋", - "totalDropped": "Dropped", + "totalDropped": "丟棄", "totalClients": "客戶端" }, "tdarr": { @@ -705,8 +705,8 @@ "time": "時間" }, "firefly": { - "networth": "Net Worth", - "budget": "Budget" + "networth": "淨值", + "budget": "預算" }, "grafana": { "dashboards": "控制面板", @@ -860,16 +860,16 @@ }, "romm": { "platforms": "平台", - "totalRoms": "Games", - "saves": "Saves", - "states": "States", - "screenshots": "Screenshots", - "totalfilesize": "Total Size" + "totalRoms": "遊戲", + "saves": "已儲存", + "states": "州", + "screenshots": "螢幕截圖", + "totalfilesize": "大小總計" }, "mailcow": { "domains": "網域", - "mailboxes": "Mailboxes", - "mails": "Mails", + "mailboxes": "信箱", + "mails": "郵件數", "storage": "儲存空間" }, "netdata": { @@ -885,7 +885,8 @@ "gitea": { "notifications": "信息", "issues": "出版", - "pulls": "提取請求" + "pulls": "提取請求", + "repositories": "套件來源" }, "stash": { "scenes": "場景", @@ -921,16 +922,16 @@ "bans": "禁止" }, "wgeasy": { - "connected": "Connected", + "connected": "已連線", "enabled": "已啟用", "disabled": "已停用", "total": "全部" }, "swagdashboard": { - "proxied": "Proxied", - "auth": "With Auth", - "outdated": "Outdated", - "banned": "Banned" + "proxied": "已代理", + "auth": "已授權", + "outdated": "須更新", + "banned": "已封鎖" }, "myspeed": { "ping": "延遲", @@ -938,43 +939,43 @@ "upload": "上傳速率" }, "stocks": { - "stocks": "Stocks", - "loading": "Loading", - "open": "Open - US Market", - "closed": "Closed - US Market", - "invalidConfiguration": "Invalid Configuration" + "stocks": "股票", + "loading": "載入中 ", + "open": "美國市場已開放", + "closed": "美國市場已關閉", + "invalidConfiguration": "無效的設定" }, "frigate": { - "cameras": "Cameras", + "cameras": " ", "uptime": "運行時間", "version": "版本" }, "linkwarden": { - "links": "Links", - "collections": "Collections", + "links": " ", + "collections": "收藏庫", "tags": "標籤" }, "zabbix": { - "unclassified": "Not classified", + "unclassified": "未分類", "information": "資訊", - "warning": "Warning", - "average": "Average", - "high": "High", - "disaster": "Disaster" + "warning": "警告", + "average": "平均", + "high": "高優先權", + "disaster": "災難" }, "lubelogger": { - "vehicle": "Vehicle", - "vehicles": "Vehicles", - "serviceRecords": "Service Records", - "reminders": "Reminders", - "nextReminder": "Next Reminder", - "none": "None" + "vehicle": "車輛", + "vehicles": "車輛", + "serviceRecords": "保養記錄", + "reminders": "提醒", + "nextReminder": "下一個提醒", + "none": "沒有" }, "vikunja": { - "projects": "Active Projects", - "tasks7d": "Tasks Due This Week", - "tasksOverdue": "Overdue Tasks", - "tasksInProgress": "Tasks In Progress" + "projects": "正在應用的項目", + "tasks7d": "本週到期任務", + "tasksOverdue": "逾期處理", + "tasksInProgress": "正在執行的任務" }, "headscale": { "name": "名稱", @@ -986,7 +987,7 @@ }, "beszel": { "name": "名稱", - "systems": "Systems", + "systems": "系統", "up": "在線", "down": "離線", "paused": "擱置中", @@ -995,27 +996,27 @@ "updated": "已更新", "cpu": "CPU", "memory": "記憶體", - "disk": "Disk", - "network": "NET" + "disk": "儲存空間", + "network": "網路" }, "argocd": { - "apps": "Apps", - "synced": "Synced", - "outOfSync": "Out Of Sync", + "apps": "應用程式", + "synced": "已同步", + "outOfSync": "不同步", "healthy": "健康", - "degraded": "Degraded", - "progressing": "Progressing", + "degraded": "已降級", + "progressing": "進度", "missing": "缺少", - "suspended": "Suspended" + "suspended": "暫停" }, "spoolman": { - "loading": "Loading" + "loading": "載入中 " }, "gitlab": { - "groups": "Groups", + "groups": "群組", "issues": "出版", - "merges": "Merge Requests", - "projects": "Projects" + "merges": "合併請求", + "projects": "專" }, "apcups": { "status": "狀態", @@ -1023,12 +1024,23 @@ "bcharge": "充電", "timeleft": "剩餘時間" }, - "hoarder": { - "bookmarks": "Bookmarks", - "favorites": "Favorites", - "archived": "Archived", - "highlights": "Highlights", - "lists": "Lists", + "karakeep": { + "bookmarks": "書籤", + "favorites": "我的最愛", + "archived": "已存檔", + "highlights": "標記", + "lists": "列表", "tags": "標籤" + }, + "slskd": { + "slskStatus": "網絡", + "connected": "已連線", + "disconnected": "連接已中斷", + "updateStatus": "更新", + "update_yes": "可觀看", + "update_no": "已更新至最新", + "downloads": "下載", + "uploads": "上傳", + "sharedFiles": "檔案" } } diff --git a/src/components/bookmarks/group.jsx b/src/components/bookmarks/group.jsx index d8eb296d..2334dad5 100644 --- a/src/components/bookmarks/group.jsx +++ b/src/components/bookmarks/group.jsx @@ -1,10 +1,10 @@ -import { useRef, useEffect } from "react"; -import classNames from "classnames"; import { Disclosure, Transition } from "@headlessui/react"; -import { MdKeyboardArrowDown } from "react-icons/md"; -import ErrorBoundary from "components/errorboundry"; +import classNames from "classnames"; import List from "components/bookmarks/list"; +import ErrorBoundary from "components/errorboundry"; import ResolvedIcon from "components/resolvedicon"; +import { useEffect, useRef } from "react"; +import { MdKeyboardArrowDown } from "react-icons/md"; export default function BookmarksGroup({ bookmarks, @@ -12,6 +12,7 @@ export default function BookmarksGroup({ disableCollapse, groupsInitiallyCollapsed, bookmarksStyle, + maxGroupColumns, }) { const panel = useRef(); @@ -25,6 +26,9 @@ export default function BookmarksGroup({ className={classNames( "bookmark-group flex-1 overflow-hidden", layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/4 lg:basis-1/5 xl:basis-1/6", + layout?.style !== "row" && maxGroupColumns && parseInt(maxGroupColumns, 10) > 6 + ? `3xl:basis-1/${maxGroupColumns}` + : "", layout?.header === false ? "px-1" : "p-1 pb-0", )} > diff --git a/src/components/bookmarks/item.jsx b/src/components/bookmarks/item.jsx index dd18bb71..7ea16bba 100644 --- a/src/components/bookmarks/item.jsx +++ b/src/components/bookmarks/item.jsx @@ -1,7 +1,7 @@ -import { useContext } from "react"; import classNames from "classnames"; -import { SettingsContext } from "utils/contexts/settings"; import ResolvedIcon from "components/resolvedicon"; +import { useContext } from "react"; +import { SettingsContext } from "utils/contexts/settings"; export default function Item({ bookmark, iconOnly = false }) { const description = bookmark.description ?? new URL(bookmark.href).hostname; @@ -22,7 +22,7 @@ export default function Item({ bookmark, iconOnly = false }) { className={classNames( settings.cardBlur !== undefined && `backdrop-blur${settings.cardBlur.length ? "-" : ""}${settings.cardBlur}`, "text-left cursor-pointer transition-all rounded-md font-medium text-theme-700 dark:text-theme-200 dark:hover:text-theme-300 shadow-md shadow-theme-900/10 dark:shadow-theme-900/20 bg-theme-100/20 hover:bg-theme-300/20 dark:bg-white/5 dark:hover:bg-white/10", - iconOnly ? "h-[60px] w-[60px] grid" : "block w-full h-8 mb-3", + iconOnly ? "h-[60px] w-[60px] grid" : "block w-full mb-3", )} > {iconOnly ? ( diff --git a/src/components/favicon.jsx b/src/components/favicon.jsx index 8221c799..8961d655 100644 --- a/src/components/favicon.jsx +++ b/src/components/favicon.jsx @@ -1,6 +1,6 @@ /* eslint-disable @next/next/no-img-element */ /* eslint-disable jsx-a11y/alt-text */ -import { useRef, useEffect, useContext } from "react"; +import { useContext, useEffect, useRef } from "react"; import { ColorContext } from "utils/contexts/color"; import themes from "utils/styles/themes"; diff --git a/src/components/quicklaunch.jsx b/src/components/quicklaunch.jsx index e1f6bc09..5ed9ace7 100644 --- a/src/components/quicklaunch.jsx +++ b/src/components/quicklaunch.jsx @@ -1,6 +1,6 @@ -import { useTranslation } from "react-i18next"; -import { useEffect, useState, useRef, useCallback, useContext } from "react"; import classNames from "classnames"; +import { useTranslation } from "next-i18next"; +import { useCallback, useContext, useEffect, useRef, useState } from "react"; import useSWR from "swr"; import { SettingsContext } from "utils/contexts/settings"; @@ -21,7 +21,7 @@ export default function QuickLaunch({ servicesAndBookmarks, searchString, setSea const [searchSuggestions, setSearchSuggestions] = useState([]); const { data: widgets } = useSWR("/api/widgets"); - const searchWidget = Object.values(widgets).find((w) => w.type === "search"); + const searchWidget = widgets && Object.values(widgets).find((w) => w.type === "search"); let searchProvider; @@ -53,7 +53,7 @@ export default function QuickLaunch({ servicesAndBookmarks, searchString, setSea const result = results[currentItemIndex]; window.open( result.href, - newWindow ? "_blank" : result.target ?? searchProvider?.target ?? settings.target ?? "_blank", + newWindow ? "_blank" : (result.target ?? searchProvider?.target ?? settings.target ?? "_blank"), "noreferrer", ); } @@ -204,7 +204,8 @@ export default function QuickLaunch({ servicesAndBookmarks, searchString, setSea return () => { abortController.abort(); }; - }, [searchString, servicesAndBookmarks, searchDescriptions, hideVisitURL, searchSuggestions, searchProvider, url, t]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [searchString, servicesAndBookmarks, searchDescriptions, hideVisitURL, searchSuggestions, searchProvider, url]); const [hidden, setHidden] = useState(true); useEffect(() => { diff --git a/src/components/resolvedicon.jsx b/src/components/resolvedicon.jsx index eb2a5c0d..77ba9119 100644 --- a/src/components/resolvedicon.jsx +++ b/src/components/resolvedicon.jsx @@ -1,5 +1,5 @@ -import { useContext } from "react"; import Image from "next/image"; +import { useContext } from "react"; import { SettingsContext } from "utils/contexts/settings"; import { ThemeContext } from "utils/contexts/theme"; diff --git a/src/components/services/dropdown.jsx b/src/components/services/dropdown.jsx index 00b8a429..e8e11d97 100644 --- a/src/components/services/dropdown.jsx +++ b/src/components/services/dropdown.jsx @@ -1,7 +1,7 @@ -import { Fragment } from "react"; import { Menu, Transition } from "@headlessui/react"; -import { BiCog } from "react-icons/bi"; import classNames from "classnames"; +import { Fragment } from "react"; +import { BiCog } from "react-icons/bi"; export default function Dropdown({ options, value, setValue }) { return ( diff --git a/src/components/services/group.jsx b/src/components/services/group.jsx index 06fb83e1..cad7b5aa 100644 --- a/src/components/services/group.jsx +++ b/src/components/services/group.jsx @@ -1,16 +1,16 @@ -import { useRef, useEffect } from "react"; -import classNames from "classnames"; import { Disclosure, Transition } from "@headlessui/react"; -import { MdKeyboardArrowDown } from "react-icons/md"; -import List from "components/services/list"; +import classNames from "classnames"; import ResolvedIcon from "components/resolvedicon"; +import List from "components/services/list"; +import { useEffect, useRef } from "react"; +import { MdKeyboardArrowDown } from "react-icons/md"; import { columnMap } from "../../utils/layout/columns"; export default function ServicesGroup({ group, layout, - fiveColumns, + maxGroupColumns, disableCollapse, useEqualHeights, groupsInitiallyCollapsed, @@ -31,7 +31,7 @@ export default function ServicesGroup({ className={classNames( "services-group flex-1", layout?.style === "row" ? "basis-full" : "basis-full md:basis-1/2 lg:basis-1/3 xl:basis-1/4", - layout?.style !== "row" && fiveColumns ? "3xl:basis-1/5" : "", + layout?.style !== "row" && maxGroupColumns ? `3xl:basis-1/${maxGroupColumns}` : "", groupPadding, isSubgroup ? "subgroup" : "", )} @@ -97,7 +97,7 @@ export default function ServicesGroup({ key={subgroup.name} group={subgroup} layout={layout?.[subgroup.name]} - fiveColumns={fiveColumns} + maxGroupColumns={maxGroupColumns} disableCollapse={disableCollapse} useEqualHeights={useEqualHeights} groupsInitiallyCollapsed={groupsInitiallyCollapsed} diff --git a/src/components/services/item.jsx b/src/components/services/item.jsx index 72b0fd50..8e851611 100644 --- a/src/components/services/item.jsx +++ b/src/components/services/item.jsx @@ -1,15 +1,15 @@ import classNames from "classnames"; +import ResolvedIcon from "components/resolvedicon"; import { useContext, useState } from "react"; +import { SettingsContext } from "utils/contexts/settings"; import Docker from "widgets/docker/component"; import Kubernetes from "widgets/kubernetes/component"; -import { SettingsContext } from "utils/contexts/settings"; -import ResolvedIcon from "components/resolvedicon"; -import Status from "./status"; -import Widget from "./widget"; +import KubernetesStatus from "./kubernetes-status"; import Ping from "./ping"; import SiteMonitor from "./site-monitor"; -import KubernetesStatus from "./kubernetes-status"; +import Status from "./status"; +import Widget from "./widget"; export default function Item({ service, groupName, useEqualHeights }) { const hasLink = service.href && service.href !== "#"; diff --git a/src/components/services/kubernetes-status.jsx b/src/components/services/kubernetes-status.jsx index a256a2df..e4ea958d 100644 --- a/src/components/services/kubernetes-status.jsx +++ b/src/components/services/kubernetes-status.jsx @@ -1,5 +1,5 @@ -import useSWR from "swr"; import { t } from "i18next"; +import useSWR from "swr"; export default function KubernetesStatus({ service, style }) { const podSelectorString = service.podSelector !== undefined ? `podSelector=${service.podSelector}` : ""; diff --git a/src/components/services/ping.jsx b/src/components/services/ping.jsx index 670f9d4b..f8665e33 100644 --- a/src/components/services/ping.jsx +++ b/src/components/services/ping.jsx @@ -1,4 +1,4 @@ -import { useTranslation } from "react-i18next"; +import { useTranslation } from "next-i18next"; import useSWR from "swr"; export default function Ping({ groupName, serviceName, style }) { diff --git a/src/components/services/site-monitor.jsx b/src/components/services/site-monitor.jsx index 4dceb44c..79496f65 100644 --- a/src/components/services/site-monitor.jsx +++ b/src/components/services/site-monitor.jsx @@ -1,4 +1,4 @@ -import { useTranslation } from "react-i18next"; +import { useTranslation } from "next-i18next"; import useSWR from "swr"; export default function SiteMonitor({ groupName, serviceName, style }) { diff --git a/src/components/services/status.jsx b/src/components/services/status.jsx index 3a6f3b33..2688ca0f 100644 --- a/src/components/services/status.jsx +++ b/src/components/services/status.jsx @@ -1,4 +1,4 @@ -import { useTranslation } from "react-i18next"; +import { useTranslation } from "next-i18next"; import useSWR from "swr"; export default function Status({ service, style }) { diff --git a/src/components/services/widget.jsx b/src/components/services/widget.jsx index bda638a4..6e3a6360 100644 --- a/src/components/services/widget.jsx +++ b/src/components/services/widget.jsx @@ -1,5 +1,5 @@ -import { useTranslation } from "next-i18next"; import ErrorBoundary from "components/errorboundry"; +import { useTranslation } from "next-i18next"; import components from "widgets/components"; diff --git a/src/components/services/widget/block.jsx b/src/components/services/widget/block.jsx index 8cd74aad..720140cc 100644 --- a/src/components/services/widget/block.jsx +++ b/src/components/services/widget/block.jsx @@ -1,5 +1,5 @@ -import { useTranslation } from "next-i18next"; import classNames from "classnames"; +import { useTranslation } from "next-i18next"; export default function Block({ value, label }) { const { t } = useTranslation(); diff --git a/src/components/services/widget/container.jsx b/src/components/services/widget/container.jsx index 9b10233c..f5957382 100644 --- a/src/components/services/widget/container.jsx +++ b/src/components/services/widget/container.jsx @@ -3,6 +3,11 @@ import { SettingsContext } from "utils/contexts/settings"; import Error from "./error"; +const ALIASED_WIDGETS = { + pialert: "netalertx", + hoarder: "karakeep", +}; + export default function Container({ error = false, children, service }) { const { settings } = useContext(SettingsContext); @@ -32,7 +37,17 @@ export default function Container({ error = false, children, service }) { if (!field.includes(".")) { fullField = `${type}.${field}`; } - return fullField === child?.props?.label; + let matches = fullField === child?.props?.label; + // check if the field is an 'alias' + if (matches) { + return true; + } else if (ALIASED_WIDGETS[type]) { + matches = fullField.replace(type, ALIASED_WIDGETS[type]) === child?.props?.label; + + return matches; + } + // no match + return false; }), ); } diff --git a/src/components/services/widget/error.jsx b/src/components/services/widget/error.jsx index 30c41283..0d4757d3 100644 --- a/src/components/services/widget/error.jsx +++ b/src/components/services/widget/error.jsx @@ -1,4 +1,4 @@ -import { useTranslation } from "react-i18next"; +import { useTranslation } from "next-i18next"; import { IoAlertCircle } from "react-icons/io5"; function displayError(error) { diff --git a/src/components/tab.jsx b/src/components/tab.jsx index 2c3984c9..dc183fe4 100644 --- a/src/components/tab.jsx +++ b/src/components/tab.jsx @@ -1,5 +1,5 @@ -import { useContext } from "react"; import classNames from "classnames"; +import { useContext } from "react"; import { TabContext } from "utils/contexts/tab"; function slugify(tabName) { diff --git a/src/components/toggles/color.jsx b/src/components/toggles/color.jsx index 60cc8de8..7ea700ab 100644 --- a/src/components/toggles/color.jsx +++ b/src/components/toggles/color.jsx @@ -1,7 +1,7 @@ -import { useContext, Fragment } from "react"; -import { IoColorPalette } from "react-icons/io5"; import { Popover, Transition } from "@headlessui/react"; import classNames from "classnames"; +import { Fragment, useContext } from "react"; +import { IoColorPalette } from "react-icons/io5"; import { ColorContext } from "utils/contexts/color"; const colors = [ diff --git a/src/components/version.jsx b/src/components/version.jsx index b8ee1eb8..946fb0a9 100644 --- a/src/components/version.jsx +++ b/src/components/version.jsx @@ -1,8 +1,8 @@ +import { compareVersions, validate } from "compare-versions"; import cache from "memory-cache"; import { useTranslation } from "next-i18next"; -import useSWR from "swr"; -import { compareVersions, validate } from "compare-versions"; import { MdNewReleases } from "react-icons/md"; +import useSWR from "swr"; const LATEST_RELEASE_CACHE_KEY = "latestRelease"; diff --git a/src/components/widgets/datetime/datetime.jsx b/src/components/widgets/datetime/datetime.jsx index a7aec5da..b59cf809 100644 --- a/src/components/widgets/datetime/datetime.jsx +++ b/src/components/widgets/datetime/datetime.jsx @@ -1,5 +1,5 @@ -import { useState, useEffect } from "react"; import { useTranslation } from "next-i18next"; +import { useEffect, useState } from "react"; import Container from "../widget/container"; import Raw from "../widget/raw"; diff --git a/src/components/widgets/glances/glances.jsx b/src/components/widgets/glances/glances.jsx index 0803b88c..7f772808 100644 --- a/src/components/widgets/glances/glances.jsx +++ b/src/components/widgets/glances/glances.jsx @@ -1,9 +1,9 @@ -import useSWR from "swr"; +import classNames from "classnames"; +import { useTranslation } from "next-i18next"; import { useContext } from "react"; import { FaMemory, FaRegClock, FaThermometerHalf } from "react-icons/fa"; import { FiCpu, FiHardDrive } from "react-icons/fi"; -import { useTranslation } from "next-i18next"; -import classNames from "classnames"; +import useSWR from "swr"; import { SettingsContext } from "utils/contexts/settings"; import Error from "../widget/error"; diff --git a/src/components/widgets/kubernetes/kubernetes.jsx b/src/components/widgets/kubernetes/kubernetes.jsx index f7b101c7..50b173bc 100644 --- a/src/components/widgets/kubernetes/kubernetes.jsx +++ b/src/components/widgets/kubernetes/kubernetes.jsx @@ -1,8 +1,8 @@ -import useSWR from "swr"; import { useTranslation } from "next-i18next"; +import useSWR from "swr"; -import Error from "../widget/error"; import Container from "../widget/container"; +import Error from "../widget/error"; import Raw from "../widget/raw"; import Node from "./node"; diff --git a/src/components/widgets/kubernetes/node.jsx b/src/components/widgets/kubernetes/node.jsx index ba8f8b77..aebb40f2 100644 --- a/src/components/widgets/kubernetes/node.jsx +++ b/src/components/widgets/kubernetes/node.jsx @@ -1,7 +1,7 @@ +import { useTranslation } from "next-i18next"; import { FaMemory } from "react-icons/fa"; import { FiAlertTriangle, FiCpu, FiServer } from "react-icons/fi"; import { SiKubernetes } from "react-icons/si"; -import { useTranslation } from "next-i18next"; import UsageBar from "../resources/usage-bar"; diff --git a/src/components/widgets/longhorn/longhorn.jsx b/src/components/widgets/longhorn/longhorn.jsx index 22047e2c..db68cd7b 100644 --- a/src/components/widgets/longhorn/longhorn.jsx +++ b/src/components/widgets/longhorn/longhorn.jsx @@ -1,7 +1,7 @@ import useSWR from "swr"; -import Error from "../widget/error"; import Container from "../widget/container"; +import Error from "../widget/error"; import Raw from "../widget/raw"; import Node from "./node"; @@ -32,8 +32,8 @@ export default function Longhorn({ options }) {
{data.nodes .filter((node) => { - if (node.id === "total" && total) { - return true; + if (node.id === "total") { + return total; } if (!nodes) { return false; diff --git a/src/components/widgets/openmeteo/openmeteo.jsx b/src/components/widgets/openmeteo/openmeteo.jsx index 4d3e7e89..a46f53ab 100644 --- a/src/components/widgets/openmeteo/openmeteo.jsx +++ b/src/components/widgets/openmeteo/openmeteo.jsx @@ -1,16 +1,16 @@ -import useSWR from "swr"; -import { useState } from "react"; -import { WiCloudDown } from "react-icons/wi"; -import { MdLocationDisabled, MdLocationSearching } from "react-icons/md"; import { useTranslation } from "next-i18next"; +import { useState } from "react"; +import { MdLocationDisabled, MdLocationSearching } from "react-icons/md"; +import { WiCloudDown } from "react-icons/wi"; +import useSWR from "swr"; -import Error from "../widget/error"; +import mapIcon from "../../../utils/weather/openmeteo-condition-map"; import Container from "../widget/container"; import ContainerButton from "../widget/container_button"; -import WidgetIcon from "../widget/widget_icon"; +import Error from "../widget/error"; import PrimaryText from "../widget/primary_text"; import SecondaryText from "../widget/secondary_text"; -import mapIcon from "../../../utils/weather/openmeteo-condition-map"; +import WidgetIcon from "../widget/widget_icon"; function Widget({ options }) { const { t } = useTranslation(); diff --git a/src/components/widgets/openweathermap/weather.jsx b/src/components/widgets/openweathermap/weather.jsx index df0280e3..3336ed4f 100644 --- a/src/components/widgets/openweathermap/weather.jsx +++ b/src/components/widgets/openweathermap/weather.jsx @@ -1,16 +1,16 @@ -import useSWR from "swr"; -import { useState } from "react"; -import { WiCloudDown } from "react-icons/wi"; -import { MdLocationDisabled, MdLocationSearching } from "react-icons/md"; import { useTranslation } from "next-i18next"; +import { useState } from "react"; +import { MdLocationDisabled, MdLocationSearching } from "react-icons/md"; +import { WiCloudDown } from "react-icons/wi"; +import useSWR from "swr"; -import Error from "../widget/error"; +import mapIcon from "../../../utils/weather/owm-condition-map"; import Container from "../widget/container"; import ContainerButton from "../widget/container_button"; +import Error from "../widget/error"; import PrimaryText from "../widget/primary_text"; import SecondaryText from "../widget/secondary_text"; import WidgetIcon from "../widget/widget_icon"; -import mapIcon from "../../../utils/weather/owm-condition-map"; function Widget({ options }) { const { t, i18n } = useTranslation(); diff --git a/src/components/widgets/resources/cpu.jsx b/src/components/widgets/resources/cpu.jsx index 1963637d..1bea4af9 100644 --- a/src/components/widgets/resources/cpu.jsx +++ b/src/components/widgets/resources/cpu.jsx @@ -1,9 +1,9 @@ -import useSWR from "swr"; -import { FiCpu } from "react-icons/fi"; import { useTranslation } from "next-i18next"; +import { FiCpu } from "react-icons/fi"; +import useSWR from "swr"; -import Resource from "../widget/resource"; import Error from "../widget/error"; +import Resource from "../widget/resource"; export default function Cpu({ expanded, refresh = 1500 }) { const { t } = useTranslation(); diff --git a/src/components/widgets/resources/cputemp.jsx b/src/components/widgets/resources/cputemp.jsx index ef994c65..248cd396 100644 --- a/src/components/widgets/resources/cputemp.jsx +++ b/src/components/widgets/resources/cputemp.jsx @@ -1,9 +1,9 @@ -import useSWR from "swr"; -import { FaThermometerHalf } from "react-icons/fa"; import { useTranslation } from "next-i18next"; +import { FaThermometerHalf } from "react-icons/fa"; +import useSWR from "swr"; -import Resource from "../widget/resource"; import Error from "../widget/error"; +import Resource from "../widget/resource"; function convertToFahrenheit(t) { return (t * 9) / 5 + 32; diff --git a/src/components/widgets/resources/disk.jsx b/src/components/widgets/resources/disk.jsx index 15da7780..d5706ba5 100644 --- a/src/components/widgets/resources/disk.jsx +++ b/src/components/widgets/resources/disk.jsx @@ -1,9 +1,9 @@ -import useSWR from "swr"; -import { FiHardDrive } from "react-icons/fi"; import { useTranslation } from "next-i18next"; +import { FiHardDrive } from "react-icons/fi"; +import useSWR from "swr"; -import Resource from "../widget/resource"; import Error from "../widget/error"; +import Resource from "../widget/resource"; export default function Disk({ options, expanded, diskUnits, refresh = 1500 }) { const { t } = useTranslation(); diff --git a/src/components/widgets/resources/memory.jsx b/src/components/widgets/resources/memory.jsx index 155b7ecb..a8c82cbf 100644 --- a/src/components/widgets/resources/memory.jsx +++ b/src/components/widgets/resources/memory.jsx @@ -1,9 +1,9 @@ -import useSWR from "swr"; -import { FaMemory } from "react-icons/fa"; import { useTranslation } from "next-i18next"; +import { FaMemory } from "react-icons/fa"; +import useSWR from "swr"; -import Resource from "../widget/resource"; import Error from "../widget/error"; +import Resource from "../widget/resource"; export default function Memory({ expanded, refresh = 1500 }) { const { t } = useTranslation(); diff --git a/src/components/widgets/resources/network.jsx b/src/components/widgets/resources/network.jsx index a2a3acac..48286030 100644 --- a/src/components/widgets/resources/network.jsx +++ b/src/components/widgets/resources/network.jsx @@ -1,9 +1,9 @@ -import useSWR from "swr"; -import { FaNetworkWired } from "react-icons/fa"; import { useTranslation } from "next-i18next"; +import { FaNetworkWired } from "react-icons/fa"; +import useSWR from "swr"; -import Resource from "../widget/resource"; import Error from "../widget/error"; +import Resource from "../widget/resource"; export default function Network({ options, refresh = 1500 }) { const { t } = useTranslation(); diff --git a/src/components/widgets/resources/resources.jsx b/src/components/widgets/resources/resources.jsx index db26caa7..1002f98c 100644 --- a/src/components/widgets/resources/resources.jsx +++ b/src/components/widgets/resources/resources.jsx @@ -1,12 +1,12 @@ import Container from "../widget/container"; import Raw from "../widget/raw"; -import Disk from "./disk"; import Cpu from "./cpu"; -import Memory from "./memory"; import CpuTemp from "./cputemp"; -import Uptime from "./uptime"; +import Disk from "./disk"; +import Memory from "./memory"; import Network from "./network"; +import Uptime from "./uptime"; export default function Resources({ options }) { const { expanded, units, diskUnits, tempmin, tempmax } = options; diff --git a/src/components/widgets/resources/uptime.jsx b/src/components/widgets/resources/uptime.jsx index 2fac0fcd..f21634c2 100644 --- a/src/components/widgets/resources/uptime.jsx +++ b/src/components/widgets/resources/uptime.jsx @@ -1,9 +1,9 @@ -import useSWR from "swr"; -import { FaRegClock } from "react-icons/fa"; import { useTranslation } from "next-i18next"; +import { FaRegClock } from "react-icons/fa"; +import useSWR from "swr"; -import Resource from "../widget/resource"; import Error from "../widget/error"; +import Resource from "../widget/resource"; export default function Uptime({ refresh = 1500 }) { const { t } = useTranslation(); diff --git a/src/components/widgets/search/search.jsx b/src/components/widgets/search/search.jsx index e0564c48..6699a374 100644 --- a/src/components/widgets/search/search.jsx +++ b/src/components/widgets/search/search.jsx @@ -1,10 +1,10 @@ -import { useState, useEffect, Fragment } from "react"; -import { useTranslation } from "next-i18next"; -import { FiSearch } from "react-icons/fi"; -import { SiDuckduckgo, SiGoogle, SiBaidu, SiBrave } from "react-icons/si"; -import { BiLogoBing } from "react-icons/bi"; -import { Listbox, Transition, Combobox } from "@headlessui/react"; +import { Combobox, Listbox, Transition } from "@headlessui/react"; import classNames from "classnames"; +import { useTranslation } from "next-i18next"; +import { Fragment, useEffect, useState } from "react"; +import { BiLogoBing } from "react-icons/bi"; +import { FiSearch } from "react-icons/fi"; +import { SiBaidu, SiBrave, SiDuckduckgo, SiGoogle } from "react-icons/si"; import ContainerForm from "../widget/container_form"; import Raw from "../widget/raw"; diff --git a/src/components/widgets/stocks/stocks.jsx b/src/components/widgets/stocks/stocks.jsx index 1a9018d3..e6657878 100644 --- a/src/components/widgets/stocks/stocks.jsx +++ b/src/components/widgets/stocks/stocks.jsx @@ -1,13 +1,13 @@ -import useSWR from "swr"; -import { useState } from "react"; import { useTranslation } from "next-i18next"; +import { useState } from "react"; import { FaChartLine } from "react-icons/fa6"; +import useSWR from "swr"; -import Error from "../widget/error"; import Container from "../widget/container"; +import Error from "../widget/error"; import PrimaryText from "../widget/primary_text"; -import WidgetIcon from "../widget/widget_icon"; import Raw from "../widget/raw"; +import WidgetIcon from "../widget/widget_icon"; export default function Widget({ options }) { const { t, i18n } = useTranslation(); diff --git a/src/components/widgets/unifi_console/unifi_console.jsx b/src/components/widgets/unifi_console/unifi_console.jsx index 5295dbb7..09e6952f 100644 --- a/src/components/widgets/unifi_console/unifi_console.jsx +++ b/src/components/widgets/unifi_console/unifi_console.jsx @@ -1,13 +1,13 @@ -import { BiError, BiWifi, BiCheckCircle, BiXCircle, BiNetworkChart } from "react-icons/bi"; -import { MdSettingsEthernet } from "react-icons/md"; import { useTranslation } from "next-i18next"; +import { BiCheckCircle, BiError, BiNetworkChart, BiWifi, BiXCircle } from "react-icons/bi"; +import { MdSettingsEthernet } from "react-icons/md"; import { SiUbiquiti } from "react-icons/si"; -import Error from "../widget/error"; import Container from "../widget/container"; +import Error from "../widget/error"; +import PrimaryText from "../widget/primary_text"; import Raw from "../widget/raw"; import WidgetIcon from "../widget/widget_icon"; -import PrimaryText from "../widget/primary_text"; import useWidgetAPI from "utils/proxy/use-widget-api"; diff --git a/src/components/widgets/weather/weather.jsx b/src/components/widgets/weather/weather.jsx index 4ebb08c5..98768963 100644 --- a/src/components/widgets/weather/weather.jsx +++ b/src/components/widgets/weather/weather.jsx @@ -1,16 +1,16 @@ -import useSWR from "swr"; -import { useState } from "react"; -import { WiCloudDown } from "react-icons/wi"; -import { MdLocationDisabled, MdLocationSearching } from "react-icons/md"; import { useTranslation } from "next-i18next"; +import { useState } from "react"; +import { MdLocationDisabled, MdLocationSearching } from "react-icons/md"; +import { WiCloudDown } from "react-icons/wi"; +import useSWR from "swr"; -import Error from "../widget/error"; +import mapIcon from "../../../utils/weather/condition-map"; import Container from "../widget/container"; +import ContainerButton from "../widget/container_button"; +import Error from "../widget/error"; import PrimaryText from "../widget/primary_text"; import SecondaryText from "../widget/secondary_text"; import WidgetIcon from "../widget/widget_icon"; -import ContainerButton from "../widget/container_button"; -import mapIcon from "../../../utils/weather/condition-map"; function Widget({ options }) { const { t, i18n } = useTranslation(); diff --git a/src/components/widgets/widget.jsx b/src/components/widgets/widget.jsx index 6cb48fde..ebc706ac 100644 --- a/src/components/widgets/widget.jsx +++ b/src/components/widgets/widget.jsx @@ -1,5 +1,5 @@ -import dynamic from "next/dynamic"; import ErrorBoundary from "components/errorboundry"; +import dynamic from "next/dynamic"; const widgetMappings = { weatherapi: dynamic(() => import("components/widgets/weather/weather")), diff --git a/src/components/widgets/widget/container.jsx b/src/components/widgets/widget/container.jsx index ae06d8ba..fe6397e0 100644 --- a/src/components/widgets/widget/container.jsx +++ b/src/components/widgets/widget/container.jsx @@ -2,10 +2,10 @@ import classNames from "classnames"; import { useContext } from "react"; import { SettingsContext } from "utils/contexts/settings"; -import WidgetIcon from "./widget_icon"; import PrimaryText from "./primary_text"; -import SecondaryText from "./secondary_text"; import Raw from "./raw"; +import SecondaryText from "./secondary_text"; +import WidgetIcon from "./widget_icon"; export function getAllClasses(options, additionalClassNames = "") { if (options?.style?.header === "boxedWidgets") { diff --git a/src/components/widgets/widget/container_button.jsx b/src/components/widgets/widget/container_button.jsx index a6379081..e0802511 100644 --- a/src/components/widgets/widget/container_button.jsx +++ b/src/components/widgets/widget/container_button.jsx @@ -1,4 +1,4 @@ -import { getAllClasses, getInnerBlock, getBottomBlock } from "./container"; +import { getAllClasses, getBottomBlock, getInnerBlock } from "./container"; export default function ContainerButton({ children = [], options, additionalClassNames = "", callback }) { return ( diff --git a/src/components/widgets/widget/container_form.jsx b/src/components/widgets/widget/container_form.jsx index 68cbd64b..a9afef3a 100644 --- a/src/components/widgets/widget/container_form.jsx +++ b/src/components/widgets/widget/container_form.jsx @@ -1,4 +1,4 @@ -import { getAllClasses, getInnerBlock, getBottomBlock } from "./container"; +import { getAllClasses, getBottomBlock, getInnerBlock } from "./container"; export default function ContainerForm({ children = [], options, additionalClassNames = "", callback }) { return ( diff --git a/src/components/widgets/widget/container_link.jsx b/src/components/widgets/widget/container_link.jsx index 6f157875..a36f311c 100644 --- a/src/components/widgets/widget/container_link.jsx +++ b/src/components/widgets/widget/container_link.jsx @@ -1,4 +1,4 @@ -import { getAllClasses, getInnerBlock, getBottomBlock } from "./container"; +import { getAllClasses, getBottomBlock, getInnerBlock } from "./container"; export default function ContainerLink({ children = [], options, additionalClassNames = "", target }) { return ( diff --git a/src/components/widgets/widget/error.jsx b/src/components/widgets/widget/error.jsx index e454256f..e0e8b1e1 100644 --- a/src/components/widgets/widget/error.jsx +++ b/src/components/widgets/widget/error.jsx @@ -1,4 +1,4 @@ -import { useTranslation } from "react-i18next"; +import { useTranslation } from "next-i18next"; import { BiError } from "react-icons/bi"; import Container from "./container"; diff --git a/src/components/widgets/widget/resources.jsx b/src/components/widgets/widget/resources.jsx index 2f594942..b9a48a41 100644 --- a/src/components/widgets/widget/resources.jsx +++ b/src/components/widgets/widget/resources.jsx @@ -1,8 +1,8 @@ import classNames from "classnames"; import ContainerLink from "./container_link"; -import Resource from "./resource"; import Raw from "./raw"; +import Resource from "./resource"; import WidgetLabel from "./widget_label"; export default function Resources({ options, children, target, additionalClassNames }) { diff --git a/src/middleware.js b/src/middleware.js index f2011903..bb9fbea5 100644 --- a/src/middleware.js +++ b/src/middleware.js @@ -4,11 +4,12 @@ export function middleware(req) { // Check the Host header, if HOMEPAGE_ALLOWED_HOSTS is set const host = req.headers.get("host"); const port = process.env.PORT || 3000; - let allowedHosts = [`localhost:${port}`]; + let allowedHosts = [`localhost:${port}`, `127.0.0.1:${port}`]; + const allowAll = process.env.HOMEPAGE_ALLOWED_HOSTS === "*"; if (process.env.HOMEPAGE_ALLOWED_HOSTS) { allowedHosts = allowedHosts.concat(process.env.HOMEPAGE_ALLOWED_HOSTS.split(",")); } - if (!host || !allowedHosts.includes(host)) { + if (!allowAll && (!host || !allowedHosts.includes(host))) { // eslint-disable-next-line no-console console.error( `Host validation failed for: ${host}. Hint: Set the HOMEPAGE_ALLOWED_HOSTS environment variable to allow requests from this host / port.`, diff --git a/src/pages/_app.jsx b/src/pages/_app.jsx index bf46e3f6..8e88f6b2 100644 --- a/src/pages/_app.jsx +++ b/src/pages/_app.jsx @@ -1,17 +1,72 @@ /* eslint-disable react/jsx-props-no-spreading */ -import { SWRConfig } from "swr"; import { appWithTranslation } from "next-i18next"; import Head from "next/head"; import "styles/globals.css"; -import "styles/theme.css"; import "styles/manrope.css"; +import "styles/theme.css"; +import { SWRConfig } from "swr"; import { ColorProvider } from "utils/contexts/color"; -import { ThemeProvider } from "utils/contexts/theme"; import { SettingsProvider } from "utils/contexts/settings"; import { TabProvider } from "utils/contexts/tab"; +import { ThemeProvider } from "utils/contexts/theme"; import nextI18nextConfig from "../../next-i18next.config"; +// eslint-disable-next-line no-unused-vars +const tailwindSafelist = [ + // TODO: remove pending https://github.com/tailwindlabs/tailwindcss/pull/17147 + "backdrop-blur", + "backdrop-blur-xs", + "backdrop-blur-sm", + "backdrop-blur-md", + "backdrop-blur-xl", + "backdrop-saturate-0", + "backdrop-saturate-50", + "backdrop-saturate-100", + "backdrop-saturate-150", + "backdrop-saturate-200", + "backdrop-brightness-0", + "backdrop-brightness-50", + "backdrop-brightness-75", + "backdrop-brightness-90", + "backdrop-brightness-95", + "backdrop-brightness-100", + "backdrop-brightness-105", + "backdrop-brightness-110", + "backdrop-brightness-125", + "backdrop-brightness-150", + "backdrop-brightness-200", + "grid-cols-1", + "md:grid-cols-1", + "md:grid-cols-2", + "lg:grid-cols-1", + "lg:grid-cols-2", + "lg:grid-cols-3", + "lg:grid-cols-4", + "lg:grid-cols-5", + "lg:grid-cols-6", + "lg:grid-cols-7", + "lg:grid-cols-8", + // for status + "bg-white", + "bg-black", + "dark:bg-white", + "bg-orange-400", + "dark:bg-orange-400", + // maxGroupColumns + "3xl:basis-1/5", + "3xl:basis-1/6", + "3xl:basis-1/7", + "3xl:basis-1/8", + // yep + "h-0 h-1 h-2 h-3 h-4 h-5 h-6 h-7 h-8 h-9 h-10 h-11 h-12 h-13 h-14 h-15 h-16 h-17 h-18 h-19 h-20 h-21 h-22 h-23 h-24 h-25 h-26 h-27 h-28 h-29 h-30 h-31 h-32 h-33 h-34 h-35 h-36 h-37 h-38 h-39 h-40 h-41 h-42 h-43 h-44 h-45 h-46 h-47 h-48 h-49 h-50 h-51 h-52 h-53 h-54 h-55 h-56 h-57 h-58 h-59 h-60 h-61 h-62 h-63 h-64 h-65 h-66 h-67 h-68 h-69 h-70 h-71 h-72 h-73 h-74 h-75 h-76 h-77 h-78 h-79 h-80 h-81 h-82 h-83 h-84 h-85 h-86 h-87 h-88 h-89 h-90 h-91 h-92 h-93 h-94 h-95 h-96", + "sm:h-0 sm:h-1 sm:h-2 sm:h-3 sm:h-4 sm:h-5 sm:h-6 sm:h-7 sm:h-8 sm:h-9 sm:h-10 sm:h-11 sm:h-12 sm:h-13 sm:h-14 sm:h-15 sm:h-16 sm:h-17 sm:h-18 sm:h-19 sm:h-20 sm:h-21 sm:h-22 sm:h-23 sm:h-24 sm:h-25 sm:h-26 sm:h-27 sm:h-28 sm:h-29 sm:h-30 sm:h-31 sm:h-32 sm:h-33 sm:h-34 sm:h-35 sm:h-36 sm:h-37 sm:h-38 sm:h-39 sm:h-40 sm:h-41 sm:h-42 sm:h-43 sm:h-44 sm:h-45 sm:h-46 sm:h-47 sm:h-48 sm:h-49 sm:h-50 sm:h-51 sm:h-52 sm:h-53 sm:h-54 sm:h-55 sm:h-56 sm:h-57 sm:h-58 sm:h-59 sm:h-60 sm:h-61 sm:h-62 sm:h-63 sm:h-64 sm:h-65 sm:h-66 sm:h-67 sm:h-68 sm:h-69 sm:h-70 sm:h-71 sm:h-72 sm:h-73 sm:h-74 sm:h-75 sm:h-76 sm:h-77 sm:h-78 sm:h-79 sm:h-80 sm:h-81 sm:h-82 sm:h-83 sm:h-84 sm:h-85 sm:h-86 sm:h-87 sm:h-88 sm:h-89 sm:h-90 sm:h-91 sm:h-92 sm:h-93 sm:h-94 sm:h-95 sm:h-96", + "md:h-0 md:h-1 md:h-2 md:h-3 md:h-4 md:h-5 md:h-6 md:h-7 md:h-8 md:h-9 md:h-10 md:h-11 md:h-12 md:h-13 md:h-14 md:h-15 md:h-16 md:h-17 md:h-18 md:h-19 md:h-20 md:h-21 md:h-22 md:h-23 md:h-24 md:h-25 md:h-26 md:h-27 md:h-28 md:h-29 md:h-30 md:h-31 md:h-32 md:h-33 md:h-34 md:h-35 md:h-36 md:h-37 md:h-38 md:h-39 md:h-40 md:h-41 md:h-42 md:h-43 md:h-44 md:h-45 md:h-46 md:h-47 md:h-48 md:h-49 md:h-50 md:h-51 md:h-52 md:h-53 md:h-54 md:h-55 md:h-56 md:h-57 md:h-58 md:h-59 md:h-60 md:h-61 md:h-62 md:h-63 md:h-64 md:h-65 md:h-66 md:h-67 md:h-68 md:h-69 md:h-70 md:h-71 md:h-72 md:h-73 md:h-74 md:h-75 md:h-76 md:h-77 md:h-78 md:h-79 md:h-80 md:h-81 md:h-82 md:h-83 md:h-84 md:h-85 md:h-86 md:h-87 md:h-88 md:h-89 md:h-90 md:h-91 md:h-92 md:h-93 md:h-94 md:h-95 md:h-96", + "lg:h-0 lg:h-1 lg:h-2 lg:h-3 lg:h-4 lg:h-5 lg:h-6 lg:h-7 lg:h-8 lg:h-9 lg:h-10 lg:h-11 lg:h-12 lg:h-13 lg:h-14 lg:h-15 lg:h-16 lg:h-17 lg:h-18 lg:h-19 lg:h-20 lg:h-21 lg:h-22 lg:h-23 lg:h-24 lg:h-25 lg:h-26 lg:h-27 lg:h-28 lg:h-29 lg:h-30 lg:h-31 lg:h-32 lg:h-33 lg:h-34 lg:h-35 lg:h-36 lg:h-37 lg:h-38 lg:h-39 lg:h-40 lg:h-41 lg:h-42 lg:h-43 lg:h-44 lg:h-45 lg:h-46 lg:h-47 lg:h-48 lg:h-49 lg:h-50 lg:h-51 lg:h-52 lg:h-53 lg:h-54 lg:h-55 lg:h-56 lg:h-57 lg:h-58 lg:h-59 lg:h-60 lg:h-61 lg:h-62 lg:h-63 lg:h-64 lg:h-65 lg:h-66 lg:h-67 lg:h-68 lg:h-69 lg:h-70 lg:h-71 lg:h-72 lg:h-73 lg:h-74 lg:h-75 lg:h-76 lg:h-77 lg:h-78 lg:h-79 lg:h-80 lg:h-81 lg:h-82 lg:h-83 lg:h-84 lg:h-85 lg:h-86 lg:h-87 lg:h-88 lg:h-89 lg:h-90 lg:h-91 lg:h-92 lg:h-93 lg:h-94 lg:h-95 lg:h-96", + "xl:h-0 xl:h-1 xl:h-2 xl:h-3 xl:h-4 xl:h-5 xl:h-6 xl:h-7 xl:h-8 xl:h-9 xl:h-10 xl:h-11 xl:h-12 xl:h-13 xl:h-14 xl:h-15 xl:h-16 xl:h-17 xl:h-18 xl:h-19 xl:h-20 xl:h-21 xl:h-22 xl:h-23 xl:h-24 xl:h-25 xl:h-26 xl:h-27 xl:h-28 xl:h-29 xl:h-30 xl:h-31 xl:h-32 xl:h-33 xl:h-34 xl:h-35 xl:h-36 xl:h-37 xl:h-38 xl:h-39 xl:h-40 xl:h-41 xl:h-42 xl:h-43 xl:h-44 xl:h-45 xl:h-46 xl:h-47 xl:h-48 xl:h-49 xl:h-50 xl:h-51 xl:h-52 xl:h-53 xl:h-54 xl:h-55 xl:h-56 xl:h-57 xl:h-58 xl:h-59 xl:h-60 xl:h-61 xl:h-62 xl:h-63 xl:h-64 xl:h-65 xl:h-66 xl:h-67 xl:h-68 xl:h-69 xl:h-70 xl:h-71 xl:h-72 xl:h-73 xl:h-74 xl:h-75 xl:h-76 xl:h-77 xl:h-78 xl:h-79 xl:h-80 xl:h-81 xl:h-82 xl:h-83 xl:h-84 xl:h-85 xl:h-86 xl:h-87 xl:h-88 xl:h-89 xl:h-90 xl:h-91 xl:h-92 xl:h-93 xl:h-94 xl:h-95 xl:h-96", + "2xl:h-0 2xl:h-1 2xl:h-2 2xl:h-3 2xl:h-4 2xl:h-5 2xl:h-6 2xl:h-7 2xl:h-8 2xl:h-9 2xl:h-10 2xl:h-11 2xl:h-12 2xl:h-13 2xl:h-14 2xl:h-15 2xl:h-16 2xl:h-17 2xl:h-18 2xl:h-19 2xl:h-20 2xl:h-21 2xl:h-22 2xl:h-23 2xl:h-24 2xl:h-25 2xl:h-26 2xl:h-27 2xl:h-28 2xl:h-29 2xl:h-30 2xl:h-31 2xl:h-32 2xl:h-33 2xl:h-34 2xl:h-35 2xl:h-36 2xl:h-37 2xl:h-38 2xl:h-39 2xl:h-40 2xl:h-41 2xl:h-42 2xl:h-43 2xl:h-44 2xl:h-45 2xl:h-46 2xl:h-47 2xl:h-48 2xl:h-49 2xl:h-50 2xl:h-51 2xl:h-52 2xl:h-53 2xl:h-54 2xl:h-55 2xl:h-56 2xl:h-57 2xl:h-58 2xl:h-59 2xl:h-60 2xl:h-61 2xl:h-62 2xl:h-63 2xl:h-64 2xl:h-65 2xl:h-66 2xl:h-67 2xl:h-68 2xl:h-69 2xl:h-70 2xl:h-71 2xl:h-72 2xl:h-73 2xl:h-74 2xl:h-75 2xl:h-76 2xl:h-77 2xl:h-78 2xl:h-79 2xl:h-80 2xl:h-81 2xl:h-82 2xl:h-83 2xl:h-84 2xl:h-85 2xl:h-86 2xl:h-87 2xl:h-88 2xl:h-89 2xl:h-90 2xl:h-91 2xl:h-92 2xl:h-93 2xl:h-94 2xl:h-95 2xl:h-96", +]; + function MyApp({ Component, pageProps }) { return ( { + podNames.add(pod.metadata.name); pod.spec.containers.forEach((container) => { if (container?.resources?.limits?.cpu) { cpuLimit += parseCpu(container?.resources?.limits?.cpu); @@ -66,40 +68,32 @@ export default async function handler(req, res) { }); }); - const podStatsList = await Promise.all( - pods.map(async (pod) => { - let depMem = 0; - let depCpu = 0; - const podMetrics = await metricsApi - .getPodMetrics(namespace, pod.metadata.name) - .then((response) => response) - .catch((err) => { - // 404 generally means that the metrics have not been populated yet - if (err.statusCode !== 404) { - logger.error("Error getting pod metrics: %d %s %s", err.statusCode, err.body, err.response); - } - return null; - }); - if (podMetrics) { - podMetrics.containers.forEach((container) => { - depMem += parseMemory(container.usage.memory); - depCpu += parseCpu(container.usage.cpu); - }); + const namespaceMetrics = await metricsApi + .getPodMetrics(namespace) + .then((response) => response.items) + .catch((err) => { + // 404 generally means that the metrics have not been populated yet + if (err.statusCode !== 404) { + logger.error("Error getting pod metrics: %d %s %s", err.statusCode, err.body, err.response); } - return { - mem: depMem, - cpu: depCpu, - }; - }), - ); + return null; + }); + const stats = { mem: 0, cpu: 0, }; - podStatsList.forEach((podStat) => { - stats.mem += podStat.mem; - stats.cpu += podStat.cpu; - }); + + if (namespaceMetrics) { + const podMetrics = namespaceMetrics.filter((item) => podNames.has(item.metadata.name)); + podMetrics.forEach((metrics) => { + metrics.containers.forEach((container) => { + stats.mem += parseMemory(container.usage.memory); + stats.cpu += parseCpu(container.usage.cpu); + }); + }); + } + stats.cpuLimit = cpuLimit; stats.memLimit = memLimit; stats.cpuUsage = cpuLimit ? 100 * (stats.cpu / cpuLimit) : 0; diff --git a/src/pages/api/releases.js b/src/pages/api/releases.js index f15930c2..01d0e8a5 100644 --- a/src/pages/api/releases.js +++ b/src/pages/api/releases.js @@ -1,12 +1,12 @@ -import cachedFetch from "utils/proxy/cached-fetch"; import createLogger from "utils/logger"; +import { cachedRequest } from "utils/proxy/http"; const logger = createLogger("releases"); export default async function handler(req, res) { const releasesURL = "https://api.github.com/repos/gethomepage/homepage/releases"; try { - return res.send(await cachedFetch(releasesURL, 5)); + return res.send(await cachedRequest(releasesURL, 5)); } catch (e) { logger.error(`Error checking GitHub releases: ${e}`); return res.send([]); diff --git a/src/pages/api/search/searchSuggestion.js b/src/pages/api/search/searchSuggestion.js index 7d5d250b..13f3f301 100644 --- a/src/pages/api/search/searchSuggestion.js +++ b/src/pages/api/search/searchSuggestion.js @@ -1,7 +1,8 @@ import { searchProviders } from "components/widgets/search/search"; -import cachedFetch from "utils/proxy/cached-fetch"; +import { getSettings } from "utils/config/config"; import { widgetsFromConfig } from "utils/config/widget-helpers"; +import { cachedRequest } from "utils/proxy/http"; export default async function handler(req, res) { const { query, providerName } = req.query; @@ -12,13 +13,21 @@ export default async function handler(req, res) { const widgets = await widgetsFromConfig(); const searchWidget = widgets.find((w) => w.type === "search"); - provider.url = searchWidget.options.url; - provider.suggestionUrl = searchWidget.options.suggestionUrl; + if (searchWidget) { + provider.url = searchWidget.options.url; + provider.suggestionUrl = searchWidget.options.suggestionUrl; + } else { + const settings = getSettings(); + if (settings.quicklaunch && settings.quicklaunch.provider === "custom") { + provider.url = settings.quicklaunch.url; + provider.suggestionUrl = settings.quicklaunch.suggestionUrl; + } + } } if (!provider.suggestionUrl) { return res.json([query, []]); // Responde with the same array format but with no suggestions. } - return res.send(await cachedFetch(`${provider.suggestionUrl}${encodeURIComponent(query)}`, 5, "Mozilla/5.0")); + return res.send(await cachedRequest(`${provider.suggestionUrl}${encodeURIComponent(query)}`, 5, "Mozilla/5.0")); } diff --git a/src/pages/api/services/index.js b/src/pages/api/services/index.js index 46d0a721..f6ba54c8 100644 --- a/src/pages/api/services/index.js +++ b/src/pages/api/services/index.js @@ -1,5 +1,8 @@ +import { readIdentitySettings } from "utils/identity/identity-helpers"; import { servicesResponse } from "utils/config/api-response"; +import { getSettings } from "utils/config/config"; export default async function handler(req, res) { - res.send(await servicesResponse()); + const { provider, groups } = readIdentitySettings(getSettings().identity); + res.send(await servicesResponse(provider.getIdentity(req), groups)); } diff --git a/src/pages/api/services/proxy.js b/src/pages/api/services/proxy.js index 3f8adc88..0cdf806f 100644 --- a/src/pages/api/services/proxy.js +++ b/src/pages/api/services/proxy.js @@ -1,9 +1,9 @@ -import { formatApiCall } from "utils/proxy/api-helpers"; -import createLogger from "utils/logger"; -import genericProxyHandler from "utils/proxy/handlers/generic"; -import widgets from "widgets/widgets"; -import calendarProxyHandler from "widgets/calendar/proxy"; import getServiceWidget from "utils/config/service-helpers"; +import createLogger from "utils/logger"; +import { formatApiCall } from "utils/proxy/api-helpers"; +import genericProxyHandler from "utils/proxy/handlers/generic"; +import calendarProxyHandler from "widgets/calendar/proxy"; +import widgets from "widgets/widgets"; const logger = createLogger("servicesProxy"); diff --git a/src/pages/api/widgets/glances.js b/src/pages/api/widgets/glances.js index 199c133e..f0a3a7d9 100644 --- a/src/pages/api/widgets/glances.js +++ b/src/pages/api/widgets/glances.js @@ -1,6 +1,6 @@ -import { httpProxy } from "utils/proxy/http"; -import createLogger from "utils/logger"; import { getPrivateWidgetOptions } from "utils/config/widget-helpers"; +import createLogger from "utils/logger"; +import { httpProxy } from "utils/proxy/http"; const logger = createLogger("glances"); diff --git a/src/pages/api/widgets/index.js b/src/pages/api/widgets/index.js index 513e02e9..447ef340 100644 --- a/src/pages/api/widgets/index.js +++ b/src/pages/api/widgets/index.js @@ -1,5 +1,8 @@ +import { readIdentitySettings } from "utils/identity/identity-helpers"; import { widgetsResponse } from "utils/config/api-response"; +import { getSettings } from "utils/config/config"; export default async function handler(req, res) { - res.send(await widgetsResponse()); + const { provider } = readIdentitySettings(getSettings().identity); + res.send(await widgetsResponse(provider.getIdentity(req))); } diff --git a/src/pages/api/widgets/longhorn.js b/src/pages/api/widgets/longhorn.js index 9126e937..c45086bc 100644 --- a/src/pages/api/widgets/longhorn.js +++ b/src/pages/api/widgets/longhorn.js @@ -1,6 +1,6 @@ -import { httpProxy } from "../../../utils/proxy/http"; -import createLogger from "../../../utils/logger"; import { getSettings } from "../../../utils/config/config"; +import createLogger from "../../../utils/logger"; +import { httpProxy } from "../../../utils/proxy/http"; const logger = createLogger("longhorn"); diff --git a/src/pages/api/widgets/openmeteo.js b/src/pages/api/widgets/openmeteo.js index e63847b4..28f2e4f0 100644 --- a/src/pages/api/widgets/openmeteo.js +++ b/src/pages/api/widgets/openmeteo.js @@ -1,9 +1,9 @@ -import cachedFetch from "utils/proxy/cached-fetch"; +import { cachedRequest } from "utils/proxy/http"; export default async function handler(req, res) { const { latitude, longitude, units, cache, timezone } = req.query; const degrees = units === "metric" ? "celsius" : "fahrenheit"; const timezeone = timezone ?? "auto"; const apiUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&daily=sunrise,sunset¤t_weather=true&temperature_unit=${degrees}&timezone=${timezeone}`; - return res.send(await cachedFetch(apiUrl, cache)); + return res.send(await cachedRequest(apiUrl, cache)); } diff --git a/src/pages/api/widgets/openweathermap.js b/src/pages/api/widgets/openweathermap.js index 089ee804..993ee1f5 100644 --- a/src/pages/api/widgets/openweathermap.js +++ b/src/pages/api/widgets/openweathermap.js @@ -1,6 +1,6 @@ -import cachedFetch from "utils/proxy/cached-fetch"; import { getSettings } from "utils/config/config"; import { getPrivateWidgetOptions } from "utils/config/widget-helpers"; +import { cachedRequest } from "utils/proxy/http"; export default async function handler(req, res) { const { latitude, longitude, units, provider, cache, lang, index } = req.query; @@ -26,5 +26,5 @@ export default async function handler(req, res) { const apiUrl = `https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${apiKey}&units=${units}&lang=${lang}`; - return res.send(await cachedFetch(apiUrl, cache)); + return res.send(await cachedRequest(apiUrl, cache)); } diff --git a/src/pages/api/widgets/stocks.js b/src/pages/api/widgets/stocks.js index 3941a773..77881ad7 100644 --- a/src/pages/api/widgets/stocks.js +++ b/src/pages/api/widgets/stocks.js @@ -1,6 +1,6 @@ -import cachedFetch from "utils/proxy/cached-fetch"; import { getSettings } from "utils/config/config"; import createLogger from "utils/logger"; +import { cachedRequest } from "utils/proxy/http"; const logger = createLogger("stocks"); @@ -60,7 +60,7 @@ export default async function handler(req, res) { const apiUrl = `https://finnhub.io/api/v1/quote?symbol=${ticker}&token=${apiKey}`; // Finnhub free accounts allow up to 60 calls/minute // https://finnhub.io/pricing - const { c, dp } = await cachedFetch(apiUrl, cache || 1); + const { c, dp } = await cachedRequest(apiUrl, cache || 1); logger.debug("Finnhub API response for %s: %o", ticker, { c, dp }); // API sometimes returns 200, but values returned are `null` diff --git a/src/pages/api/widgets/weather.js b/src/pages/api/widgets/weather.js index 9d0451ce..78418f74 100644 --- a/src/pages/api/widgets/weather.js +++ b/src/pages/api/widgets/weather.js @@ -1,6 +1,6 @@ -import cachedFetch from "utils/proxy/cached-fetch"; import { getSettings } from "utils/config/config"; import { getPrivateWidgetOptions } from "utils/config/widget-helpers"; +import { cachedRequest } from "utils/proxy/http"; export default async function handler(req, res) { const { latitude, longitude, provider, cache, lang, index } = req.query; @@ -26,5 +26,5 @@ export default async function handler(req, res) { const apiUrl = `http://api.weatherapi.com/v1/current.json?q=${latitude},${longitude}&key=${apiKey}&lang=${lang}`; - return res.send(await cachedFetch(apiUrl, cache)); + return res.send(await cachedRequest(apiUrl, cache)); } diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 5055a22b..95c19dd3 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -1,31 +1,33 @@ /* eslint-disable react/no-array-index-key */ -import useSWR, { SWRConfig } from "swr"; -import Head from "next/head"; -import Script from "next/script"; -import dynamic from "next/dynamic"; import classNames from "classnames"; -import { useTranslation } from "next-i18next"; -import { useEffect, useContext, useState, useMemo } from "react"; -import { BiError } from "react-icons/bi"; -import { serverSideTranslations } from "next-i18next/serverSideTranslations"; -import { useRouter } from "next/router"; -import Tab, { slugifyAndEncode } from "components/tab"; -import ServicesGroup from "components/services/group"; import BookmarksGroup from "components/bookmarks/group"; -import Widget from "components/widgets/widget"; -import Revalidate from "components/toggles/revalidate"; -import { ColorContext } from "utils/contexts/color"; -import { ThemeContext } from "utils/contexts/theme"; -import { SettingsContext } from "utils/contexts/settings"; -import { TabContext } from "utils/contexts/tab"; import ErrorBoundary from "components/errorboundry"; import QuickLaunch from "components/quicklaunch"; +import ServicesGroup from "components/services/group"; +import Tab, { slugifyAndEncode } from "components/tab"; +import Revalidate from "components/toggles/revalidate"; +import Widget from "components/widgets/widget"; +import { useTranslation } from "next-i18next"; +import { serverSideTranslations } from "next-i18next/serverSideTranslations"; +import dynamic from "next/dynamic"; +import Head from "next/head"; +import { useRouter } from "next/router"; +import Script from "next/script"; +import { useContext, useEffect, useMemo, useState } from "react"; +import { BiError } from "react-icons/bi"; +import useSWR, { SWRConfig, unstable_serialize as unstableSerialize } from "swr"; +import { ColorContext } from "utils/contexts/color"; +import { SettingsContext } from "utils/contexts/settings"; +import { TabContext } from "utils/contexts/tab"; +import { ThemeContext } from "utils/contexts/theme"; +import { fetchWithIdentity, readIdentitySettings } from "utils/identity/identity-helpers"; +import NullIdentityProvider from "utils/identity/null"; import { bookmarksResponse, servicesResponse, widgetsResponse } from "utils/config/api-response"; -import themes from "utils/styles/themes"; import { getSettings } from "utils/config/config"; import useWindowFocus from "utils/hooks/window-focus"; import createLogger from "utils/logger"; +import themes from "utils/styles/themes"; const ThemeToggle = dynamic(() => import("components/toggles/theme"), { ssr: false, @@ -41,25 +43,28 @@ const Version = dynamic(() => import("components/version"), { const rightAlignedWidgets = ["weatherapi", "openweathermap", "weather", "openmeteo", "search", "datetime"]; -export async function getStaticProps() { +export async function getServerSideProps({ req }) { let logger; try { logger = createLogger("index"); - const { providers, ...settings } = getSettings(); + const { providers, identity, ...settings } = getSettings(); + const { provider, groups } = readIdentitySettings(identity); - const services = await servicesResponse(); - const bookmarks = await bookmarksResponse(); - const widgets = await widgetsResponse(); + const services = await servicesResponse(provider.getIdentity(req), groups); + const bookmarks = await bookmarksResponse(provider.getIdentity(req), groups); + const widgets = await widgetsResponse(provider.getIdentity(req)); + const identityContext = provider.getContext(req); return { props: { initialSettings: settings, fallback: { - "/api/services": services, - "/api/bookmarks": bookmarks, - "/api/widgets": widgets, + [unstableSerialize(["/api/services", identityContext])]: services, + [unstableSerialize(["/api/bookmarks", identityContext])]: bookmarks, + [unstableSerialize(["/api/widgets", identityContext])]: widgets, "/api/hash": false, }, + identityContext, ...(await serverSideTranslations(settings.language ?? "en")), }, }; @@ -67,22 +72,24 @@ export async function getStaticProps() { if (logger && e) { logger.error(e); } + const identityContext = NullIdentityProvider.create().getContext(req); return { props: { initialSettings: {}, fallback: { - "/api/services": [], - "/api/bookmarks": [], - "/api/widgets": [], + [unstableSerialize(["/api/services", identityContext])]: [], + [unstableSerialize(["/api/bookmarks", identityContext])]: [], + [unstableSerialize(["/api/widgets", identityContext])]: [], "/api/hash": false, }, + identityContext, ...(await serverSideTranslations("en")), }, }; } } -function Index({ initialSettings, fallback }) { +function Index({ initialSettings, fallback, identityContext }) { const windowFocused = useWindowFocus(); const [stale, setStale] = useState(false); const { data: errorsData } = useSWR("/api/validate"); @@ -171,7 +178,7 @@ function Index({ initialSettings, fallback }) { return ( fetch(resource, init).then((res) => res.json()) }}> - + ); @@ -197,7 +204,7 @@ function getAllServices(services) { return [...services.map(getServices).flat()]; } -function Home({ initialSettings }) { +function Home({ initialSettings, identityContext }) { const { i18n } = useTranslation(); const { theme, setTheme } = useContext(ThemeContext); const { color, setColor } = useContext(ColorContext); @@ -209,9 +216,9 @@ function Home({ initialSettings }) { setSettings(initialSettings); }, [initialSettings, setSettings]); - const { data: services } = useSWR("/api/services"); - const { data: bookmarks } = useSWR("/api/bookmarks"); - const { data: widgets } = useSWR("/api/widgets"); + const { data: services } = useSWR(["/api/services", identityContext], fetchWithIdentity); + const { data: bookmarks } = useSWR(["/api/bookmarks", identityContext], fetchWithIdentity); + const { data: widgets } = useSWR(["/api/widgets", identityContext], fetchWithIdentity); const servicesAndBookmarks = [...bookmarks.map((bg) => bg.bookmarks).flat(), ...getAllServices(services)].filter( (i) => i?.href, @@ -323,7 +330,7 @@ function Home({ initialSettings }) { key={group.name} group={group} layout={settings.layout?.[group.name]} - fiveColumns={settings.fiveColumns} + maxGroupColumns={settings.fiveColumns ? 5 : settings.maxGroupColumns} disableCollapse={settings.disableCollapse} useEqualHeights={settings.useEqualHeights} groupsInitiallyCollapsed={settings.groupsInitiallyCollapsed} @@ -334,6 +341,7 @@ function Home({ initialSettings }) { bookmarks={group} layout={settings.layout?.[group.name]} disableCollapse={settings.disableCollapse} + maxGroupColumns={settings.maxBookmarkGroupColumns ?? settings.maxGroupColumns} groupsInitiallyCollapsed={settings.groupsInitiallyCollapsed} /> ), @@ -347,7 +355,7 @@ function Home({ initialSettings }) { key={group.name} group={group} layout={settings.layout?.[group.name]} - fiveColumns={settings.fiveColumns} + maxGroupColumns={settings.fiveColumns ? 5 : settings.maxGroupColumns} disableCollapse={settings.disableCollapse} groupsInitiallyCollapsed={settings.groupsInitiallyCollapsed} /> @@ -362,6 +370,7 @@ function Home({ initialSettings }) { bookmarks={group} layout={settings.layout?.[group.name]} disableCollapse={settings.disableCollapse} + maxGroupColumns={settings.maxBookmarkGroupColumns ?? settings.maxGroupColumns} groupsInitiallyCollapsed={settings.groupsInitiallyCollapsed} bookmarksStyle={settings.bookmarksStyle} /> @@ -377,6 +386,8 @@ function Home({ initialSettings }) { bookmarks, settings.layout, settings.fiveColumns, + settings.maxGroupColumns, + settings.maxBookmarkGroupColumns, settings.disableCollapse, settings.useEqualHeights, settings.cardBlur, @@ -417,7 +428,12 @@ function Home({ initialSettings }) {