diff --git a/.all-contributorsrc b/.all-contributorsrc
index a230a468..3cf5e765 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -665,6 +665,78 @@
       "contributions": [
         "translation"
       ]
+    },
+    {
+      "login": "sambartik",
+      "name": "Samuel Bartík",
+      "avatar_url": "https://avatars.githubusercontent.com/u/63553146?v=4",
+      "profile": "https://github.com/sambartik",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "frank-cywong",
+      "name": "Chun Yeung Wong",
+      "avatar_url": "https://avatars.githubusercontent.com/u/90653148?v=4",
+      "profile": "https://github.com/frank-cywong",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "TheMeanCanEHdian",
+      "name": "TheMeanCanEHdian",
+      "avatar_url": "https://avatars.githubusercontent.com/u/16025103?v=4",
+      "profile": "https://github.com/TheMeanCanEHdian",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "Gylesie",
+      "name": "Gylesie",
+      "avatar_url": "https://avatars.githubusercontent.com/u/86306812?v=4",
+      "profile": "https://github.com/Gylesie",
+      "contributions": [
+        "code"
+      ]
+    },
+    {
+      "login": "Fhd-pro",
+      "name": "Fhd-pro",
+      "avatar_url": "https://avatars.githubusercontent.com/u/82862079?v=4",
+      "profile": "https://github.com/Fhd-pro",
+      "contributions": [
+        "translation"
+      ]
+    },
+    {
+      "login": "PovilasID",
+      "name": "PovilasID",
+      "avatar_url": "https://avatars.githubusercontent.com/u/396243?v=4",
+      "profile": "https://github.com/PovilasID",
+      "contributions": [
+        "translation"
+      ]
+    },
+    {
+      "login": "byakurau",
+      "name": "byakurau",
+      "avatar_url": "https://avatars.githubusercontent.com/u/1811683?v=4",
+      "profile": "https://github.com/byakurau",
+      "contributions": [
+        "translation"
+      ]
+    },
+    {
+      "login": "miknii",
+      "name": "miknii",
+      "avatar_url": "https://avatars.githubusercontent.com/u/109232569?v=4",
+      "profile": "https://github.com/miknii",
+      "contributions": [
+        "translation"
+      ]
     }
   ],
   "badgeTemplate": "<a href=\"#contributors-\"><img alt=\"All Contributors\" src=\"https://img.shields.io/badge/all_contributors-<%= contributors.length %>-orange.svg\"/></a>",
@@ -673,5 +745,5 @@
   "projectOwner": "sct",
   "repoType": "github",
   "repoHost": "https://github.com",
-  "skipCi": true
+  "skipCi": false
 }
diff --git a/.dockerignore b/.dockerignore
index 7d669c86..21a5da86 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -26,3 +26,4 @@ public/os_logo_filled.png
 public/preview.jpg
 snap
 stylelint.config.js
+cypress
diff --git a/.eslintrc.js b/.eslintrc.js
index b1c6f4b9..5af484c5 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -7,6 +7,7 @@ module.exports = {
     'plugin:jsx-a11y/recommended',
     'plugin:react/recommended',
     'plugin:react-hooks/recommended',
+    'plugin:react/jsx-runtime',
     'prettier',
   ],
   parserOptions: {
@@ -26,11 +27,21 @@ module.exports = {
     'react-hooks/rules-of-hooks': 'error',
     'react-hooks/exhaustive-deps': 'warn',
     '@typescript-eslint/explicit-function-return-type': 'off',
-    'prettier/prettier': ['error', { endOfLine: 'auto' }],
     'formatjs/no-offset': 'error',
     'no-unused-vars': 'off',
     '@typescript-eslint/no-unused-vars': ['error'],
+    '@typescript-eslint/array-type': ['error', { default: 'array' }],
     'jsx-a11y/no-onchange': 'off',
+    '@typescript-eslint/consistent-type-imports': [
+      'error',
+      {
+        prefer: 'type-imports',
+      },
+    ],
+    'no-relative-import-paths/no-relative-import-paths': [
+      'error',
+      { allowSameFolder: true },
+    ],
   },
   overrides: [
     {
@@ -40,7 +51,7 @@ module.exports = {
       },
     },
   ],
-  plugins: ['jsx-a11y', 'prettier', 'react-hooks', 'formatjs'],
+  plugins: ['jsx-a11y', 'react-hooks', 'formatjs', 'no-relative-import-paths'],
   settings: {
     react: {
       pragma: 'React',
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
deleted file mode 100644
index 7590f941..00000000
--- a/.github/dependabot.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-version: 2
-updates:
-  - package-ecosystem: npm
-    directory: '/'
-    schedule:
-      interval: daily
-      time: '20:00'
-    open-pull-requests-limit: 10
-  - package-ecosystem: github-actions
-    directory: '/'
-    schedule:
-      interval: daily
-      time: '20:00'
-    open-pull-requests-limit: 10
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5aa1572d..05db03e1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -13,16 +13,18 @@ jobs:
     name: Lint & Test Build
     if: github.event_name == 'pull_request'
     runs-on: ubuntu-20.04
-    container: node:16.14-alpine
+    container: node:16.17-alpine
     steps:
       - name: Checkout
         uses: actions/checkout@v3
       - name: Install dependencies
         env:
-          HUSKY_SKIP_INSTALL: 1
+          HUSKY: 0
         run: yarn
       - name: Lint
         run: yarn lint
+      - name: Formatting
+        run: yarn format:check
       - name: Build
         run: yarn build
 
@@ -34,29 +36,29 @@ jobs:
       - name: Checkout
         uses: actions/checkout@v3
       - name: Set up QEMU
-        uses: docker/setup-qemu-action@v1
+        uses: docker/setup-qemu-action@v2
       - name: Set up Docker Buildx
-        uses: docker/setup-buildx-action@v1
+        uses: docker/setup-buildx-action@v2
       - name: Cache Docker layers
-        uses: actions/cache@v2
+        uses: actions/cache@v3
         with:
           path: /tmp/.buildx-cache
           key: ${{ runner.os }}-buildx-${{ github.sha }}
           restore-keys: |
             ${{ runner.os }}-buildx-
       - name: Log in to Docker Hub
-        uses: docker/login-action@v1
+        uses: docker/login-action@v2
         with:
           username: ${{ secrets.DOCKER_USERNAME }}
           password: ${{ secrets.DOCKER_TOKEN }}
       - name: Log in to GitHub Container Registry
-        uses: docker/login-action@v1
+        uses: docker/login-action@v2
         with:
           registry: ghcr.io
           username: ${{ github.repository_owner }}
           password: ${{ secrets.GITHUB_TOKEN }}
       - name: Build and push
-        uses: docker/build-push-action@v2
+        uses: docker/build-push-action@v3
         with:
           context: .
           file: ./Dockerfile
@@ -86,7 +88,7 @@ jobs:
     runs-on: ubuntu-20.04
     steps:
       - name: Get Build Job Status
-        uses: technote-space/workflow-conclusion-action@v2
+        uses: technote-space/workflow-conclusion-action@v3
       - name: Combine Job Status
         id: status
         run: |
diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml
new file mode 100644
index 00000000..ecd260dd
--- /dev/null
+++ b/.github/workflows/cypress.yml
@@ -0,0 +1,30 @@
+name: Cypress Tests
+
+on:
+  pull_request:
+    branches:
+      - '*'
+  push:
+    branches:
+      - develop
+
+jobs:
+  cypress-run:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v3
+      - name: Cypress run
+        uses: cypress-io/github-action@v4
+        with:
+          build: yarn cypress:build
+          start: yarn start
+          wait-on: 'http://localhost:5055'
+          record: true
+        env:
+          CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          WITH_MIGRATIONS: true
+          # Fix test titles in cypress dashboard
+          COMMIT_INFO_MESSAGE: ${{github.event.pull_request.title}}
+          COMMIT_INFO_SHA: ${{github.event.pull_request.head.sha}}
diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml
index 307c9263..6e0d8f3d 100644
--- a/.github/workflows/preview.yml
+++ b/.github/workflows/preview.yml
@@ -16,22 +16,22 @@ jobs:
         id: get_version
         run: echo ::set-output name=VERSION::${GITHUB_REF#refs/tags/}
       - name: Set up QEMU
-        uses: docker/setup-qemu-action@v1
+        uses: docker/setup-qemu-action@v2
       - name: Set up Docker Buildx
-        uses: docker/setup-buildx-action@v1
+        uses: docker/setup-buildx-action@v2
       - name: Log in to Docker Hub
-        uses: docker/login-action@v1
+        uses: docker/login-action@v2
         with:
           username: ${{ secrets.DOCKER_USERNAME }}
           password: ${{ secrets.DOCKER_TOKEN }}
       - name: Log in to GitHub Container Registry
-        uses: docker/login-action@v1
+        uses: docker/login-action@v2
         with:
           registry: ghcr.io
           username: ${{ github.repository_owner }}
           password: ${{ secrets.GITHUB_TOKEN }}
       - name: Build and push
-        uses: docker/build-push-action@v2
+        uses: docker/build-push-action@v3
         with:
           context: .
           file: ./Dockerfile
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 8dc0b98b..cd6b2616 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -21,16 +21,16 @@ jobs:
         with:
           node-version: 16
       - name: Set up QEMU
-        uses: docker/setup-qemu-action@v1
+        uses: docker/setup-qemu-action@v2
       - name: Set up Docker Buildx
-        uses: docker/setup-buildx-action@v1
+        uses: docker/setup-buildx-action@v2
       - name: Log in to Docker Hub
-        uses: docker/login-action@v1
+        uses: docker/login-action@v2
         with:
           username: ${{ secrets.DOCKER_USERNAME }}
           password: ${{ secrets.DOCKER_TOKEN }}
       - name: Log in to GitHub Container Registry
-        uses: docker/login-action@v1
+        uses: docker/login-action@v2
         with:
           registry: ghcr.io
           username: ${{ github.repository_owner }}
@@ -74,7 +74,7 @@ jobs:
             echo ::set-output name=RELEASE::edge
           fi
       - name: Set Up QEMU
-        uses: docker/setup-qemu-action@v1
+        uses: docker/setup-qemu-action@v2
         with:
           image: tonistiigi/binfmt@sha256:df15403e06a03c2f461c1f7938b171fda34a5849eb63a70e2a2109ed5a778bde
       - name: Build Snap Package
@@ -83,7 +83,7 @@ jobs:
         with:
           architecture: ${{ matrix.architecture }}
       - name: Upload Snap Package
-        uses: actions/upload-artifact@v2
+        uses: actions/upload-artifact@v3
         with:
           name: overseerr-snap-package-${{ matrix.architecture }}
           path: ${{ steps.build.outputs.snap }}
@@ -105,7 +105,7 @@ jobs:
     runs-on: ubuntu-20.04
     steps:
       - name: Get Build Job Status
-        uses: technote-space/workflow-conclusion-action@v2
+        uses: technote-space/workflow-conclusion-action@v3
       - name: Combine Job Status
         id: status
         run: |
diff --git a/.github/workflows/snap.yaml b/.github/workflows/snap.yaml
new file mode 100644
index 00000000..bf00e04d
--- /dev/null
+++ b/.github/workflows/snap.yaml
@@ -0,0 +1,88 @@
+name: Publish Snap
+
+on:
+  push:
+    branches:
+      - develop
+
+jobs:
+  jobs:
+    name: Job Check
+    runs-on: ubuntu-20.04
+    if: "!contains(github.event.head_commit.message, '[skip ci]')"
+    steps:
+      - name: Cancel Previous Runs
+        uses: styfle/cancel-workflow-action@0.10.0
+        with:
+          access_token: ${{ secrets.GITHUB_TOKEN }}
+
+  build-snap:
+    name: Build Snap Package (${{ matrix.architecture }})
+    needs: jobs
+    runs-on: ubuntu-20.04
+    strategy:
+      fail-fast: false
+      matrix:
+        architecture:
+          - amd64
+          - arm64
+          - armhf
+    steps:
+      - name: Checkout Code
+        uses: actions/checkout@v3
+      - name: Prepare
+        id: prepare
+        run: |
+          git fetch --prune --unshallow --tags
+          if [[ $GITHUB_REF == refs/tags/* || $GITHUB_REF == refs/heads/master ]]; then
+            echo ::set-output name=RELEASE::stable
+          else
+            echo ::set-output name=RELEASE::edge
+          fi
+      - name: Set Up QEMU
+        uses: docker/setup-qemu-action@v2
+      - name: Build Snap Package
+        uses: diddlesnaps/snapcraft-multiarch-action@v1
+        id: build
+        with:
+          architecture: ${{ matrix.architecture }}
+      - name: Upload Snap Package
+        uses: actions/upload-artifact@v3
+        with:
+          name: overseerr-snap-package-${{ matrix.architecture }}
+          path: ${{ steps.build.outputs.snap }}
+      - name: Review Snap Package
+        uses: diddlesnaps/snapcraft-review-tools-action@v1
+        with:
+          snap: ${{ steps.build.outputs.snap }}
+      - name: Publish Snap Package
+        uses: snapcore/action-publish@v1
+        with:
+          store_login: ${{ secrets.SNAP_LOGIN }}
+          snap: ${{ steps.build.outputs.snap }}
+          release: ${{ steps.prepare.outputs.RELEASE }}
+
+  discord:
+    name: Send Discord Notification
+    needs: build-snap
+    if: always() && !contains(github.event.head_commit.message, '[skip ci]')
+    runs-on: ubuntu-20.04
+    steps:
+      - name: Get Build Job Status
+        uses: technote-space/workflow-conclusion-action@v3
+      - name: Combine Job Status
+        id: status
+        run: |
+          failures=(neutral, skipped, timed_out, action_required)
+          if [[ ${array[@]} =~ $WORKFLOW_CONCLUSION ]]; then
+            echo ::set-output name=status::failure
+          else
+            echo ::set-output name=status::$WORKFLOW_CONCLUSION
+          fi
+      - name: Post Status to Discord
+        uses: sarisia/actions-status-discord@v1
+        with:
+          webhook: ${{ secrets.DISCORD_WEBHOOK }}
+          status: ${{ steps.status.outputs.status }}
+          title: ${{ github.workflow }}
+          nofail: true
diff --git a/.gitignore b/.gitignore
index 7d606105..4f7c3ce6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -53,3 +53,14 @@ config/db/db.sqlite3-journal
 
 # VS Code
 .vscode/launch.json
+
+# Cypress
+cypress.env.json
+cypress/videos
+cypress/screenshots
+
+# ESLint
+.eslintcache
+
+# TS Build Info
+tsconfig.tsbuildinfo
diff --git a/.prettierrc.js b/.prettierrc.js
new file mode 100644
index 00000000..c735fffa
--- /dev/null
+++ b/.prettierrc.js
@@ -0,0 +1,5 @@
+module.exports = {
+  plugins: [require('./merged-prettier-plugin.js')],
+  singleQuote: true,
+  trailingComma: 'es5',
+};
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index 80a16c64..8dc1918f 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -11,9 +11,6 @@
     // https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode
     "esbenp.prettier-vscode",
 
-    // https://marketplace.visualstudio.com/items?itemName=eg2.vscode-npm-script
-    "eg2.vscode-npm-script",
-
     // https://marketplace.visualstudio.com/items?itemName=Orta.vscode-jest
     "Orta.vscode-jest",
 
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 26aca34b..45da7ba6 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -15,8 +15,6 @@
       "database": "./config/db/db.sqlite3"
     }
   ],
-  "editor.codeActionsOnSave": {
-    "source.organizeImports": true
-  },
-  "editor.formatOnSave": true
+  "editor.formatOnSave": true,
+  "typescript.preferences.importModuleSpecifier": "non-relative"
 }
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index e54e45d6..51df9e14 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -86,7 +86,7 @@ When adding new UI text, please try to adhere to the following guidelines:
 1. Be concise and clear, and use as few words as possible to make your point.
 2. Use the Oxford comma where appropriate.
 3. Use the appropriate Unicode characters for ellipses, arrows, and other special characters/symbols.
-4. Capitalize proper nouns, such as Plex, Radarr, Sonarr, Telegram, Slack, Pushover, etc. Be sure to also use the official capitalization for any abbreviations; e.g., TMDb and IMDb have a lowercase 'b', whereas TheTVDB has a capital 'B'.
+4. Capitalize proper nouns, such as Plex, Radarr, Sonarr, Telegram, Slack, Pushover, etc. Be sure to also use the official capitalization for any abbreviations; e.g., IMDb has a lowercase 'b', whereas TMDB and TheTVDB have a capital 'B'.
 5. Title case headings, button text, and form labels. Note that verbs such as "is" should be capitalized, whereas prepositions like "from" should be lowercase (unless as the first or last word of the string, in which case they are also capitalized).
 6. Capitalize the first word in validation error messages, dropdowns, and form "tips." These strings should not end in punctuation.
 7. Ensure that toast notification strings are complete sentences ending in punctuation.
diff --git a/Dockerfile b/Dockerfile
index 8f3ed32c..851ba472 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM node:16.14-alpine AS BUILD_IMAGE
+FROM node:16.17-alpine AS BUILD_IMAGE
 
 WORKDIR /app
 
@@ -14,7 +14,7 @@ RUN \
   esac
 
 COPY package.json yarn.lock ./
-RUN yarn install --frozen-lockfile --network-timeout 1000000
+RUN CYPRESS_INSTALL_BINARY=0 yarn install --frozen-lockfile --network-timeout 1000000
 
 COPY . ./
 
@@ -33,7 +33,7 @@ RUN touch config/DOCKER
 RUN echo "{\"commitTag\": \"${COMMIT_TAG}\"}" > committag.json
 
 
-FROM node:16.14-alpine
+FROM node:16.17-alpine
 
 WORKDIR /app
 
diff --git a/Dockerfile.local b/Dockerfile.local
index f0228b6b..39e0534f 100644
--- a/Dockerfile.local
+++ b/Dockerfile.local
@@ -1,4 +1,4 @@
-FROM node:16.14-alpine
+FROM node:16.17-alpine
 
 COPY . /app
 WORKDIR /app
diff --git a/README.md b/README.md
index 6bca69eb..05de02e2 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@
 <a href="https://lgtm.com/projects/g/sct/overseerr/context:javascript"><img alt="Language grade: JavaScript" src="https://img.shields.io/lgtm/grade/javascript/g/sct/overseerr.svg?logo=lgtm&logoWidth=18"/></a>
 <a href="https://github.com/sct/overseerr/blob/develop/LICENSE"><img alt="GitHub" src="https://img.shields.io/github/license/sct/overseerr"></a>
 <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
-<a href="#contributors-"><img alt="All Contributors" src="https://img.shields.io/badge/all_contributors-72-orange.svg"/></a>
+<a href="#contributors-"><img alt="All Contributors" src="https://img.shields.io/badge/all_contributors-80-orange.svg"/></a>
 <!-- ALL-CONTRIBUTORS-BADGE:END -->
 </p>
 
@@ -167,6 +167,16 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
   <tr>
     <td align="center"><a href="https://github.com/Andersborrits"><img src="https://avatars.githubusercontent.com/u/29452218?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Andersborrits</b></sub></a><br /><a href="#translation-Andersborrits" title="Translation">🌍</a></td>
     <td align="center"><a href="http://maxentrouault.fr"><img src="https://avatars.githubusercontent.com/u/67283154?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Maxent</b></sub></a><br /><a href="#translation-Maxentr" title="Translation">🌍</a></td>
+    <td align="center"><a href="https://github.com/sambartik"><img src="https://avatars.githubusercontent.com/u/63553146?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Samuel Bartík</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=sambartik" title="Code">💻</a></td>
+    <td align="center"><a href="https://github.com/frank-cywong"><img src="https://avatars.githubusercontent.com/u/90653148?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Chun Yeung Wong</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=frank-cywong" title="Code">💻</a></td>
+    <td align="center"><a href="https://github.com/TheMeanCanEHdian"><img src="https://avatars.githubusercontent.com/u/16025103?v=4?s=100" width="100px;" alt=""/><br /><sub><b>TheMeanCanEHdian</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=TheMeanCanEHdian" title="Code">💻</a></td>
+    <td align="center"><a href="https://github.com/Gylesie"><img src="https://avatars.githubusercontent.com/u/86306812?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Gylesie</b></sub></a><br /><a href="https://github.com/sct/overseerr/commits?author=Gylesie" title="Code">💻</a></td>
+    <td align="center"><a href="https://github.com/Fhd-pro"><img src="https://avatars.githubusercontent.com/u/82862079?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Fhd-pro</b></sub></a><br /><a href="#translation-Fhd-pro" title="Translation">🌍</a></td>
+  </tr>
+  <tr>
+    <td align="center"><a href="https://github.com/PovilasID"><img src="https://avatars.githubusercontent.com/u/396243?v=4?s=100" width="100px;" alt=""/><br /><sub><b>PovilasID</b></sub></a><br /><a href="#translation-PovilasID" title="Translation">🌍</a></td>
+    <td align="center"><a href="https://github.com/byakurau"><img src="https://avatars.githubusercontent.com/u/1811683?v=4?s=100" width="100px;" alt=""/><br /><sub><b>byakurau</b></sub></a><br /><a href="#translation-byakurau" title="Translation">🌍</a></td>
+    <td align="center"><a href="https://github.com/miknii"><img src="https://avatars.githubusercontent.com/u/109232569?v=4?s=100" width="100px;" alt=""/><br /><sub><b>miknii</b></sub></a><br /><a href="#translation-miknii" title="Translation">🌍</a></td>
   </tr>
 </table>
 
diff --git a/cypress.config.ts b/cypress.config.ts
new file mode 100644
index 00000000..07b0c8b1
--- /dev/null
+++ b/cypress.config.ts
@@ -0,0 +1,19 @@
+import { defineConfig } from 'cypress';
+
+export default defineConfig({
+  projectId: 'onnqy3',
+  e2e: {
+    baseUrl: 'http://localhost:5055',
+    experimentalSessionAndOrigin: true,
+  },
+  env: {
+    ADMIN_EMAIL: 'admin@seerr.dev',
+    ADMIN_PASSWORD: 'test1234',
+    USER_EMAIL: 'friend@seerr.dev',
+    USER_PASSWORD: 'test1234',
+  },
+  retries: {
+    runMode: 2,
+    openMode: 0,
+  },
+});
diff --git a/cypress/config/settings.cypress.json b/cypress/config/settings.cypress.json
new file mode 100644
index 00000000..bb7b661b
--- /dev/null
+++ b/cypress/config/settings.cypress.json
@@ -0,0 +1,149 @@
+{
+  "clientId": "6919275e-142a-48d8-be6b-93594cbd4626",
+  "vapidPrivate": "tmnslaO8ZWN6bNbSEv_rolPeBTlNxOwCCAHrM9oZz3M",
+  "vapidPublic": "BK_EpP8NDm9waor2zn6_S28o3ZYv4kCkJOfYpO3pt3W6jnPmxrgTLANUBNbbyaNatPnSQ12De9CeqSYQrqWzHTs",
+  "main": {
+   "apiKey": "testkey",
+   "applicationTitle": "Overseerr",
+   "applicationUrl": "",
+   "csrfProtection": false,
+   "cacheImages": false,
+   "defaultPermissions": 32,
+   "defaultQuotas": {
+    "movie": {},
+    "tv": {}
+   },
+   "hideAvailable": false,
+   "localLogin": true,
+   "newPlexLogin": true,
+   "region": "",
+   "originalLanguage": "",
+   "trustProxy": false,
+   "partialRequestsEnabled": true,
+   "locale": "en"
+  },
+  "plex": {
+   "name": "Seerr",
+   "ip": "192.168.1.1",
+   "port": 32400,
+   "useSsl": false,
+   "libraries": [
+    {
+     "id": "1",
+     "name": "Movies",
+     "enabled": true,
+     "type": "movie"
+    }
+   ],
+   "machineId": "test"
+  },
+  "tautulli": {},
+  "radarr": [],
+  "sonarr": [],
+  "public": {
+   "initialized": true
+  },
+  "notifications": {
+   "agents": {
+    "email": {
+     "enabled": false,
+     "options": {
+      "emailFrom": "",
+      "smtpHost": "",
+      "smtpPort": 587,
+      "secure": false,
+      "ignoreTls": false,
+      "requireTls": false,
+      "allowSelfSigned": false,
+      "senderName": "Overseerr"
+     }
+    },
+    "discord": {
+     "enabled": false,
+     "types": 0,
+     "options": {
+      "webhookUrl": "",
+      "enableMentions": true
+     }
+    },
+    "lunasea": {
+     "enabled": false,
+     "types": 0,
+     "options": {
+      "webhookUrl": ""
+     }
+    },
+    "slack": {
+     "enabled": false,
+     "types": 0,
+     "options": {
+      "webhookUrl": ""
+     }
+    },
+    "telegram": {
+     "enabled": false,
+     "types": 0,
+     "options": {
+      "botAPI": "",
+      "chatId": "",
+      "sendSilently": false
+     }
+    },
+    "pushbullet": {
+     "enabled": false,
+     "types": 0,
+     "options": {
+      "accessToken": ""
+     }
+    },
+    "pushover": {
+     "enabled": false,
+     "types": 0,
+     "options": {
+      "accessToken": "",
+      "userToken": ""
+     }
+    },
+    "webhook": {
+     "enabled": false,
+     "types": 0,
+     "options": {
+      "webhookUrl": "",
+      "jsonPayload": "IntcbiAgICBcIm5vdGlmaWNhdGlvbl90eXBlXCI6IFwie3tub3RpZmljYXRpb25fdHlwZX19XCIsXG4gICAgXCJldmVudFwiOiBcInt7ZXZlbnR9fVwiLFxuICAgIFwic3ViamVjdFwiOiBcInt7c3ViamVjdH19XCIsXG4gICAgXCJtZXNzYWdlXCI6IFwie3ttZXNzYWdlfX1cIixcbiAgICBcImltYWdlXCI6IFwie3tpbWFnZX19XCIsXG4gICAgXCJ7e21lZGlhfX1cIjoge1xuICAgICAgICBcIm1lZGlhX3R5cGVcIjogXCJ7e21lZGlhX3R5cGV9fVwiLFxuICAgICAgICBcInRtZGJJZFwiOiBcInt7bWVkaWFfdG1kYmlkfX1cIixcbiAgICAgICAgXCJ0dmRiSWRcIjogXCJ7e21lZGlhX3R2ZGJpZH19XCIsXG4gICAgICAgIFwic3RhdHVzXCI6IFwie3ttZWRpYV9zdGF0dXN9fVwiLFxuICAgICAgICBcInN0YXR1czRrXCI6IFwie3ttZWRpYV9zdGF0dXM0a319XCJcbiAgICB9LFxuICAgIFwie3tyZXF1ZXN0fX1cIjoge1xuICAgICAgICBcInJlcXVlc3RfaWRcIjogXCJ7e3JlcXVlc3RfaWR9fVwiLFxuICAgICAgICBcInJlcXVlc3RlZEJ5X2VtYWlsXCI6IFwie3tyZXF1ZXN0ZWRCeV9lbWFpbH19XCIsXG4gICAgICAgIFwicmVxdWVzdGVkQnlfdXNlcm5hbWVcIjogXCJ7e3JlcXVlc3RlZEJ5X3VzZXJuYW1lfX1cIixcbiAgICAgICAgXCJyZXF1ZXN0ZWRCeV9hdmF0YXJcIjogXCJ7e3JlcXVlc3RlZEJ5X2F2YXRhcn19XCJcbiAgICB9LFxuICAgIFwie3tpc3N1ZX19XCI6IHtcbiAgICAgICAgXCJpc3N1ZV9pZFwiOiBcInt7aXNzdWVfaWR9fVwiLFxuICAgICAgICBcImlzc3VlX3R5cGVcIjogXCJ7e2lzc3VlX3R5cGV9fVwiLFxuICAgICAgICBcImlzc3VlX3N0YXR1c1wiOiBcInt7aXNzdWVfc3RhdHVzfX1cIixcbiAgICAgICAgXCJyZXBvcnRlZEJ5X2VtYWlsXCI6IFwie3tyZXBvcnRlZEJ5X2VtYWlsfX1cIixcbiAgICAgICAgXCJyZXBvcnRlZEJ5X3VzZXJuYW1lXCI6IFwie3tyZXBvcnRlZEJ5X3VzZXJuYW1lfX1cIixcbiAgICAgICAgXCJyZXBvcnRlZEJ5X2F2YXRhclwiOiBcInt7cmVwb3J0ZWRCeV9hdmF0YXJ9fVwiXG4gICAgfSxcbiAgICBcInt7Y29tbWVudH19XCI6IHtcbiAgICAgICAgXCJjb21tZW50X21lc3NhZ2VcIjogXCJ7e2NvbW1lbnRfbWVzc2FnZX19XCIsXG4gICAgICAgIFwiY29tbWVudGVkQnlfZW1haWxcIjogXCJ7e2NvbW1lbnRlZEJ5X2VtYWlsfX1cIixcbiAgICAgICAgXCJjb21tZW50ZWRCeV91c2VybmFtZVwiOiBcInt7Y29tbWVudGVkQnlfdXNlcm5hbWV9fVwiLFxuICAgICAgICBcImNvbW1lbnRlZEJ5X2F2YXRhclwiOiBcInt7Y29tbWVudGVkQnlfYXZhdGFyfX1cIlxuICAgIH0sXG4gICAgXCJ7e2V4dHJhfX1cIjogW11cbn0i"
+     }
+    },
+    "webpush": {
+     "enabled": false,
+     "options": {}
+    },
+    "gotify": {
+     "enabled": false,
+     "types": 0,
+     "options": {
+      "url": "",
+      "token": ""
+     }
+    }
+   }
+  },
+  "jobs": {
+   "plex-recently-added-scan": {
+    "schedule": "0 */5 * * * *"
+   },
+   "plex-full-scan": {
+    "schedule": "0 0 3 * * *"
+   },
+   "radarr-scan": {
+    "schedule": "0 0 4 * * *"
+   },
+   "sonarr-scan": {
+    "schedule": "0 30 4 * * *"
+   },
+   "download-sync": {
+    "schedule": "0 * * * * *"
+   },
+   "download-sync-reset": {
+    "schedule": "0 0 1 * * *"
+   }
+  }
+ }
diff --git a/cypress/e2e/discover.cy.ts b/cypress/e2e/discover.cy.ts
new file mode 100644
index 00000000..3489061b
--- /dev/null
+++ b/cypress/e2e/discover.cy.ts
@@ -0,0 +1,210 @@
+const clickFirstTitleCardInSlider = (sliderTitle: string): void => {
+  cy.contains('.slider-header', sliderTitle)
+    .next('[data-testid=media-slider]')
+    .find('[data-testid=title-card]')
+    .first()
+    .trigger('mouseover')
+    .find('[data-testid=title-card-title]')
+    .invoke('text')
+    .then((text) => {
+      cy.contains('.slider-header', sliderTitle)
+        .next('[data-testid=media-slider]')
+        .find('[data-testid=title-card]')
+        .first()
+        .click();
+      cy.get('[data-testid=media-title]').should('contain', text);
+    });
+};
+
+describe('Discover', () => {
+  beforeEach(() => {
+    cy.loginAsAdmin();
+  });
+
+  it('loads a trending item', () => {
+    cy.intercept('/api/v1/discover/trending*').as('getTrending');
+    cy.visit('/');
+    cy.wait('@getTrending');
+    clickFirstTitleCardInSlider('Trending');
+  });
+
+  it('loads popular movies', () => {
+    cy.intercept('/api/v1/discover/movies*').as('getPopularMovies');
+    cy.visit('/');
+    cy.wait('@getPopularMovies');
+    clickFirstTitleCardInSlider('Popular Movies');
+  });
+
+  it('loads upcoming movies', () => {
+    cy.intercept('/api/v1/discover/movies/upcoming*').as('getUpcomingMovies');
+    cy.visit('/');
+    cy.wait('@getUpcomingMovies');
+    clickFirstTitleCardInSlider('Upcoming Movies');
+  });
+
+  it('loads popular series', () => {
+    cy.intercept('/api/v1/discover/tv*').as('getPopularTv');
+    cy.visit('/');
+    cy.wait('@getPopularTv');
+    clickFirstTitleCardInSlider('Popular Series');
+  });
+
+  it('loads upcoming series', () => {
+    cy.intercept('/api/v1/discover/tv/upcoming*').as('getUpcomingSeries');
+    cy.visit('/');
+    cy.wait('@getUpcomingSeries');
+    clickFirstTitleCardInSlider('Upcoming Series');
+  });
+
+  it('displays error for media with invalid TMDB ID', () => {
+    cy.intercept('GET', '/api/v1/media?*', {
+      pageInfo: { pages: 1, pageSize: 20, results: 1, page: 1 },
+      results: [
+        {
+          downloadStatus: [],
+          downloadStatus4k: [],
+          id: 1922,
+          mediaType: 'movie',
+          tmdbId: 998814,
+          tvdbId: null,
+          imdbId: null,
+          status: 5,
+          status4k: 1,
+          createdAt: '2022-08-18T18:11:13.000Z',
+          updatedAt: '2022-08-18T19:56:41.000Z',
+          lastSeasonChange: '2022-08-18T19:56:41.000Z',
+          mediaAddedAt: '2022-08-18T19:56:41.000Z',
+          serviceId: null,
+          serviceId4k: null,
+          externalServiceId: null,
+          externalServiceId4k: null,
+          externalServiceSlug: null,
+          externalServiceSlug4k: null,
+          ratingKey: null,
+          ratingKey4k: null,
+          seasons: [],
+        },
+      ],
+    }).as('getMedia');
+
+    cy.visit('/');
+    cy.wait('@getMedia');
+    cy.contains('.slider-header', 'Recently Added')
+      .next('[data-testid=media-slider]')
+      .find('[data-testid=title-card]')
+      .first()
+      .find('[data-testid=title-card-title]')
+      .contains('Movie Not Found');
+  });
+
+  it('displays error for request with invalid TMDB ID', () => {
+    cy.intercept('GET', '/api/v1/request?*', {
+      pageInfo: { pages: 1, pageSize: 10, results: 1, page: 1 },
+      results: [
+        {
+          id: 582,
+          status: 1,
+          createdAt: '2022-08-18T18:11:13.000Z',
+          updatedAt: '2022-08-18T18:11:13.000Z',
+          type: 'movie',
+          is4k: false,
+          serverId: null,
+          profileId: null,
+          rootFolder: null,
+          languageProfileId: null,
+          tags: null,
+          media: {
+            downloadStatus: [],
+            downloadStatus4k: [],
+            id: 1922,
+            mediaType: 'movie',
+            tmdbId: 998814,
+            tvdbId: null,
+            imdbId: null,
+            status: 2,
+            status4k: 1,
+            createdAt: '2022-08-18T18:11:13.000Z',
+            updatedAt: '2022-08-18T18:11:13.000Z',
+            lastSeasonChange: '2022-08-18T18:11:13.000Z',
+            mediaAddedAt: null,
+            serviceId: null,
+            serviceId4k: null,
+            externalServiceId: null,
+            externalServiceId4k: null,
+            externalServiceSlug: null,
+            externalServiceSlug4k: null,
+            ratingKey: null,
+            ratingKey4k: null,
+          },
+          seasons: [],
+          modifiedBy: null,
+          requestedBy: {
+            permissions: 4194336,
+            id: 18,
+            email: 'friend@seerr.dev',
+            plexUsername: null,
+            username: '',
+            recoveryLinkExpirationDate: null,
+            userType: 2,
+            avatar:
+              'https://gravatar.com/avatar/c77fdc27cab83732b8623d2ea873d330?default=mm&size=200',
+            movieQuotaLimit: null,
+            movieQuotaDays: null,
+            tvQuotaLimit: null,
+            tvQuotaDays: null,
+            createdAt: '2022-08-17T04:55:28.000Z',
+            updatedAt: '2022-08-17T04:55:28.000Z',
+            requestCount: 1,
+            displayName: 'friend@seerr.dev',
+          },
+          seasonCount: 0,
+        },
+      ],
+    }).as('getRequests');
+
+    cy.visit('/');
+    cy.wait('@getRequests');
+    cy.contains('.slider-header', 'Recent Requests')
+      .next('[data-testid=media-slider]')
+      .find('[data-testid=request-card]')
+      .first()
+      .find('[data-testid=request-card-title]')
+      .contains('Movie Not Found');
+  });
+
+  it('loads plex watchlist', () => {
+    cy.intercept('/api/v1/discover/watchlist', {
+      fixture: 'watchlist.json',
+    }).as('getWatchlist');
+    // Wait for one of the watchlist movies to resolve
+    cy.intercept('/api/v1/movie/361743').as('getTmdbMovie');
+
+    cy.visit('/');
+
+    cy.wait('@getWatchlist');
+
+    const sliderHeader = cy.contains('.slider-header', 'Your Plex Watchlist');
+
+    sliderHeader.scrollIntoView();
+
+    cy.wait('@getTmdbMovie');
+    // Wait a little longer to make sure the movie component reloaded
+    cy.wait(500);
+
+    sliderHeader
+      .next('[data-testid=media-slider]')
+      .find('[data-testid=title-card]')
+      .first()
+      .trigger('mouseover')
+      .find('[data-testid=title-card-title]')
+      .invoke('text')
+      .then((text) => {
+        cy.contains('.slider-header', 'Plex Watchlist')
+          .next('[data-testid=media-slider]')
+          .find('[data-testid=title-card]')
+          .first()
+          .click();
+        cy.get('[data-testid=media-title]').should('contain', text);
+      });
+  });
+});
diff --git a/cypress/e2e/login.cy.ts b/cypress/e2e/login.cy.ts
new file mode 100644
index 00000000..1c955417
--- /dev/null
+++ b/cypress/e2e/login.cy.ts
@@ -0,0 +1,13 @@
+describe('Login Page', () => {
+  it('succesfully logs in as an admin', () => {
+    cy.loginAsAdmin();
+    cy.visit('/');
+    cy.contains('Trending');
+  });
+
+  it('succesfully logs in as a local user', () => {
+    cy.loginAsUser();
+    cy.visit('/');
+    cy.contains('Trending');
+  });
+});
diff --git a/cypress/e2e/movie-details.cy.ts b/cypress/e2e/movie-details.cy.ts
new file mode 100644
index 00000000..1d3ecf3f
--- /dev/null
+++ b/cypress/e2e/movie-details.cy.ts
@@ -0,0 +1,12 @@
+describe('Movie Details', () => {
+  it('loads a movie page', () => {
+    cy.loginAsAdmin();
+    // Try to load minions: rise of gru
+    cy.visit('/movie/438148');
+
+    cy.get('[data-testid=media-title]').should(
+      'contain',
+      'Minions: The Rise of Gru (2022)'
+    );
+  });
+});
diff --git a/cypress/e2e/pull-to-refresh.cy.ts b/cypress/e2e/pull-to-refresh.cy.ts
new file mode 100644
index 00000000..d56c5589
--- /dev/null
+++ b/cypress/e2e/pull-to-refresh.cy.ts
@@ -0,0 +1,25 @@
+describe('Pull To Refresh', () => {
+  beforeEach(() => {
+    cy.login(Cypress.env('ADMIN_EMAIL'), Cypress.env('ADMIN_PASSWORD'));
+    cy.viewport(390, 844);
+    cy.visitMobile('/');
+  });
+
+  it('reloads the current page', () => {
+    cy.wait(500);
+
+    cy.intercept({
+      method: 'GET',
+      url: '/api/v1/*',
+    }).as('apiCall');
+
+    cy.get('.searchbar').swipe('bottom', [190, 400]);
+
+    cy.wait('@apiCall').then((interception) => {
+      assert.isNotNull(
+        interception.response.body,
+        'API was called and received data'
+      );
+    });
+  });
+});
diff --git a/cypress/e2e/settings/general-settings.cy.ts b/cypress/e2e/settings/general-settings.cy.ts
new file mode 100644
index 00000000..3717f65b
--- /dev/null
+++ b/cypress/e2e/settings/general-settings.cy.ts
@@ -0,0 +1,32 @@
+describe('General Settings', () => {
+  beforeEach(() => {
+    cy.loginAsAdmin();
+  });
+
+  it('opens the settings page from the home page', () => {
+    cy.visit('/');
+
+    cy.get('[data-testid=sidebar-toggle]').click();
+    cy.get('[data-testid=sidebar-menu-settings-mobile]').click();
+
+    cy.get('.heading').should('contain', 'General Settings');
+  });
+
+  it('modifies setting that requires restart', () => {
+    cy.visit('/settings');
+
+    cy.get('#trustProxy').click();
+    cy.get('form').submit();
+    cy.get('[data-testid=modal-title]').should(
+      'contain',
+      'Server Restart Required'
+    );
+
+    cy.get('[data-testid=modal-ok-button]').click();
+    cy.get('[data-testid=modal-title]').should('not.exist');
+
+    cy.get('[type=checkbox]#trustProxy').click();
+    cy.get('form').submit();
+    cy.get('[data-testid=modal-title]').should('not.exist');
+  });
+});
diff --git a/cypress/e2e/tv-details.cy.ts b/cypress/e2e/tv-details.cy.ts
new file mode 100644
index 00000000..5b4bd049
--- /dev/null
+++ b/cypress/e2e/tv-details.cy.ts
@@ -0,0 +1,28 @@
+describe('TV Details', () => {
+  it('loads a tv details page', () => {
+    cy.loginAsAdmin();
+    // Try to load stranger things
+    cy.visit('/tv/66732');
+
+    cy.get('[data-testid=media-title]').should(
+      'contain',
+      'Stranger Things (2016)'
+    );
+  });
+
+  it('shows seasons and expands episodes', () => {
+    cy.loginAsAdmin();
+
+    // Try to load stranger things
+    cy.visit('/tv/66732');
+
+    // intercept request for season info
+    cy.intercept('/api/v1/tv/66732/season/4').as('season4');
+
+    cy.contains('Season 4').should('be.visible').scrollIntoView().click();
+
+    cy.wait('@season4');
+
+    cy.contains('Chapter Nine').should('be.visible');
+  });
+});
diff --git a/cypress/e2e/user/auto-request-settings.cy.ts b/cypress/e2e/user/auto-request-settings.cy.ts
new file mode 100644
index 00000000..e7f5727b
--- /dev/null
+++ b/cypress/e2e/user/auto-request-settings.cy.ts
@@ -0,0 +1,74 @@
+const visitUserEditPage = (email: string): void => {
+  cy.visit('/users');
+
+  cy.contains('[data-testid=user-list-row]', email).contains('Edit').click();
+};
+
+describe('Auto Request Settings', () => {
+  beforeEach(() => {
+    cy.loginAsAdmin();
+  });
+
+  it('should not see watchlist sync settings on an account without permissions', () => {
+    visitUserEditPage(Cypress.env('USER_EMAIL'));
+
+    cy.contains('Auto-Request Movies').should('not.exist');
+    cy.contains('Auto-Request Series').should('not.exist');
+  });
+
+  it('should see watchlist sync settings on an admin account', () => {
+    visitUserEditPage(Cypress.env('ADMIN_EMAIL'));
+
+    cy.contains('Auto-Request Movies').should('exist');
+    cy.contains('Auto-Request Series').should('exist');
+  });
+
+  it('should see auto-request settings after being given permission', () => {
+    visitUserEditPage(Cypress.env('USER_EMAIL'));
+
+    cy.get('[data-testid=settings-nav-desktop').contains('Permissions').click();
+
+    cy.get('#autorequest').should('not.be.checked').click();
+
+    cy.intercept('/api/v1/user/*/settings/permissions').as('userPermissions');
+
+    cy.contains('Save Changes').click();
+
+    cy.wait('@userPermissions');
+
+    cy.reload();
+
+    cy.get('#autorequest').should('be.checked');
+    cy.get('#autorequestmovies').should('be.checked');
+    cy.get('#autorequesttv').should('be.checked');
+
+    cy.get('[data-testid=settings-nav-desktop').contains('General').click();
+
+    cy.contains('Auto-Request Movies').should('exist');
+    cy.contains('Auto-Request Series').should('exist');
+
+    cy.get('#watchlistSyncMovies').should('not.be.checked').click();
+    cy.get('#watchlistSyncTv').should('not.be.checked').click();
+
+    cy.intercept('/api/v1/user/*/settings/main').as('userMain');
+
+    cy.contains('Save Changes').click();
+
+    cy.wait('@userMain');
+
+    cy.reload();
+
+    cy.get('#watchlistSyncMovies').should('be.checked').click();
+    cy.get('#watchlistSyncTv').should('be.checked').click();
+
+    cy.contains('Save Changes').click();
+
+    cy.wait('@userMain');
+
+    cy.get('[data-testid=settings-nav-desktop').contains('Permissions').click();
+
+    cy.get('#autorequest').should('be.checked').click();
+
+    cy.contains('Save Changes').click();
+  });
+});
diff --git a/cypress/e2e/user/profile.cy.ts b/cypress/e2e/user/profile.cy.ts
new file mode 100644
index 00000000..9cc38d88
--- /dev/null
+++ b/cypress/e2e/user/profile.cy.ts
@@ -0,0 +1,50 @@
+describe('User Profile', () => {
+  beforeEach(() => {
+    cy.loginAsAdmin();
+  });
+
+  it('opens user profile page from the home page', () => {
+    cy.visit('/');
+
+    cy.get('[data-testid=user-menu]').click();
+    cy.get('[data-testid=user-menu-profile]').click();
+
+    cy.get('h1').should('contain', Cypress.env('ADMIN_EMAIL'));
+  });
+
+  it('loads plex watchlist', () => {
+    cy.intercept('/api/v1/user/[0-9]*/watchlist', {
+      fixture: 'watchlist.json',
+    }).as('getWatchlist');
+    // Wait for one of the watchlist movies to resolve
+    cy.intercept('/api/v1/movie/361743').as('getTmdbMovie');
+
+    cy.visit('/profile');
+
+    cy.wait('@getWatchlist');
+
+    const sliderHeader = cy.contains('.slider-header', 'Plex Watchlist');
+
+    sliderHeader.scrollIntoView();
+
+    cy.wait('@getTmdbMovie');
+    // Wait a little longer to make sure the movie component reloaded
+    cy.wait(500);
+
+    sliderHeader
+      .next('[data-testid=media-slider]')
+      .find('[data-testid=title-card]')
+      .first()
+      .trigger('mouseover')
+      .find('[data-testid=title-card-title]')
+      .invoke('text')
+      .then((text) => {
+        cy.contains('.slider-header', 'Plex Watchlist')
+          .next('[data-testid=media-slider]')
+          .find('[data-testid=title-card]')
+          .first()
+          .click();
+        cy.get('[data-testid=media-title]').should('contain', text);
+      });
+  });
+});
diff --git a/cypress/e2e/user/user-list.cy.ts b/cypress/e2e/user/user-list.cy.ts
new file mode 100644
index 00000000..503bd23f
--- /dev/null
+++ b/cypress/e2e/user/user-list.cy.ts
@@ -0,0 +1,70 @@
+const testUser = {
+  displayName: 'Test User',
+  emailAddress: 'test@seeerr.dev',
+  password: 'test1234',
+};
+
+describe('User List', () => {
+  beforeEach(() => {
+    cy.loginAsAdmin();
+  });
+
+  it('opens the user list from the home page', () => {
+    cy.visit('/');
+
+    cy.get('[data-testid=sidebar-toggle]').click();
+    cy.get('[data-testid=sidebar-menu-users-mobile]').click();
+
+    cy.get('[data-testid=page-header]').should('contain', 'User List');
+  });
+
+  it('can find the admin user and friend user in the user list', () => {
+    cy.visit('/users');
+
+    cy.get('[data-testid=user-list-row]').contains(Cypress.env('ADMIN_EMAIL'));
+    cy.get('[data-testid=user-list-row]').contains(Cypress.env('USER_EMAIL'));
+  });
+
+  it('can create a local user', () => {
+    cy.visit('/users');
+
+    cy.contains('Create Local User').click();
+
+    cy.get('[data-testid=modal-title]').should('contain', 'Create Local User');
+
+    cy.get('#displayName').type(testUser.displayName);
+    cy.get('#email').type(testUser.emailAddress);
+    cy.get('#password').type(testUser.password);
+
+    cy.intercept('/api/v1/user?take=10&skip=0&sort=displayname').as('user');
+
+    cy.get('[data-testid=modal-ok-button]').click();
+
+    cy.wait('@user');
+    // Wait a little longer for the user list to fully re-render
+    cy.wait(1000);
+
+    cy.get('[data-testid=user-list-row]').contains(testUser.emailAddress);
+  });
+
+  it('can delete the created local test user', () => {
+    cy.visit('/users');
+
+    cy.contains('[data-testid=user-list-row]', testUser.emailAddress)
+      .contains('Delete')
+      .click();
+
+    cy.get('[data-testid=modal-title]').should('contain', `Delete User`);
+
+    cy.intercept('/api/v1/user?take=10&skip=0&sort=displayname').as('user');
+
+    cy.get('[data-testid=modal-ok-button]').should('contain', 'Delete').click();
+
+    cy.wait('@user');
+    cy.wait(1000);
+
+    cy.get('[data-testid=user-list-row]')
+      .contains(testUser.emailAddress)
+      .should('not.exist');
+  });
+});
diff --git a/cypress/fixtures/watchlist.json b/cypress/fixtures/watchlist.json
new file mode 100644
index 00000000..896cef74
--- /dev/null
+++ b/cypress/fixtures/watchlist.json
@@ -0,0 +1,25 @@
+{
+  "page": 1,
+  "totalPages": 1,
+  "totalResults": 3,
+  "results": [
+    {
+      "ratingKey": "5d776be17a53e9001e732ab9",
+      "title": "Top Gun: Maverick",
+      "mediaType": "movie",
+      "tmdbId": 361743
+    },
+    {
+      "ratingKey": "5e16338fbc1372003ea68ab3",
+      "title": "Nope",
+      "mediaType": "movie",
+      "tmdbId": 762504
+    },
+    {
+      "ratingKey": "5f409b8452f200004161e126",
+      "title": "Hocus Pocus 2",
+      "mediaType": "movie",
+      "tmdbId": 642885
+    }
+  ]
+}
diff --git a/cypress/support/commands.ts b/cypress/support/commands.ts
new file mode 100644
index 00000000..0eb9c869
--- /dev/null
+++ b/cypress/support/commands.ts
@@ -0,0 +1,35 @@
+/// <reference types="cypress" />
+import 'cy-mobile-commands';
+
+Cypress.Commands.add('login', (email, password) => {
+  cy.session(
+    [email, password],
+    () => {
+      cy.visit('/login');
+      cy.contains('Use your Overseerr account').click();
+
+      cy.get('[data-testid=email]').type(email);
+      cy.get('[data-testid=password]').type(password);
+
+      cy.intercept('/api/v1/auth/local').as('localLogin');
+      cy.get('[data-testid=local-signin-button]').click();
+
+      cy.wait('@localLogin');
+
+      cy.url().should('contain', '/');
+    },
+    {
+      validate() {
+        cy.request('/api/v1/auth/me').its('status').should('eq', 200);
+      },
+    }
+  );
+});
+
+Cypress.Commands.add('loginAsAdmin', () => {
+  cy.login(Cypress.env('ADMIN_EMAIL'), Cypress.env('ADMIN_PASSWORD'));
+});
+
+Cypress.Commands.add('loginAsUser', () => {
+  cy.login(Cypress.env('USER_EMAIL'), Cypress.env('USER_PASSWORD'));
+});
diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts
new file mode 100644
index 00000000..7a7697ca
--- /dev/null
+++ b/cypress/support/e2e.ts
@@ -0,0 +1,7 @@
+import './commands';
+
+before(() => {
+  if (Cypress.env('SEED_DATABASE')) {
+    cy.exec('yarn cypress:prepare');
+  }
+});
diff --git a/cypress/support/index.ts b/cypress/support/index.ts
new file mode 100644
index 00000000..85706761
--- /dev/null
+++ b/cypress/support/index.ts
@@ -0,0 +1,14 @@
+/* eslint-disable @typescript-eslint/no-namespace */
+/// <reference types="cypress" />
+
+declare global {
+  namespace Cypress {
+    interface Chainable {
+      login(email?: string, password?: string): Chainable<Element>;
+      loginAsAdmin(): Chainable<Element>;
+      loginAsUser(): Chainable<Element>;
+    }
+  }
+}
+
+export {};
diff --git a/cypress/tsconfig.json b/cypress/tsconfig.json
new file mode 100644
index 00000000..1b6425b8
--- /dev/null
+++ b/cypress/tsconfig.json
@@ -0,0 +1,10 @@
+{
+  "compilerOptions": {
+    "target": "es5",
+    "lib": ["es5", "dom"],
+    "types": ["cypress", "node"],
+    "resolveJsonModule": true,
+    "esModuleInterop": true
+  },
+  "include": ["**/*.ts"]
+}
diff --git a/docs/extending-overseerr/fail2ban.md b/docs/extending-overseerr/fail2ban.md
index fbfe6fa8..1cf9131f 100644
--- a/docs/extending-overseerr/fail2ban.md
+++ b/docs/extending-overseerr/fail2ban.md
@@ -8,7 +8,7 @@ To use Fail2ban with Overseerr, create a new file named `overseerr.local` in you
 
 ```
 [Definition]
-failregex = .*\[info\]\[Auth\]\: Failed sign-in attempt.*"ip":"<HOST>"
+failregex = .*\[warn\]\[API\]\: Failed sign-in attempt.*"ip":"<HOST>"
 ```
 
 You can then add a jail using this filter in `jail.local`. Please see the [Fail2ban documetation](https://www.fail2ban.org/wiki/index.php/MANUAL_0_8#Jails) for details on how to configure the jail.
diff --git a/docs/extending-overseerr/third-party.md b/docs/extending-overseerr/third-party.md
index 7ff2bcab..e1bacfc6 100644
--- a/docs/extending-overseerr/third-party.md
+++ b/docs/extending-overseerr/third-party.md
@@ -9,7 +9,7 @@
 - [LunaSea](https://docs.lunasea.app/modules/overseerr), a self-hosted controller for mobile and macOS
 - [Requestrr](https://github.com/darkalfx/requestrr/wiki/Configuring-Overseerr), a Discord chatbot
 - [Doplarr](https://github.com/kiranshila/Doplarr), a Discord request bot
-- [Overseerr Assistant](https://github.com/RemiRigal/Overseerr-Assistant), a browser extension for requesting directly from TMDb and IMDb
+- [Overseerr Assistant](https://github.com/RemiRigal/Overseerr-Assistant), a browser extension for requesting directly from TMDB and IMDb
 - [ha-overseerr](https://github.com/vaparr/ha-overseerr), a custom Home Assistant component
 - [OverCLIrr](https://github.com/WillFantom/OverCLIrr), a command-line tool
 - [Overseerr Exporter](https://github.com/WillFantom/overseerr-exporter), a Prometheus exporter
diff --git a/docs/support/faq.md b/docs/support/faq.md
index d3ea3cdc..f487d18f 100644
--- a/docs/support/faq.md
+++ b/docs/support/faq.md
@@ -45,7 +45,7 @@ Overseerr currently supports the following agents:
 - New Plex TV
 - Legacy Plex TV
 - TheTVDB
-- TMDb
+- TMDB
 - [HAMA](https://github.com/ZeroQI/Hama.bundle)
 
 Please verify that your library is using one of the agents previously listed.
@@ -67,7 +67,7 @@ You can also perform the following to verify the media item has a GUID Overseerr
 1. Go to the media item in Plex and **"Get info"** and click on **"View XML"**.
 2. Verify that the media item's GUID follows one of the below formats:
 
-   1. TMDb agent `guid="com.plexapp.agents.themoviedb://1705"`
+   1. TMDB agent `guid="com.plexapp.agents.themoviedb://1705"`
    2. New Plex Movie agent `<Guid id="tmdb://464052"/>`
    3. TheTVDB agent `guid="com.plexapp.agents.thetvdb://78874/1/1"`
    4. Legacy Plex Movie agent `guid="com.plexapp.agents.imdb://tt0765446"`
diff --git a/docs/using-overseerr/notifications/webhooks.md b/docs/using-overseerr/notifications/webhooks.md
index 37a5c048..cd2ada31 100644
--- a/docs/using-overseerr/notifications/webhooks.md
+++ b/docs/using-overseerr/notifications/webhooks.md
@@ -81,7 +81,7 @@ These following special variables are only included in media-related notificatio
 | Variable             | Value                                                                                                          |
 | -------------------- | -------------------------------------------------------------------------------------------------------------- |
 | `{{media_type}}`     | The media type (`movie` or `tv`)                                                                               |
-| `{{media_tmdbid}}`   | The media's TMDb ID                                                                                            |
+| `{{media_tmdbid}}`   | The media's TMDB ID                                                                                            |
 | `{{media_tvdbid}}`   | The media's TheTVDB ID                                                                                         |
 | `{{media_status}}`   | The media's availability status (`UNKNOWN`, `PENDING`, `PROCESSING`, `PARTIALLY_AVAILABLE`, or `AVAILABLE`)    |
 | `{{media_status4k}}` | The media's 4K availability status (`UNKNOWN`, `PENDING`, `PROCESSING`, `PARTIALLY_AVAILABLE`, or `AVAILABLE`) |
diff --git a/merged-prettier-plugin.js b/merged-prettier-plugin.js
new file mode 100644
index 00000000..6908488f
--- /dev/null
+++ b/merged-prettier-plugin.js
@@ -0,0 +1,21 @@
+/* eslint-disable */
+const tailwind = require('prettier-plugin-tailwindcss');
+const organizeImports = require('prettier-plugin-organize-imports');
+
+const combinedFormatter = {
+  ...tailwind,
+  parsers: {
+    ...tailwind.parsers,
+    ...Object.keys(organizeImports.parsers).reduce((acc, key) => {
+      acc[key] = {
+        ...tailwind.parsers[key],
+        preprocess(code, options) {
+          return organizeImports.parsers[key].preprocess(code, options);
+        },
+      };
+      return acc;
+    }, {}),
+  },
+};
+
+module.exports = combinedFormatter;
diff --git a/next.config.js b/next.config.js
index f0a623d4..b0e872e8 100644
--- a/next.config.js
+++ b/next.config.js
@@ -1,3 +1,6 @@
+/**
+ * @type {import('next').NextConfig}
+ */
 module.exports = {
   env: {
     commitTag: process.env.COMMIT_TAG || 'local',
@@ -14,4 +17,7 @@ module.exports = {
 
     return config;
   },
+  experimental: {
+    scrollRestoration: true,
+  },
 };
diff --git a/overseerr-api.yml b/overseerr-api.yml
index 77282ea1..164187de 100644
--- a/overseerr-api.yml
+++ b/overseerr-api.yml
@@ -1793,14 +1793,14 @@ components:
 paths:
   /status:
     get:
-      summary: Get Overseerr version
-      description: Returns the current Overseerr version in a JSON object.
+      summary: Get Overseerr status
+      description: Returns the current Overseerr status in a JSON object.
       security: []
       tags:
         - public
       responses:
         '200':
-          description: Returned version
+          description: Returned status
           content:
             application/json:
               schema:
@@ -1811,6 +1811,12 @@ paths:
                     example: 1.0.0
                   commitTag:
                     type: string
+                  updateAvailable:
+                    type: boolean
+                  commitsBehind:
+                    type: number
+                  restartRequired:
+                    type: boolean
   /status/appdata:
     get:
       summary: Get application data volume status
@@ -2533,6 +2539,12 @@ paths:
             nullable: true
             enum: [debug, info, warn, error]
             default: debug
+        - in: query
+          name: search
+          schema:
+            type: string
+            nullable: true
+            example: plex
       responses:
         '200':
           description: Server log returned
@@ -3170,8 +3182,8 @@ paths:
           name: guid
           required: true
           schema:
-            type: number
-            example: 1
+            type: string
+            example: '9afef5a7-ec89-4d5f-9397-261e96970b50'
       responses:
         '200':
           description: OK
@@ -3506,6 +3518,53 @@ paths:
                       restricted:
                         type: boolean
                         example: false
+  /user/{userId}/watchlist:
+    get:
+      summary: Get user by ID
+      description: |
+        Retrieves a user's Plex Watchlist in a JSON object.
+      tags:
+        - users
+      parameters:
+        - in: path
+          name: userId
+          required: true
+          schema:
+            type: number
+        - in: query
+          name: page
+          schema:
+            type: number
+            example: 1
+            default: 1
+      responses:
+        '200':
+          description: Watchlist data returned
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  page:
+                    type: number
+                  totalPages:
+                    type: number
+                  totalResults:
+                    type: number
+                  results:
+                    type: array
+                    items:
+                      type: object
+                      properties:
+                        tmdbId:
+                          type: number
+                          example: 1
+                        ratingKey:
+                          type: string
+                        type:
+                          type: string
+                        title:
+                          type: string
   /user/{userId}/settings/main:
     get:
       summary: Get general settings for a user
@@ -4397,6 +4456,46 @@ paths:
                     name:
                       type: string
                       example: Genre Name
+  /discover/watchlist:
+    get:
+      summary: Get the Plex watchlist.
+      tags:
+        - search
+      parameters:
+        - in: query
+          name: page
+          schema:
+            type: number
+            example: 1
+            default: 1
+      responses:
+        '200':
+          description: Watchlist data returned
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  page:
+                    type: number
+                  totalPages:
+                    type: number
+                  totalResults:
+                    type: number
+                  results:
+                    type: array
+                    items:
+                      type: object
+                      properties:
+                        tmdbId:
+                          type: number
+                          example: 1
+                        ratingKey:
+                          type: string
+                        type:
+                          type: string
+                        title:
+                          type: string
   /request:
     get:
       summary: Get all requests
@@ -4424,7 +4523,16 @@ paths:
           schema:
             type: string
             nullable: true
-            enum: [all, approved, available, pending, processing, unavailable]
+            enum:
+              [
+                all,
+                approved,
+                available,
+                pending,
+                processing,
+                unavailable,
+                failed,
+              ]
         - in: query
           name: sort
           schema:
@@ -5327,7 +5435,7 @@ paths:
                   $ref: '#/components/schemas/SonarrSeries'
   /regions:
     get:
-      summary: Regions supported by TMDb
+      summary: Regions supported by TMDB
       description: Returns a list of regions in a JSON object.
       tags:
         - tmdb
@@ -5349,7 +5457,7 @@ paths:
                       example: United States of America
   /languages:
     get:
-      summary: Languages supported by TMDb
+      summary: Languages supported by TMDB
       description: Returns a list of languages in a JSON object.
       tags:
         - tmdb
@@ -5414,7 +5522,7 @@ paths:
                 $ref: '#/components/schemas/ProductionCompany'
   /genres/movie:
     get:
-      summary: Get list of official TMDb movie genres
+      summary: Get list of official TMDB movie genres
       description: Returns a list of genres in a JSON array.
       tags:
         - tmdb
@@ -5442,7 +5550,7 @@ paths:
                       example: Family
   /genres/tv:
     get:
-      summary: Get list of official TMDb movie genres
+      summary: Get list of official TMDB movie genres
       description: Returns a list of genres in a JSON array.
       tags:
         - tmdb
@@ -5562,6 +5670,36 @@ paths:
             application/json:
               schema:
                 $ref: '#/components/schemas/Issue'
+
+  /issue/count:
+    get:
+      summary: Gets issue counts
+      description: |
+        Returns the number of open and closed issues, as well as the number of issues of each type.
+      tags:
+        - issue
+      responses:
+        '200':
+          description: Issue counts returned
+          content:
+            application/json:
+              schema:
+                type: object
+                properties:
+                  total:
+                    type: number
+                  video:
+                    type: number
+                  audio:
+                    type: number
+                  subtitles:
+                    type: number
+                  others:
+                    type: number
+                  open:
+                    type: number
+                  closed:
+                    type: number
   /issue/{issueId}:
     get:
       summary: Get issue
diff --git a/package.json b/package.json
index 4e708f1f..0a66f852 100644
--- a/package.json
+++ b/package.json
@@ -3,18 +3,25 @@
   "version": "1.29.1",
   "private": true,
   "scripts": {
-    "dev": "nodemon -e ts --watch server --watch overseerr-api.yml -e .json,.ts,.yml -x ts-node --files --project server/tsconfig.json server/index.ts",
-    "build:server": "tsc --project server/tsconfig.json && copyfiles -u 2 server/templates/**/*.{html,pug} dist/templates",
+    "dev": "nodemon -e ts --watch server --watch overseerr-api.yml -e .json,.ts,.yml -x ts-node -r tsconfig-paths/register --files --project server/tsconfig.json server/index.ts",
+    "build:server": "tsc --project server/tsconfig.json && copyfiles -u 2 server/templates/**/*.{html,pug} dist/templates && tsc-alias -p server/tsconfig.json",
     "build:next": "next build",
     "build": "yarn build:next && yarn build:server",
-    "lint": "eslint \"./server/**/*.{ts,tsx}\" \"./src/**/*.{ts,tsx}\"",
+    "lint": "eslint \"./server/**/*.{ts,tsx}\" \"./src/**/*.{ts,tsx}\" --cache",
     "start": "NODE_ENV=production node dist/index.js",
     "i18n:extract": "extract-messages -l=en -o src/i18n/locale -d en --flat true --overwriteDefault true \"./src/**/!(*.test).{ts,tsx}\"",
-    "migration:generate": "ts-node --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:generate",
-    "migration:create": "ts-node --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:create",
-    "migration:run": "ts-node --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:run",
-    "format": "prettier --write .",
-    "prepare": "husky install"
+    "migration:generate": "ts-node -r tsconfig-paths/register --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:generate -d server/datasource.ts",
+    "migration:create": "ts-node -r tsconfig-paths/register --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:create -d server/datasource.ts",
+    "migration:run": "ts-node -r tsconfig-paths/register --project server/tsconfig.json ./node_modules/typeorm/cli.js migration:run -d server/datasource.ts",
+    "format": "prettier --loglevel warn --write --cache .",
+    "format:check": "prettier --check --cache .",
+    "typecheck": "yarn typecheck:server && yarn typecheck:client",
+    "typecheck:server": "tsc --project server/tsconfig.json --noEmit",
+    "typecheck:client": "tsc --noEmit",
+    "prepare": "husky install",
+    "cypress:open": "cypress open",
+    "cypress:prepare": "ts-node -r tsconfig-paths/register --files --project server/tsconfig.json server/scripts/prepareTestDb.ts",
+    "cypress:build": "yarn build && yarn cypress:prepare"
   },
   "repository": {
     "type": "git",
@@ -22,127 +29,144 @@
   },
   "license": "MIT",
   "dependencies": {
-    "@headlessui/react": "^1.5.0",
-    "@heroicons/react": "^1.0.6",
-    "@supercharge/request-ip": "^1.2.0",
-    "@svgr/webpack": "^6.2.1",
-    "@tanem/react-nprogress": "^4.0.10",
-    "ace-builds": "^1.4.14",
-    "axios": "^0.26.1",
-    "bcrypt": "^5.0.1",
-    "bowser": "^2.11.0",
-    "connect-typeorm": "^1.1.4",
-    "cookie-parser": "^1.4.6",
-    "copy-to-clipboard": "^3.3.1",
-    "country-flag-icons": "^1.4.21",
-    "csurf": "^1.11.0",
-    "email-templates": "^8.0.10",
-    "express": "^4.17.3",
-    "express-openapi-validator": "^4.13.6",
-    "express-rate-limit": "^6.3.0",
-    "express-session": "^1.17.2",
-    "formik": "^2.2.9",
-    "gravatar-url": "^3.1.0",
-    "intl": "^1.2.5",
-    "lodash": "^4.17.21",
-    "next": "12.1.0",
-    "node-cache": "^5.1.2",
-    "node-gyp": "^9.0.0",
-    "node-schedule": "^2.1.0",
-    "nodemailer": "^6.7.2",
-    "openpgp": "^5.2.0",
-    "plex-api": "^5.3.2",
-    "pug": "^3.0.2",
-    "react": "17.0.2",
-    "react-ace": "^9.5.0",
-    "react-animate-height": "^2.0.23",
-    "react-dom": "17.0.2",
-    "react-intersection-observer": "^8.33.1",
-    "react-intl": "5.24.7",
-    "react-markdown": "^8.0.0",
-    "react-select": "^5.2.2",
-    "react-spring": "^9.4.4",
-    "react-toast-notifications": "^2.5.1",
-    "react-transition-group": "^4.4.2",
-    "react-truncate-markup": "^5.1.0",
-    "react-use-clipboard": "1.0.7",
-    "reflect-metadata": "^0.1.13",
-    "secure-random-password": "^0.2.3",
-    "semver": "^7.3.5",
-    "sqlite3": "^5.0.2",
-    "swagger-ui-express": "^4.3.0",
-    "swr": "^1.2.2",
-    "typeorm": "0.2.45",
-    "web-push": "^3.4.5",
-    "winston": "^3.6.0",
-    "winston-daily-rotate-file": "^4.6.1",
-    "xml2js": "^0.4.23",
-    "yamljs": "^0.3.0",
-    "yup": "^0.32.11"
+    "@formatjs/intl-displaynames": "6.0.3",
+    "@formatjs/intl-locale": "3.0.3",
+    "@formatjs/intl-pluralrules": "5.0.3",
+    "@formatjs/intl-utils": "3.8.4",
+    "@headlessui/react": "0.0.0-insiders.b301f04",
+    "@heroicons/react": "1.0.6",
+    "@supercharge/request-ip": "1.2.0",
+    "@svgr/webpack": "6.3.1",
+    "@tanem/react-nprogress": "5.0.11",
+    "ace-builds": "1.9.6",
+    "axios": "0.27.2",
+    "axios-rate-limit": "1.3.0",
+    "bcrypt": "5.0.1",
+    "bowser": "2.11.0",
+    "connect-typeorm": "1.1.4",
+    "cookie-parser": "1.4.6",
+    "copy-to-clipboard": "3.3.2",
+    "country-flag-icons": "1.5.5",
+    "cronstrue": "2.11.0",
+    "csurf": "1.11.0",
+    "date-fns": "2.29.1",
+    "email-templates": "9.0.0",
+    "express": "4.18.1",
+    "express-openapi-validator": "4.13.8",
+    "express-rate-limit": "6.5.1",
+    "express-session": "1.17.3",
+    "formik": "2.2.9",
+    "gravatar-url": "3.1.0",
+    "intl": "1.2.5",
+    "lodash": "4.17.21",
+    "next": "12.2.5",
+    "node-cache": "5.1.2",
+    "node-gyp": "9.1.0",
+    "node-schedule": "2.1.0",
+    "nodemailer": "6.7.8",
+    "openpgp": "5.4.0",
+    "plex-api": "5.3.2",
+    "pug": "3.0.2",
+    "pulltorefreshjs": "0.1.22",
+    "react": "18.2.0",
+    "react-ace": "10.1.0",
+    "react-animate-height": "2.1.2",
+    "react-dom": "18.2.0",
+    "react-intersection-observer": "9.4.0",
+    "react-intl": "6.0.5",
+    "react-markdown": "8.0.3",
+    "react-popper-tooltip": "4.4.2",
+    "react-select": "5.4.0",
+    "react-spring": "9.5.2",
+    "react-toast-notifications": "2.5.1",
+    "react-truncate-markup": "5.1.2",
+    "react-use-clipboard": "1.0.8",
+    "reflect-metadata": "0.1.13",
+    "secure-random-password": "0.2.3",
+    "semver": "7.3.7",
+    "sqlite3": "5.0.11",
+    "swagger-ui-express": "4.5.0",
+    "swr": "1.3.0",
+    "typeorm": "0.3.7",
+    "web-push": "3.5.0",
+    "winston": "3.8.1",
+    "winston-daily-rotate-file": "4.7.1",
+    "xml2js": "0.4.23",
+    "yamljs": "0.3.0",
+    "yup": "0.32.11"
   },
   "devDependencies": {
-    "@babel/cli": "^7.17.6",
-    "@commitlint/cli": "^16.2.1",
-    "@commitlint/config-conventional": "^16.2.1",
-    "@semantic-release/changelog": "^6.0.1",
-    "@semantic-release/commit-analyzer": "^9.0.2",
-    "@semantic-release/exec": "^6.0.3",
-    "@semantic-release/git": "^10.0.1",
-    "@tailwindcss/aspect-ratio": "^0.4.0",
-    "@tailwindcss/forms": "^0.5.0",
-    "@tailwindcss/typography": "^0.5.2",
-    "@types/bcrypt": "^5.0.0",
-    "@types/cookie-parser": "^1.4.2",
-    "@types/country-flag-icons": "^1.2.0",
-    "@types/csurf": "^1.11.2",
-    "@types/email-templates": "^8.0.4",
-    "@types/express": "^4.17.13",
-    "@types/express-session": "^1.17.4",
-    "@types/lodash": "^4.14.179",
-    "@types/node": "^17.0.21",
-    "@types/node-schedule": "^1.3.2",
-    "@types/nodemailer": "^6.4.4",
-    "@types/react": "^17.0.40",
-    "@types/react-dom": "^17.0.13",
-    "@types/react-transition-group": "^4.4.4",
-    "@types/secure-random-password": "^0.2.1",
-    "@types/semver": "^7.3.9",
-    "@types/swagger-ui-express": "^4.1.3",
-    "@types/web-push": "^3.3.2",
-    "@types/xml2js": "^0.4.9",
-    "@types/yamljs": "^0.2.31",
-    "@types/yup": "^0.29.13",
-    "@typescript-eslint/eslint-plugin": "^5.14.0",
-    "@typescript-eslint/parser": "^5.14.0",
-    "autoprefixer": "^10.4.2",
-    "babel-plugin-react-intl": "^8.2.25",
-    "babel-plugin-react-intl-auto": "^3.3.0",
-    "commitizen": "^4.2.4",
-    "copyfiles": "^2.4.1",
-    "cz-conventional-changelog": "^3.3.0",
-    "eslint": "^8.11.0",
-    "eslint-config-next": "^12.1.0",
-    "eslint-config-prettier": "^8.5.0",
-    "eslint-plugin-formatjs": "^3.0.0",
-    "eslint-plugin-jsx-a11y": "^6.5.1",
-    "eslint-plugin-prettier": "^4.0.0",
-    "eslint-plugin-react": "^7.29.3",
-    "eslint-plugin-react-hooks": "^4.3.0",
-    "extract-react-intl-messages": "^4.1.1",
-    "husky": "^7.0.4",
-    "lint-staged": "^12.3.5",
-    "nodemon": "^2.0.15",
-    "postcss": "^8.4.8",
-    "prettier": "^2.5.1",
-    "prettier-plugin-tailwindcss": "^0.1.8",
-    "semantic-release": "^19.0.2",
-    "semantic-release-docker-buildx": "^1.0.1",
-    "tailwindcss": "^3.0.23",
-    "ts-node": "^10.7.0",
-    "typescript": "^4.6.2"
+    "@babel/cli": "7.18.10",
+    "@commitlint/cli": "17.0.3",
+    "@commitlint/config-conventional": "17.0.3",
+    "@semantic-release/changelog": "6.0.1",
+    "@semantic-release/commit-analyzer": "9.0.2",
+    "@semantic-release/exec": "6.0.3",
+    "@semantic-release/git": "10.0.1",
+    "@tailwindcss/aspect-ratio": "0.4.0",
+    "@tailwindcss/forms": "0.5.2",
+    "@tailwindcss/typography": "0.5.4",
+    "@types/bcrypt": "5.0.0",
+    "@types/cookie-parser": "1.4.3",
+    "@types/country-flag-icons": "1.2.0",
+    "@types/csurf": "1.11.2",
+    "@types/email-templates": "8.0.4",
+    "@types/express": "4.17.13",
+    "@types/express-session": "1.17.4",
+    "@types/lodash": "4.14.183",
+    "@types/node": "17.0.36",
+    "@types/node-schedule": "2.1.0",
+    "@types/nodemailer": "6.4.5",
+    "@types/pulltorefreshjs": "0.1.5",
+    "@types/react": "18.0.17",
+    "@types/react-dom": "18.0.6",
+    "@types/react-transition-group": "4.4.5",
+    "@types/secure-random-password": "0.2.1",
+    "@types/semver": "7.3.12",
+    "@types/swagger-ui-express": "4.1.3",
+    "@types/web-push": "3.3.2",
+    "@types/xml2js": "0.4.11",
+    "@types/yamljs": "0.2.31",
+    "@types/yup": "0.29.14",
+    "@typescript-eslint/eslint-plugin": "5.33.1",
+    "@typescript-eslint/parser": "5.33.1",
+    "autoprefixer": "10.4.8",
+    "babel-plugin-react-intl": "8.2.25",
+    "babel-plugin-react-intl-auto": "3.3.0",
+    "commitizen": "4.2.5",
+    "copyfiles": "2.4.1",
+    "cy-mobile-commands": "0.3.0",
+    "cypress": "10.6.0",
+    "cz-conventional-changelog": "3.3.0",
+    "eslint": "8.22.0",
+    "eslint-config-next": "12.2.5",
+    "eslint-config-prettier": "8.5.0",
+    "eslint-plugin-formatjs": "4.1.0",
+    "eslint-plugin-jsx-a11y": "6.6.1",
+    "eslint-plugin-no-relative-import-paths": "1.4.0",
+    "eslint-plugin-prettier": "4.2.1",
+    "eslint-plugin-react": "7.30.1",
+    "eslint-plugin-react-hooks": "4.6.0",
+    "extract-react-intl-messages": "4.1.1",
+    "husky": "8.0.1",
+    "lint-staged": "12.4.3",
+    "nodemon": "2.0.19",
+    "postcss": "8.4.16",
+    "prettier": "2.7.1",
+    "prettier-plugin-organize-imports": "3.1.0",
+    "prettier-plugin-tailwindcss": "0.1.13",
+    "semantic-release": "19.0.3",
+    "semantic-release-docker-buildx": "1.0.1",
+    "tailwindcss": "3.1.8",
+    "ts-node": "10.9.1",
+    "tsc-alias": "1.7.0",
+    "tsconfig-paths": "4.1.0",
+    "typescript": "4.7.4"
   },
   "resolutions": {
-    "sqlite3/node-gyp": "^8.4.1"
+    "sqlite3/node-gyp": "8.4.1",
+    "@types/react": "18.0.17",
+    "@types/react-dom": "18.0.6"
   },
   "config": {
     "commitizen": {
@@ -163,10 +187,6 @@
       "@commitlint/config-conventional"
     ]
   },
-  "prettier": {
-    "singleQuote": true,
-    "trailingComma": "es5"
-  },
   "release": {
     "plugins": [
       "@semantic-release/commit-analyzer",
diff --git a/renovate.json b/renovate.json
new file mode 100644
index 00000000..bc68da3a
--- /dev/null
+++ b/renovate.json
@@ -0,0 +1,21 @@
+{
+  "$schema": "https://docs.renovatebot.com/renovate-schema.json",
+  "extends": [
+    "config:js-app",
+    "group:allNonMajor",
+    "docker:disableMajor",
+    "helpers:disableTypesNodeMajor"
+  ],
+  "packageRules": [
+    {
+      "matchManagers": ["github-actions"],
+      "groupName": "GitHub Actions",
+      "groupSlug": "github-actions"
+    },
+    {
+      "matchPackageNames": ["node"],
+      "groupName": "Node.js",
+      "groupSlug": "node"
+    }
+  ]
+}
diff --git a/server/api/animelist.ts b/server/api/animelist.ts
index 20eb2f60..740f6725 100644
--- a/server/api/animelist.ts
+++ b/server/api/animelist.ts
@@ -1,8 +1,8 @@
+import logger from '@server/logger';
 import axios from 'axios';
-import xml2js from 'xml2js';
 import fs, { promises as fsp } from 'fs';
 import path from 'path';
-import logger from '../logger';
+import xml2js from 'xml2js';
 
 const UPDATE_INTERVAL_MSEC = 24 * 3600 * 1000; // how often to download new mapping in milliseconds
 // originally at https://raw.githubusercontent.com/ScudLee/anime-lists/master/anime-list.xml
@@ -14,7 +14,7 @@ const LOCAL_PATH = process.env.CONFIG_DIRECTORY
 
 const mappingRegexp = new RegExp(/;[0-9]+-([0-9]+)/g);
 
-// Anime-List xml files are community maintained mappings that Hama agent uses to map AniDB IDs to TVDB/TMDb IDs
+// Anime-List xml files are community maintained mappings that Hama agent uses to map AniDB IDs to TVDB/TMDB IDs
 // https://github.com/Anime-Lists/anime-lists/
 
 interface AnimeMapping {
diff --git a/server/api/externalapi.ts b/server/api/externalapi.ts
index 2a1d9495..cc1e429f 100644
--- a/server/api/externalapi.ts
+++ b/server/api/externalapi.ts
@@ -1,5 +1,7 @@
-import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
-import NodeCache from 'node-cache';
+import type { AxiosInstance, AxiosRequestConfig } from 'axios';
+import axios from 'axios';
+import rateLimit from 'axios-rate-limit';
+import type NodeCache from 'node-cache';
 
 // 5 minute default TTL (in seconds)
 const DEFAULT_TTL = 300;
@@ -10,6 +12,10 @@ const DEFAULT_ROLLING_BUFFER = 10000;
 interface ExternalAPIOptions {
   nodeCache?: NodeCache;
   headers?: Record<string, unknown>;
+  rateLimit?: {
+    maxRPS: number;
+    maxRequests: number;
+  };
 }
 
 class ExternalAPI {
@@ -31,6 +37,14 @@ class ExternalAPI {
         ...options.headers,
       },
     });
+
+    if (options.rateLimit) {
+      this.axios = rateLimit(this.axios, {
+        maxRequests: options.rateLimit.maxRequests,
+        maxRPS: options.rateLimit.maxRPS,
+      });
+    }
+
     this.baseUrl = baseUrl;
     this.cache = options.nodeCache;
   }
diff --git a/server/api/github.ts b/server/api/github.ts
index 48b8854b..b453056e 100644
--- a/server/api/github.ts
+++ b/server/api/github.ts
@@ -1,5 +1,5 @@
-import cacheManager from '../lib/cache';
-import logger from '../logger';
+import cacheManager from '@server/lib/cache';
+import logger from '@server/logger';
 import ExternalAPI from './externalapi';
 
 interface GitHubRelease {
diff --git a/server/api/plexapi.ts b/server/api/plexapi.ts
index 73278387..03246c81 100644
--- a/server/api/plexapi.ts
+++ b/server/api/plexapi.ts
@@ -1,6 +1,7 @@
+import type { Library, PlexSettings } from '@server/lib/settings';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
 import NodePlexAPI from 'plex-api';
-import { getSettings, Library, PlexSettings } from '../lib/settings';
-import logger from '../logger';
 
 export interface PlexLibraryItem {
   ratingKey: string;
@@ -130,7 +131,6 @@ class PlexAPI {
     });
   }
 
-  // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
   public async getStatus() {
     return await this.plexClient.query('/');
   }
@@ -232,6 +232,10 @@ class PlexAPI {
       uri: `/library/sections/${id}/all?sort=addedAt%3Adesc&addedAt>>=${Math.floor(
         options.addedAt / 1000
       )}`,
+      extraHeaders: {
+        'X-Plex-Container-Start': `0`,
+        'X-Plex-Container-Size': `500`,
+      },
     });
 
     return response.MediaContainer.Metadata;
diff --git a/server/api/plextv.ts b/server/api/plextv.ts
index 1733a85a..76ee6618 100644
--- a/server/api/plextv.ts
+++ b/server/api/plextv.ts
@@ -1,8 +1,9 @@
-import axios, { AxiosInstance } from 'axios';
+import type { PlexDevice } from '@server/interfaces/api/plexInterfaces';
+import cacheManager from '@server/lib/cache';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
 import xml2js from 'xml2js';
-import { PlexDevice } from '../interfaces/api/plexInterfaces';
-import { getSettings } from '../lib/settings';
-import logger from '../logger';
+import ExternalAPI from './externalapi';
 
 interface PlexAccountResponse {
   user: PlexUser;
@@ -111,20 +112,54 @@ interface UsersResponse {
   };
 }
 
-class PlexTvAPI {
+interface WatchlistResponse {
+  MediaContainer: {
+    totalSize: number;
+    Metadata?: {
+      ratingKey: string;
+    }[];
+  };
+}
+
+interface MetadataResponse {
+  MediaContainer: {
+    Metadata: {
+      ratingKey: string;
+      type: 'movie' | 'show';
+      title: string;
+      Guid: {
+        id: `imdb://tt${number}` | `tmdb://${number}` | `tvdb://${number}`;
+      }[];
+    }[];
+  };
+}
+
+export interface PlexWatchlistItem {
+  ratingKey: string;
+  tmdbId: number;
+  tvdbId?: number;
+  type: 'movie' | 'show';
+  title: string;
+}
+
+class PlexTvAPI extends ExternalAPI {
   private authToken: string;
-  private axios: AxiosInstance;
 
   constructor(authToken: string) {
+    super(
+      'https://plex.tv',
+      {},
+      {
+        headers: {
+          'X-Plex-Token': authToken,
+          'Content-Type': 'application/json',
+          Accept: 'application/json',
+        },
+        nodeCache: cacheManager.getCache('plextv').data,
+      }
+    );
+
     this.authToken = authToken;
-    this.axios = axios.create({
-      baseURL: 'https://plex.tv',
-      headers: {
-        'X-Plex-Token': this.authToken,
-        'Content-Type': 'application/json',
-        Accept: 'application/json',
-      },
-    });
   }
 
   public async getDevices(): Promise<PlexDevice[]> {
@@ -252,6 +287,83 @@ class PlexTvAPI {
     )) as UsersResponse;
     return parsedXml;
   }
+
+  public async getWatchlist({
+    offset = 0,
+    size = 20,
+  }: { offset?: number; size?: number } = {}): Promise<{
+    offset: number;
+    size: number;
+    totalSize: number;
+    items: PlexWatchlistItem[];
+  }> {
+    try {
+      const response = await this.axios.get<WatchlistResponse>(
+        '/library/sections/watchlist/all',
+        {
+          params: {
+            'X-Plex-Container-Start': offset,
+            'X-Plex-Container-Size': size,
+          },
+          baseURL: 'https://metadata.provider.plex.tv',
+        }
+      );
+
+      const watchlistDetails = await Promise.all(
+        (response.data.MediaContainer.Metadata ?? []).map(
+          async (watchlistItem) => {
+            const detailedResponse = await this.getRolling<MetadataResponse>(
+              `/library/metadata/${watchlistItem.ratingKey}`,
+              {
+                baseURL: 'https://metadata.provider.plex.tv',
+              }
+            );
+
+            const metadata = detailedResponse.MediaContainer.Metadata[0];
+
+            const tmdbString = metadata.Guid.find((guid) =>
+              guid.id.startsWith('tmdb')
+            );
+            const tvdbString = metadata.Guid.find((guid) =>
+              guid.id.startsWith('tvdb')
+            );
+
+            return {
+              ratingKey: metadata.ratingKey,
+              // This should always be set? But I guess it also cannot be?
+              // We will filter out the 0's afterwards
+              tmdbId: tmdbString ? Number(tmdbString.id.split('//')[1]) : 0,
+              tvdbId: tvdbString
+                ? Number(tvdbString.id.split('//')[1])
+                : undefined,
+              title: metadata.title,
+              type: metadata.type,
+            };
+          }
+        )
+      );
+
+      const filteredList = watchlistDetails.filter((detail) => detail.tmdbId);
+
+      return {
+        offset,
+        size,
+        totalSize: response.data.MediaContainer.totalSize,
+        items: filteredList,
+      };
+    } catch (e) {
+      logger.error('Failed to retrieve watchlist items', {
+        label: 'Plex.TV Metadata API',
+        errorMessage: e.message,
+      });
+      return {
+        offset,
+        size,
+        totalSize: 0,
+        items: [],
+      };
+    }
+  }
 }
 
 export default PlexTvAPI;
diff --git a/server/api/rottentomatoes.ts b/server/api/rottentomatoes.ts
index b9b00e10..e190b7b9 100644
--- a/server/api/rottentomatoes.ts
+++ b/server/api/rottentomatoes.ts
@@ -1,4 +1,4 @@
-import cacheManager from '../lib/cache';
+import cacheManager from '@server/lib/cache';
 import ExternalAPI from './externalapi';
 
 interface RTSearchResult {
diff --git a/server/api/servarr/base.ts b/server/api/servarr/base.ts
index 9e455933..2b8ec4cb 100644
--- a/server/api/servarr/base.ts
+++ b/server/api/servarr/base.ts
@@ -1,6 +1,7 @@
-import cacheManager, { AvailableCacheIds } from '../../lib/cache';
-import { DVRSettings } from '../../lib/settings';
-import ExternalAPI from '../externalapi';
+import ExternalAPI from '@server/api/externalapi';
+import type { AvailableCacheIds } from '@server/lib/cache';
+import cacheManager from '@server/lib/cache';
+import type { DVRSettings } from '@server/lib/settings';
 
 export interface SystemStatus {
   version: string;
diff --git a/server/api/servarr/radarr.ts b/server/api/servarr/radarr.ts
index 7305baf0..1637a8d8 100644
--- a/server/api/servarr/radarr.ts
+++ b/server/api/servarr/radarr.ts
@@ -1,4 +1,4 @@
-import logger from '../../logger';
+import logger from '@server/logger';
 import ServarrBase from './base';
 
 export interface RadarrMovieOptions {
@@ -69,7 +69,7 @@ class RadarrAPI extends ServarrBase<{ movieId: number }> {
 
       return response.data[0];
     } catch (e) {
-      logger.error('Error retrieving movie by TMDb ID', {
+      logger.error('Error retrieving movie by TMDB ID', {
         label: 'Radarr API',
         errorMessage: e.message,
         tmdbId: id,
diff --git a/server/api/servarr/sonarr.ts b/server/api/servarr/sonarr.ts
index 7440d278..a5b9c1e8 100644
--- a/server/api/servarr/sonarr.ts
+++ b/server/api/servarr/sonarr.ts
@@ -1,4 +1,4 @@
-import logger from '../../logger';
+import logger from '@server/logger';
 import ServarrBase from './base';
 
 interface SonarrSeason {
diff --git a/server/api/tautulli.ts b/server/api/tautulli.ts
index bb7f3723..0e5e0707 100644
--- a/server/api/tautulli.ts
+++ b/server/api/tautulli.ts
@@ -1,8 +1,9 @@
-import axios, { AxiosInstance } from 'axios';
+import type { User } from '@server/entity/User';
+import type { TautulliSettings } from '@server/lib/settings';
+import logger from '@server/logger';
+import type { AxiosInstance } from 'axios';
+import axios from 'axios';
 import { uniqWith } from 'lodash';
-import { User } from '../entity/User';
-import { TautulliSettings } from '../lib/settings';
-import logger from '../logger';
 
 export interface TautulliHistoryRecord {
   date: number;
diff --git a/server/api/themoviedb/index.ts b/server/api/themoviedb/index.ts
index cf5e280c..ea05b8ab 100644
--- a/server/api/themoviedb/index.ts
+++ b/server/api/themoviedb/index.ts
@@ -1,7 +1,7 @@
+import ExternalAPI from '@server/api/externalapi';
+import cacheManager from '@server/lib/cache';
 import { sortBy } from 'lodash';
-import cacheManager from '../../lib/cache';
-import ExternalAPI from '../externalapi';
-import {
+import type {
   TmdbCollection,
   TmdbExternalIdResponse,
   TmdbGenre,
@@ -92,6 +92,10 @@ class TheMovieDb extends ExternalAPI {
       },
       {
         nodeCache: cacheManager.getCache('tmdb').data,
+        rateLimit: {
+          maxRequests: 20,
+          maxRPS: 50,
+        },
       }
     );
     this.region = region;
@@ -129,7 +133,13 @@ class TheMovieDb extends ExternalAPI {
   }: SingleSearchOptions): Promise<TmdbSearchMovieResponse> => {
     try {
       const data = await this.get<TmdbSearchMovieResponse>('/search/movie', {
-        params: { query, page, include_adult: includeAdult, language, year },
+        params: {
+          query,
+          page,
+          include_adult: includeAdult,
+          language,
+          primary_release_year: year,
+        },
       });
 
       return data;
@@ -186,7 +196,7 @@ class TheMovieDb extends ExternalAPI {
 
       return data;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch person details: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch person details: ${e.message}`);
     }
   };
 
@@ -208,7 +218,7 @@ class TheMovieDb extends ExternalAPI {
       return data;
     } catch (e) {
       throw new Error(
-        `[TMDb] Failed to fetch person combined credits: ${e.message}`
+        `[TMDB] Failed to fetch person combined credits: ${e.message}`
       );
     }
   };
@@ -235,7 +245,7 @@ class TheMovieDb extends ExternalAPI {
 
       return data;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch movie details: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch movie details: ${e.message}`);
     }
   };
 
@@ -261,7 +271,7 @@ class TheMovieDb extends ExternalAPI {
 
       return data;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch TV show details: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch TV show details: ${e.message}`);
     }
   };
 
@@ -287,7 +297,7 @@ class TheMovieDb extends ExternalAPI {
 
       return data;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch TV show details: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch TV show details: ${e.message}`);
     }
   };
 
@@ -313,7 +323,7 @@ class TheMovieDb extends ExternalAPI {
 
       return data;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch discover movies: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch discover movies: ${e.message}`);
     }
   }
 
@@ -339,7 +349,7 @@ class TheMovieDb extends ExternalAPI {
 
       return data;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch discover movies: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch discover movies: ${e.message}`);
     }
   }
 
@@ -365,7 +375,7 @@ class TheMovieDb extends ExternalAPI {
 
       return data;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch movies by keyword: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch movies by keyword: ${e.message}`);
     }
   }
 
@@ -392,7 +402,7 @@ class TheMovieDb extends ExternalAPI {
       return data;
     } catch (e) {
       throw new Error(
-        `[TMDb] Failed to fetch TV recommendations: ${e.message}`
+        `[TMDB] Failed to fetch TV recommendations: ${e.message}`
       );
     }
   }
@@ -416,7 +426,7 @@ class TheMovieDb extends ExternalAPI {
 
       return data;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch TV similar: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch TV similar: ${e.message}`);
     }
   }
 
@@ -449,7 +459,7 @@ class TheMovieDb extends ExternalAPI {
 
       return data;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch discover movies: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch discover movies: ${e.message}`);
     }
   };
 
@@ -482,7 +492,7 @@ class TheMovieDb extends ExternalAPI {
 
       return data;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch discover TV: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch discover TV: ${e.message}`);
     }
   };
 
@@ -508,7 +518,7 @@ class TheMovieDb extends ExternalAPI {
 
       return data;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch upcoming movies: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch upcoming movies: ${e.message}`);
     }
   };
 
@@ -535,7 +545,7 @@ class TheMovieDb extends ExternalAPI {
 
       return data;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch all trending: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch all trending: ${e.message}`);
     }
   };
 
@@ -558,7 +568,7 @@ class TheMovieDb extends ExternalAPI {
 
       return data;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch all trending: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch all trending: ${e.message}`);
     }
   };
 
@@ -581,7 +591,7 @@ class TheMovieDb extends ExternalAPI {
 
       return data;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch all trending: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch all trending: ${e.message}`);
     }
   };
 
@@ -613,7 +623,7 @@ class TheMovieDb extends ExternalAPI {
 
       return data;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to find by external ID: ${e.message}`);
+      throw new Error(`[TMDB] Failed to find by external ID: ${e.message}`);
     }
   }
 
@@ -651,7 +661,7 @@ class TheMovieDb extends ExternalAPI {
       throw new Error(`No movie or show returned from API for ID ${imdbId}`);
     } catch (e) {
       throw new Error(
-        `[TMDb] Failed to find media using external IMDb ID: ${e.message}`
+        `[TMDB] Failed to find media using external IMDb ID: ${e.message}`
       );
     }
   }
@@ -681,7 +691,7 @@ class TheMovieDb extends ExternalAPI {
       throw new Error(`No show returned from API for ID ${tvdbId}`);
     } catch (e) {
       throw new Error(
-        `[TMDb] Failed to get TV show using the external TVDB ID: ${e.message}`
+        `[TMDB] Failed to get TV show using the external TVDB ID: ${e.message}`
       );
     }
   }
@@ -705,7 +715,7 @@ class TheMovieDb extends ExternalAPI {
 
       return data;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch collection: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch collection: ${e.message}`);
     }
   }
 
@@ -721,7 +731,7 @@ class TheMovieDb extends ExternalAPI {
 
       return regions;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch countries: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch countries: ${e.message}`);
     }
   }
 
@@ -737,7 +747,7 @@ class TheMovieDb extends ExternalAPI {
 
       return languages;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch langauges: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch langauges: ${e.message}`);
     }
   }
 
@@ -749,7 +759,7 @@ class TheMovieDb extends ExternalAPI {
 
       return data;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch movie studio: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch movie studio: ${e.message}`);
     }
   }
 
@@ -759,7 +769,7 @@ class TheMovieDb extends ExternalAPI {
 
       return data;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch TV network: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch TV network: ${e.message}`);
     }
   }
 
@@ -810,7 +820,7 @@ class TheMovieDb extends ExternalAPI {
 
       return movieGenres;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch movie genres: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch movie genres: ${e.message}`);
     }
   }
 
@@ -861,7 +871,7 @@ class TheMovieDb extends ExternalAPI {
 
       return tvGenres;
     } catch (e) {
-      throw new Error(`[TMDb] Failed to fetch TV genres: ${e.message}`);
+      throw new Error(`[TMDB] Failed to fetch TV genres: ${e.message}`);
     }
   }
 }
diff --git a/server/constants/media.ts b/server/constants/media.ts
index d9ef9e02..de2bf834 100644
--- a/server/constants/media.ts
+++ b/server/constants/media.ts
@@ -2,6 +2,7 @@ export enum MediaRequestStatus {
   PENDING = 1,
   APPROVED,
   DECLINED,
+  FAILED,
 }
 
 export enum MediaType {
diff --git a/ormconfig.js b/server/datasource.ts
similarity index 64%
rename from ormconfig.js
rename to server/datasource.ts
index 4122f079..a6839298 100644
--- a/ormconfig.js
+++ b/server/datasource.ts
@@ -1,4 +1,8 @@
-const devConfig = {
+import 'reflect-metadata';
+import type { DataSourceOptions, EntityTarget, Repository } from 'typeorm';
+import { DataSource } from 'typeorm';
+
+const devConfig: DataSourceOptions = {
   type: 'sqlite',
   database: process.env.CONFIG_DIRECTORY
     ? `${process.env.CONFIG_DIRECTORY}/db/db.sqlite3`
@@ -10,31 +14,30 @@ const devConfig = {
   entities: ['server/entity/**/*.ts'],
   migrations: ['server/migration/**/*.ts'],
   subscribers: ['server/subscriber/**/*.ts'],
-  cli: {
-    entitiesDir: 'server/entity',
-    migrationsDir: 'server/migration',
-  },
 };
 
-const prodConfig = {
+const prodConfig: DataSourceOptions = {
   type: 'sqlite',
   database: process.env.CONFIG_DIRECTORY
     ? `${process.env.CONFIG_DIRECTORY}/db/db.sqlite3`
     : 'config/db/db.sqlite3',
   synchronize: false,
+  migrationsRun: false,
   logging: false,
   enableWAL: true,
   entities: ['dist/entity/**/*.js'],
   migrations: ['dist/migration/**/*.js'],
-  migrationsRun: false,
   subscribers: ['dist/subscriber/**/*.js'],
-  cli: {
-    entitiesDir: 'dist/entity',
-    migrationsDir: 'dist/migration',
-  },
 };
 
-const finalConfig =
-  process.env.NODE_ENV !== 'production' ? devConfig : prodConfig;
+const dataSource = new DataSource(
+  process.env.NODE_ENV !== 'production' ? devConfig : prodConfig
+);
+
+export const getRepository = <Entity>(
+  target: EntityTarget<Entity>
+): Repository<Entity> => {
+  return dataSource.getRepository(target);
+};
 
-module.exports = finalConfig;
+export default dataSource;
diff --git a/server/entity/Issue.ts b/server/entity/Issue.ts
index d8e05c56..fae96967 100644
--- a/server/entity/Issue.ts
+++ b/server/entity/Issue.ts
@@ -1,3 +1,5 @@
+import type { IssueType } from '@server/constants/issue';
+import { IssueStatus } from '@server/constants/issue';
 import {
   Column,
   CreateDateColumn,
@@ -7,7 +9,6 @@ import {
   PrimaryGeneratedColumn,
   UpdateDateColumn,
 } from 'typeorm';
-import { IssueStatus, IssueType } from '../constants/issue';
 import IssueComment from './IssueComment';
 import Media from './Media';
 import { User } from './User';
diff --git a/server/entity/Media.ts b/server/entity/Media.ts
index 9d106d4f..6a681c47 100644
--- a/server/entity/Media.ts
+++ b/server/entity/Media.ts
@@ -1,21 +1,22 @@
+import RadarrAPI from '@server/api/servarr/radarr';
+import SonarrAPI from '@server/api/servarr/sonarr';
+import { MediaStatus, MediaType } from '@server/constants/media';
+import { getRepository } from '@server/datasource';
+import type { DownloadingItem } from '@server/lib/downloadtracker';
+import downloadTracker from '@server/lib/downloadtracker';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
 import {
   AfterLoad,
   Column,
   CreateDateColumn,
   Entity,
-  getRepository,
   In,
   Index,
   OneToMany,
   PrimaryGeneratedColumn,
   UpdateDateColumn,
 } from 'typeorm';
-import RadarrAPI from '../api/servarr/radarr';
-import SonarrAPI from '../api/servarr/sonarr';
-import { MediaStatus, MediaType } from '../constants/media';
-import downloadTracker, { DownloadingItem } from '../lib/downloadtracker';
-import { getSettings } from '../lib/settings';
-import logger from '../logger';
 import Issue from './Issue';
 import { MediaRequest } from './MediaRequest';
 import Season from './Season';
@@ -36,7 +37,7 @@ class Media {
       }
 
       const media = await mediaRepository.find({
-        tmdbId: In(finalIds),
+        where: { tmdbId: In(finalIds) },
       });
 
       return media;
@@ -55,10 +56,10 @@ class Media {
     try {
       const media = await mediaRepository.findOne({
         where: { tmdbId: id, mediaType },
-        relations: ['requests', 'issues'],
+        relations: { requests: true, issues: true },
       });
 
-      return media;
+      return media ?? undefined;
     } catch (e) {
       logger.error(e.message);
       return undefined;
@@ -145,6 +146,9 @@ class Media {
   public plexUrl?: string;
   public plexUrl4k?: string;
 
+  public iOSPlexUrl?: string;
+  public iOSPlexUrl4k?: string;
+
   public tautulliUrl?: string;
   public tautulliUrl4k?: string;
 
@@ -164,6 +168,8 @@ class Media {
         this.ratingKey
       }`;
 
+      this.iOSPlexUrl = `plex://preplay/?metadataKey=%2Flibrary%2Fmetadata%2F${this.ratingKey}&server=${machineId}`;
+
       if (tautulliUrl) {
         this.tautulliUrl = `${tautulliUrl}/info?rating_key=${this.ratingKey}`;
       }
@@ -176,6 +182,8 @@ class Media {
         this.ratingKey4k
       }`;
 
+      this.iOSPlexUrl4k = `plex://preplay/?metadataKey=%2Flibrary%2Fmetadata%2F${this.ratingKey4k}&server=${machineId}`;
+
       if (tautulliUrl) {
         this.tautulliUrl4k = `${tautulliUrl}/info?rating_key=${this.ratingKey4k}`;
       }
diff --git a/server/entity/MediaRequest.ts b/server/entity/MediaRequest.ts
index f7f82115..eefbc11f 100644
--- a/server/entity/MediaRequest.ts
+++ b/server/entity/MediaRequest.ts
@@ -1,3 +1,23 @@
+import type { RadarrMovieOptions } from '@server/api/servarr/radarr';
+import RadarrAPI from '@server/api/servarr/radarr';
+import type {
+  AddSeriesOptions,
+  SonarrSeries,
+} from '@server/api/servarr/sonarr';
+import SonarrAPI from '@server/api/servarr/sonarr';
+import TheMovieDb from '@server/api/themoviedb';
+import { ANIME_KEYWORD_ID } from '@server/api/themoviedb/constants';
+import {
+  MediaRequestStatus,
+  MediaStatus,
+  MediaType,
+} from '@server/constants/media';
+import { getRepository } from '@server/datasource';
+import type { MediaRequestBody } from '@server/interfaces/api/requestInterfaces';
+import notificationManager, { Notification } from '@server/lib/notifications';
+import { Permission } from '@server/lib/permissions';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
 import { isEqual, truncate } from 'lodash';
 import {
   AfterInsert,
@@ -6,30 +26,347 @@ import {
   Column,
   CreateDateColumn,
   Entity,
-  getRepository,
   ManyToOne,
   OneToMany,
   PrimaryGeneratedColumn,
   RelationCount,
   UpdateDateColumn,
 } from 'typeorm';
-import RadarrAPI, { RadarrMovieOptions } from '../api/servarr/radarr';
-import SonarrAPI, {
-  AddSeriesOptions,
-  SonarrSeries,
-} from '../api/servarr/sonarr';
-import TheMovieDb from '../api/themoviedb';
-import { ANIME_KEYWORD_ID } from '../api/themoviedb/constants';
-import { MediaRequestStatus, MediaStatus, MediaType } from '../constants/media';
-import notificationManager, { Notification } from '../lib/notifications';
-import { getSettings } from '../lib/settings';
-import logger from '../logger';
 import Media from './Media';
 import SeasonRequest from './SeasonRequest';
 import { User } from './User';
 
+export class RequestPermissionError extends Error {}
+export class QuotaRestrictedError extends Error {}
+export class DuplicateMediaRequestError extends Error {}
+export class NoSeasonsAvailableError extends Error {}
+
+type MediaRequestOptions = {
+  isAutoRequest?: boolean;
+};
+
 @Entity()
 export class MediaRequest {
+  public static async request(
+    requestBody: MediaRequestBody,
+    user: User,
+    options: MediaRequestOptions = {}
+  ): Promise<MediaRequest> {
+    const tmdb = new TheMovieDb();
+    const mediaRepository = getRepository(Media);
+    const requestRepository = getRepository(MediaRequest);
+    const userRepository = getRepository(User);
+
+    let requestUser = user;
+
+    if (
+      requestBody.userId &&
+      !requestUser.hasPermission([
+        Permission.MANAGE_USERS,
+        Permission.MANAGE_REQUESTS,
+      ])
+    ) {
+      throw new RequestPermissionError(
+        'You do not have permission to modify the request user.'
+      );
+    } else if (requestBody.userId) {
+      requestUser = await userRepository.findOneOrFail({
+        where: { id: requestBody.userId },
+      });
+    }
+
+    if (!requestUser) {
+      throw new Error('User missing from request context.');
+    }
+
+    if (
+      requestBody.mediaType === MediaType.MOVIE &&
+      !requestUser.hasPermission(
+        requestBody.is4k
+          ? [Permission.REQUEST_4K, Permission.REQUEST_4K_MOVIE]
+          : [Permission.REQUEST, Permission.REQUEST_MOVIE],
+        {
+          type: 'or',
+        }
+      )
+    ) {
+      throw new RequestPermissionError(
+        `You do not have permission to make ${
+          requestBody.is4k ? '4K ' : ''
+        }movie requests.`
+      );
+    } else if (
+      requestBody.mediaType === MediaType.TV &&
+      !requestUser.hasPermission(
+        requestBody.is4k
+          ? [Permission.REQUEST_4K, Permission.REQUEST_4K_TV]
+          : [Permission.REQUEST, Permission.REQUEST_TV],
+        {
+          type: 'or',
+        }
+      )
+    ) {
+      throw new RequestPermissionError(
+        `You do not have permission to make ${
+          requestBody.is4k ? '4K ' : ''
+        }series requests.`
+      );
+    }
+
+    const quotas = await requestUser.getQuota();
+
+    if (requestBody.mediaType === MediaType.MOVIE && quotas.movie.restricted) {
+      throw new QuotaRestrictedError('Movie Quota exceeded.');
+    } else if (requestBody.mediaType === MediaType.TV && quotas.tv.restricted) {
+      throw new QuotaRestrictedError('Series Quota exceeded.');
+    }
+
+    const tmdbMedia =
+      requestBody.mediaType === MediaType.MOVIE
+        ? await tmdb.getMovie({ movieId: requestBody.mediaId })
+        : await tmdb.getTvShow({ tvId: requestBody.mediaId });
+
+    let media = await mediaRepository.findOne({
+      where: {
+        tmdbId: requestBody.mediaId,
+        mediaType: requestBody.mediaType,
+      },
+      relations: ['requests'],
+    });
+
+    if (!media) {
+      media = new Media({
+        tmdbId: tmdbMedia.id,
+        tvdbId: requestBody.tvdbId ?? tmdbMedia.external_ids.tvdb_id,
+        status: !requestBody.is4k ? MediaStatus.PENDING : MediaStatus.UNKNOWN,
+        status4k: requestBody.is4k ? MediaStatus.PENDING : MediaStatus.UNKNOWN,
+        mediaType: requestBody.mediaType,
+      });
+    } else {
+      if (media.status === MediaStatus.UNKNOWN && !requestBody.is4k) {
+        media.status = MediaStatus.PENDING;
+      }
+
+      if (media.status4k === MediaStatus.UNKNOWN && requestBody.is4k) {
+        media.status4k = MediaStatus.PENDING;
+      }
+    }
+
+    const existing = await requestRepository
+      .createQueryBuilder('request')
+      .leftJoin('request.media', 'media')
+      .leftJoinAndSelect('request.requestedBy', 'user')
+      .where('request.is4k = :is4k', { is4k: requestBody.is4k })
+      .andWhere('media.tmdbId = :tmdbId', { tmdbId: tmdbMedia.id })
+      .andWhere('media.mediaType = :mediaType', {
+        mediaType: requestBody.mediaType,
+      })
+      .getMany();
+
+    if (existing && existing.length > 0) {
+      // If there is an existing movie request that isn't declined, don't allow a new one.
+      if (
+        requestBody.mediaType === MediaType.MOVIE &&
+        existing[0].status !== MediaRequestStatus.DECLINED
+      ) {
+        logger.warn('Duplicate request for media blocked', {
+          tmdbId: tmdbMedia.id,
+          mediaType: requestBody.mediaType,
+          is4k: requestBody.is4k,
+          label: 'Media Request',
+        });
+
+        throw new DuplicateMediaRequestError(
+          'Request for this media already exists.'
+        );
+      }
+
+      // If an existing auto-request for this media exists from the same user,
+      // don't allow a new one.
+      if (
+        existing.find(
+          (r) => r.requestedBy.id === requestUser.id && r.isAutoRequest
+        )
+      ) {
+        throw new DuplicateMediaRequestError(
+          'Auto-request for this media and user already exists.'
+        );
+      }
+    }
+
+    if (requestBody.mediaType === MediaType.MOVIE) {
+      await mediaRepository.save(media);
+
+      const request = new MediaRequest({
+        type: MediaType.MOVIE,
+        media,
+        requestedBy: requestUser,
+        // If the user is an admin or has the "auto approve" permission, automatically approve the request
+        status: user.hasPermission(
+          [
+            requestBody.is4k
+              ? Permission.AUTO_APPROVE_4K
+              : Permission.AUTO_APPROVE,
+            requestBody.is4k
+              ? Permission.AUTO_APPROVE_4K_MOVIE
+              : Permission.AUTO_APPROVE_MOVIE,
+            Permission.MANAGE_REQUESTS,
+          ],
+          { type: 'or' }
+        )
+          ? MediaRequestStatus.APPROVED
+          : MediaRequestStatus.PENDING,
+        modifiedBy: user.hasPermission(
+          [
+            requestBody.is4k
+              ? Permission.AUTO_APPROVE_4K
+              : Permission.AUTO_APPROVE,
+            requestBody.is4k
+              ? Permission.AUTO_APPROVE_4K_MOVIE
+              : Permission.AUTO_APPROVE_MOVIE,
+            Permission.MANAGE_REQUESTS,
+          ],
+          { type: 'or' }
+        )
+          ? user
+          : undefined,
+        is4k: requestBody.is4k,
+        serverId: requestBody.serverId,
+        profileId: requestBody.profileId,
+        rootFolder: requestBody.rootFolder,
+        tags: requestBody.tags,
+        isAutoRequest: options.isAutoRequest ?? false,
+      });
+
+      await requestRepository.save(request);
+      return request;
+    } else {
+      const tmdbMediaShow = tmdbMedia as Awaited<
+        ReturnType<typeof tmdb.getTvShow>
+      >;
+      const requestedSeasons =
+        requestBody.seasons === 'all'
+          ? tmdbMediaShow.seasons
+              .map((season) => season.season_number)
+              .filter((sn) => sn > 0)
+          : (requestBody.seasons as number[]);
+      let existingSeasons: number[] = [];
+
+      // We need to check existing requests on this title to make sure we don't double up on seasons that were
+      // already requested. In the case they were, we just throw out any duplicates but still approve the request.
+      // (Unless there are no seasons, in which case we abort)
+      if (media.requests) {
+        existingSeasons = media.requests
+          .filter(
+            (request) =>
+              request.is4k === requestBody.is4k &&
+              request.status !== MediaRequestStatus.DECLINED
+          )
+          .reduce((seasons, request) => {
+            const combinedSeasons = request.seasons.map(
+              (season) => season.seasonNumber
+            );
+
+            return [...seasons, ...combinedSeasons];
+          }, [] as number[]);
+      }
+
+      // We should also check seasons that are available/partially available but don't have existing requests
+      if (media.seasons) {
+        existingSeasons = [
+          ...existingSeasons,
+          ...media.seasons
+            .filter(
+              (season) =>
+                season[requestBody.is4k ? 'status4k' : 'status'] !==
+                MediaStatus.UNKNOWN
+            )
+            .map((season) => season.seasonNumber),
+        ];
+      }
+
+      const finalSeasons = requestedSeasons.filter(
+        (rs) => !existingSeasons.includes(rs)
+      );
+
+      if (finalSeasons.length === 0) {
+        throw new NoSeasonsAvailableError('No seasons available to request');
+      } else if (
+        quotas.tv.limit &&
+        finalSeasons.length > (quotas.tv.remaining ?? 0)
+      ) {
+        throw new QuotaRestrictedError('Series Quota exceeded.');
+      }
+
+      await mediaRepository.save(media);
+
+      const request = new MediaRequest({
+        type: MediaType.TV,
+        media,
+        requestedBy: requestUser,
+        // If the user is an admin or has the "auto approve" permission, automatically approve the request
+        status: user.hasPermission(
+          [
+            requestBody.is4k
+              ? Permission.AUTO_APPROVE_4K
+              : Permission.AUTO_APPROVE,
+            requestBody.is4k
+              ? Permission.AUTO_APPROVE_4K_TV
+              : Permission.AUTO_APPROVE_TV,
+            Permission.MANAGE_REQUESTS,
+          ],
+          { type: 'or' }
+        )
+          ? MediaRequestStatus.APPROVED
+          : MediaRequestStatus.PENDING,
+        modifiedBy: user.hasPermission(
+          [
+            requestBody.is4k
+              ? Permission.AUTO_APPROVE_4K
+              : Permission.AUTO_APPROVE,
+            requestBody.is4k
+              ? Permission.AUTO_APPROVE_4K_TV
+              : Permission.AUTO_APPROVE_TV,
+            Permission.MANAGE_REQUESTS,
+          ],
+          { type: 'or' }
+        )
+          ? user
+          : undefined,
+        is4k: requestBody.is4k,
+        serverId: requestBody.serverId,
+        profileId: requestBody.profileId,
+        rootFolder: requestBody.rootFolder,
+        languageProfileId: requestBody.languageProfileId,
+        tags: requestBody.tags,
+        seasons: finalSeasons.map(
+          (sn) =>
+            new SeasonRequest({
+              seasonNumber: sn,
+              status: user.hasPermission(
+                [
+                  requestBody.is4k
+                    ? Permission.AUTO_APPROVE_4K
+                    : Permission.AUTO_APPROVE,
+                  requestBody.is4k
+                    ? Permission.AUTO_APPROVE_4K_TV
+                    : Permission.AUTO_APPROVE_TV,
+                  Permission.MANAGE_REQUESTS,
+                ],
+                { type: 'or' }
+              )
+                ? MediaRequestStatus.APPROVED
+                : MediaRequestStatus.PENDING,
+            })
+        ),
+        isAutoRequest: options.isAutoRequest ?? false,
+      });
+
+      await requestRepository.save(request);
+      return request;
+    }
+  }
+
   @PrimaryGeneratedColumn()
   public id: number;
 
@@ -120,6 +457,9 @@ export class MediaRequest {
   })
   public tags?: number[];
 
+  @Column({ default: false })
+  public isAutoRequest: boolean;
+
   constructor(init?: Partial<MediaRequest>) {
     Object.assign(this, init);
   }
@@ -147,6 +487,10 @@ export class MediaRequest {
       }
 
       this.sendNotification(media, Notification.MEDIA_PENDING);
+
+      if (this.isAutoRequest) {
+        this.sendNotification(media, Notification.MEDIA_AUTO_REQUESTED);
+      }
     }
   }
 
@@ -191,6 +535,14 @@ export class MediaRequest {
             : Notification.MEDIA_APPROVED
           : Notification.MEDIA_DECLINED
       );
+
+      if (
+        this.status === MediaRequestStatus.APPROVED &&
+        autoApproved &&
+        this.isAutoRequest
+      ) {
+        this.sendNotification(media, Notification.MEDIA_AUTO_REQUESTED);
+      }
     }
   }
 
@@ -207,7 +559,7 @@ export class MediaRequest {
     const mediaRepository = getRepository(Media);
     const media = await mediaRepository.findOne({
       where: { id: this.media.id },
-      relations: ['requests'],
+      relations: { requests: true },
     });
     if (!media) {
       logger.error('Media data not found', {
@@ -272,7 +624,7 @@ export class MediaRequest {
     const mediaRepository = getRepository(Media);
     const fullMedia = await mediaRepository.findOneOrFail({
       where: { id: this.media.id },
-      relations: ['requests'],
+      relations: { requests: true },
     });
 
     if (
@@ -452,10 +804,13 @@ export class MediaRequest {
             await mediaRepository.save(media);
           })
           .catch(async () => {
-            media[this.is4k ? 'status4k' : 'status'] = MediaStatus.UNKNOWN;
-            await mediaRepository.save(media);
+            const requestRepository = getRepository(MediaRequest);
+
+            this.status = MediaRequestStatus.FAILED;
+            requestRepository.save(this);
+
             logger.warn(
-              'Something went wrong sending movie request to Radarr, marking status as UNKNOWN',
+              'Something went wrong sending movie request to Radarr, marking status as FAILED',
               {
                 label: 'Media Request',
                 requestId: this.id,
@@ -543,7 +898,7 @@ export class MediaRequest {
 
         const media = await mediaRepository.findOne({
           where: { id: this.media.id },
-          relations: ['requests'],
+          relations: { requests: true },
         });
 
         if (!media) {
@@ -670,7 +1025,7 @@ export class MediaRequest {
             // We grab media again here to make sure we have the latest version of it
             const media = await mediaRepository.findOne({
               where: { id: this.media.id },
-              relations: ['requests'],
+              relations: { requests: true },
             });
 
             if (!media) {
@@ -685,10 +1040,13 @@ export class MediaRequest {
             await mediaRepository.save(media);
           })
           .catch(async () => {
-            media[this.is4k ? 'status4k' : 'status'] = MediaStatus.UNKNOWN;
-            await mediaRepository.save(media);
+            const requestRepository = getRepository(MediaRequest);
+
+            this.status = MediaRequestStatus.FAILED;
+            requestRepository.save(this);
+
             logger.warn(
-              'Something went wrong sending series request to Sonarr, marking status as UNKNOWN',
+              'Something went wrong sending series request to Sonarr, marking status as FAILED',
               {
                 label: 'Media Request',
                 requestId: this.id,
@@ -723,6 +1081,7 @@ export class MediaRequest {
       const mediaType = this.type === MediaType.MOVIE ? 'Movie' : 'Series';
       let event: string | undefined;
       let notifyAdmin = true;
+      let notifySystem = true;
 
       switch (type) {
         case Notification.MEDIA_APPROVED:
@@ -736,6 +1095,13 @@ export class MediaRequest {
         case Notification.MEDIA_PENDING:
           event = `New ${this.is4k ? '4K ' : ''}${mediaType} Request`;
           break;
+        case Notification.MEDIA_AUTO_REQUESTED:
+          event = `${
+            this.is4k ? '4K ' : ''
+          }${mediaType} Request Automatically Submitted`;
+          notifyAdmin = false;
+          notifySystem = false;
+          break;
         case Notification.MEDIA_AUTO_APPROVED:
           event = `${
             this.is4k ? '4K ' : ''
@@ -752,6 +1118,7 @@ export class MediaRequest {
           media,
           request: this,
           notifyAdmin,
+          notifySystem,
           notifyUser: notifyAdmin ? undefined : this.requestedBy,
           event,
           subject: `${movie.title}${
@@ -770,6 +1137,7 @@ export class MediaRequest {
           media,
           request: this,
           notifyAdmin,
+          notifySystem,
           notifyUser: notifyAdmin ? undefined : this.requestedBy,
           event,
           subject: `${tv.name}${
diff --git a/server/entity/Season.ts b/server/entity/Season.ts
index 77f9c760..44a83d97 100644
--- a/server/entity/Season.ts
+++ b/server/entity/Season.ts
@@ -1,12 +1,12 @@
+import { MediaStatus } from '@server/constants/media';
 import {
-  Entity,
-  PrimaryGeneratedColumn,
   Column,
-  ManyToOne,
   CreateDateColumn,
+  Entity,
+  ManyToOne,
+  PrimaryGeneratedColumn,
   UpdateDateColumn,
 } from 'typeorm';
-import { MediaStatus } from '../constants/media';
 import Media from './Media';
 
 @Entity()
diff --git a/server/entity/SeasonRequest.ts b/server/entity/SeasonRequest.ts
index f499406c..f9eeef50 100644
--- a/server/entity/SeasonRequest.ts
+++ b/server/entity/SeasonRequest.ts
@@ -1,12 +1,12 @@
+import { MediaRequestStatus } from '@server/constants/media';
 import {
-  Entity,
-  PrimaryGeneratedColumn,
   Column,
   CreateDateColumn,
-  UpdateDateColumn,
+  Entity,
   ManyToOne,
+  PrimaryGeneratedColumn,
+  UpdateDateColumn,
 } from 'typeorm';
-import { MediaRequestStatus } from '../constants/media';
 import { MediaRequest } from './MediaRequest';
 
 @Entity()
diff --git a/server/entity/Session.ts b/server/entity/Session.ts
index e7462c19..ddf851a6 100644
--- a/server/entity/Session.ts
+++ b/server/entity/Session.ts
@@ -1,5 +1,5 @@
-import { ISession } from 'connect-typeorm';
-import { Index, Column, PrimaryColumn, Entity } from 'typeorm';
+import type { ISession } from 'connect-typeorm';
+import { Column, Entity, Index, PrimaryColumn } from 'typeorm';
 
 @Entity()
 export class Session implements ISession {
diff --git a/server/entity/User.ts b/server/entity/User.ts
index d54e31ae..0c540fee 100644
--- a/server/entity/User.ts
+++ b/server/entity/User.ts
@@ -1,3 +1,13 @@
+import { MediaRequestStatus, MediaType } from '@server/constants/media';
+import { UserType } from '@server/constants/user';
+import { getRepository } from '@server/datasource';
+import type { QuotaResponse } from '@server/interfaces/api/userInterfaces';
+import PreparedEmail from '@server/lib/email';
+import type { PermissionCheckOptions } from '@server/lib/permissions';
+import { hasPermission, Permission } from '@server/lib/permissions';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
+import { AfterDate } from '@server/utils/dateHelpers';
 import bcrypt from 'bcrypt';
 import { randomUUID } from 'crypto';
 import path from 'path';
@@ -7,8 +17,6 @@ import {
   Column,
   CreateDateColumn,
   Entity,
-  getRepository,
-  MoreThan,
   Not,
   OneToMany,
   OneToOne,
@@ -16,17 +24,6 @@ import {
   RelationCount,
   UpdateDateColumn,
 } from 'typeorm';
-import { MediaRequestStatus, MediaType } from '../constants/media';
-import { UserType } from '../constants/user';
-import { QuotaResponse } from '../interfaces/api/userInterfaces';
-import PreparedEmail from '../lib/email';
-import {
-  hasPermission,
-  Permission,
-  PermissionCheckOptions,
-} from '../lib/permissions';
-import { getSettings } from '../lib/settings';
-import logger from '../logger';
 import Issue from './Issue';
 import { MediaRequest } from './MediaRequest';
 import SeasonRequest from './SeasonRequest';
@@ -255,13 +252,14 @@ export class User {
     if (movieQuotaDays) {
       movieDate.setDate(movieDate.getDate() - movieQuotaDays);
     }
-    const movieQuotaStartDate = movieDate.toJSON();
 
     const movieQuotaUsed = movieQuotaLimit
       ? await requestRepository.count({
           where: {
-            requestedBy: this,
-            createdAt: MoreThan(movieQuotaStartDate),
+            requestedBy: {
+              id: this.id,
+            },
+            createdAt: AfterDate(movieDate),
             type: MediaType.MOVIE,
             status: Not(MediaRequestStatus.DECLINED),
           },
diff --git a/server/entity/UserSettings.ts b/server/entity/UserSettings.ts
index 08397b12..771c382d 100644
--- a/server/entity/UserSettings.ts
+++ b/server/entity/UserSettings.ts
@@ -1,3 +1,6 @@
+import type { NotificationAgentTypes } from '@server/interfaces/api/userSettingsInterfaces';
+import { hasNotificationType, Notification } from '@server/lib/notifications';
+import { NotificationAgentKey } from '@server/lib/settings';
 import {
   Column,
   Entity,
@@ -5,9 +8,6 @@ import {
   OneToOne,
   PrimaryGeneratedColumn,
 } from 'typeorm';
-import { NotificationAgentTypes } from '../interfaces/api/userSettingsInterfaces';
-import { hasNotificationType, Notification } from '../lib/notifications';
-import { NotificationAgentKey } from '../lib/settings';
 import { User } from './User';
 
 export const ALL_NOTIFICATIONS = Object.values(Notification)
@@ -57,6 +57,12 @@ export class UserSettings {
   @Column({ nullable: true })
   public telegramSendSilently?: boolean;
 
+  @Column({ nullable: true })
+  public watchlistSyncMovies?: boolean;
+
+  @Column({ nullable: true })
+  public watchlistSyncTv?: boolean;
+
   @Column({
     type: 'text',
     nullable: true,
diff --git a/server/index.ts b/server/index.ts
index c8053012..e78d5a57 100644
--- a/server/index.ts
+++ b/server/index.ts
@@ -1,34 +1,37 @@
+import PlexAPI from '@server/api/plexapi';
+import dataSource, { getRepository } from '@server/datasource';
+import { Session } from '@server/entity/Session';
+import { User } from '@server/entity/User';
+import { startJobs } from '@server/job/schedule';
+import notificationManager from '@server/lib/notifications';
+import DiscordAgent from '@server/lib/notifications/agents/discord';
+import EmailAgent from '@server/lib/notifications/agents/email';
+import GotifyAgent from '@server/lib/notifications/agents/gotify';
+import LunaSeaAgent from '@server/lib/notifications/agents/lunasea';
+import PushbulletAgent from '@server/lib/notifications/agents/pushbullet';
+import PushoverAgent from '@server/lib/notifications/agents/pushover';
+import SlackAgent from '@server/lib/notifications/agents/slack';
+import TelegramAgent from '@server/lib/notifications/agents/telegram';
+import WebhookAgent from '@server/lib/notifications/agents/webhook';
+import WebPushAgent from '@server/lib/notifications/agents/webpush';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
+import routes from '@server/routes';
+import { getAppVersion } from '@server/utils/appVersion';
+import restartFlag from '@server/utils/restartFlag';
 import { getClientIp } from '@supercharge/request-ip';
 import { TypeormStore } from 'connect-typeorm/out';
 import cookieParser from 'cookie-parser';
 import csurf from 'csurf';
-import express, { NextFunction, Request, Response } from 'express';
+import type { NextFunction, Request, Response } from 'express';
+import express from 'express';
 import * as OpenApiValidator from 'express-openapi-validator';
-import session, { Store } from 'express-session';
+import type { Store } from 'express-session';
+import session from 'express-session';
 import next from 'next';
 import path from 'path';
 import swaggerUi from 'swagger-ui-express';
-import { createConnection, getRepository } from 'typeorm';
 import YAML from 'yamljs';
-import PlexAPI from './api/plexapi';
-import { Session } from './entity/Session';
-import { User } from './entity/User';
-import { startJobs } from './job/schedule';
-import notificationManager from './lib/notifications';
-import DiscordAgent from './lib/notifications/agents/discord';
-import EmailAgent from './lib/notifications/agents/email';
-import GotifyAgent from './lib/notifications/agents/gotify';
-import LunaSeaAgent from './lib/notifications/agents/lunasea';
-import PushbulletAgent from './lib/notifications/agents/pushbullet';
-import PushoverAgent from './lib/notifications/agents/pushover';
-import SlackAgent from './lib/notifications/agents/slack';
-import TelegramAgent from './lib/notifications/agents/telegram';
-import WebhookAgent from './lib/notifications/agents/webhook';
-import WebPushAgent from './lib/notifications/agents/webpush';
-import { getSettings } from './lib/settings';
-import logger from './logger';
-import routes from './routes';
-import { getAppVersion } from './utils/appVersion';
 
 const API_SPEC_PATH = path.join(__dirname, '../overseerr-api.yml');
 
@@ -40,7 +43,7 @@ const handle = app.getRequestHandler();
 app
   .prepare()
   .then(async () => {
-    const dbConnection = await createConnection();
+    const dbConnection = await dataSource.initialize();
 
     // Run migrations in production
     if (process.env.NODE_ENV === 'production') {
@@ -51,6 +54,7 @@ app
 
     // Load Settings
     const settings = getSettings().load();
+    restartFlag.initializeSettings(settings.main);
 
     // Migrate library types
     if (
@@ -59,8 +63,8 @@ app
     ) {
       const userRepository = getRepository(User);
       const admin = await userRepository.findOne({
-        select: ['id', 'plexToken'],
-        order: { id: 'ASC' },
+        select: { id: true, plexToken: true },
+        where: { id: 1 },
       });
 
       if (admin) {
diff --git a/server/interfaces/api/discoverInterfaces.ts b/server/interfaces/api/discoverInterfaces.ts
index db90e55d..89cb7426 100644
--- a/server/interfaces/api/discoverInterfaces.ts
+++ b/server/interfaces/api/discoverInterfaces.ts
@@ -3,3 +3,17 @@ export interface GenreSliderItem {
   name: string;
   backdrops: string[];
 }
+
+export interface WatchlistItem {
+  ratingKey: string;
+  tmdbId: number;
+  mediaType: 'movie' | 'tv';
+  title: string;
+}
+
+export interface WatchlistResponse {
+  page: number;
+  totalPages: number;
+  totalResults: number;
+  results: WatchlistItem[];
+}
diff --git a/server/interfaces/api/issueInterfaces.ts b/server/interfaces/api/issueInterfaces.ts
index bd17f195..e5b3643c 100644
--- a/server/interfaces/api/issueInterfaces.ts
+++ b/server/interfaces/api/issueInterfaces.ts
@@ -1,5 +1,5 @@
-import Issue from '../../entity/Issue';
-import { PaginatedResponse } from './common';
+import type Issue from '@server/entity/Issue';
+import type { PaginatedResponse } from './common';
 
 export interface IssueResultsResponse extends PaginatedResponse {
   results: Issue[];
diff --git a/server/interfaces/api/mediaInterfaces.ts b/server/interfaces/api/mediaInterfaces.ts
index d17716d2..263d859a 100644
--- a/server/interfaces/api/mediaInterfaces.ts
+++ b/server/interfaces/api/mediaInterfaces.ts
@@ -1,6 +1,6 @@
-import type Media from '../../entity/Media';
-import { User } from '../../entity/User';
-import { PaginatedResponse } from './common';
+import type Media from '@server/entity/Media';
+import type { User } from '@server/entity/User';
+import type { PaginatedResponse } from './common';
 
 export interface MediaResultsResponse extends PaginatedResponse {
   results: Media[];
diff --git a/server/interfaces/api/personInterfaces.ts b/server/interfaces/api/personInterfaces.ts
index 19d3468c..c52ad0c6 100644
--- a/server/interfaces/api/personInterfaces.ts
+++ b/server/interfaces/api/personInterfaces.ts
@@ -1,4 +1,4 @@
-import { PersonCreditCast, PersonCreditCrew } from '../../models/Person';
+import type { PersonCreditCast, PersonCreditCrew } from '@server/models/Person';
 
 export interface PersonCombinedCreditsResponse {
   id: number;
diff --git a/server/interfaces/api/plexInterfaces.ts b/server/interfaces/api/plexInterfaces.ts
index 5373cb58..32be891e 100644
--- a/server/interfaces/api/plexInterfaces.ts
+++ b/server/interfaces/api/plexInterfaces.ts
@@ -1,4 +1,4 @@
-import { PlexSettings } from '../../lib/settings';
+import type { PlexSettings } from '@server/lib/settings';
 
 export interface PlexStatus {
   settings: PlexSettings;
diff --git a/server/interfaces/api/requestInterfaces.ts b/server/interfaces/api/requestInterfaces.ts
index ca39515b..89863cb0 100644
--- a/server/interfaces/api/requestInterfaces.ts
+++ b/server/interfaces/api/requestInterfaces.ts
@@ -1,6 +1,21 @@
+import type { MediaType } from '@server/constants/media';
+import type { MediaRequest } from '@server/entity/MediaRequest';
 import type { PaginatedResponse } from './common';
-import type { MediaRequest } from '../../entity/MediaRequest';
 
 export interface RequestResultsResponse extends PaginatedResponse {
   results: MediaRequest[];
 }
+
+export type MediaRequestBody = {
+  mediaType: MediaType;
+  mediaId: number;
+  tvdbId?: number;
+  seasons?: number[] | 'all';
+  is4k?: boolean;
+  serverId?: number;
+  profileId?: number;
+  rootFolder?: string;
+  languageProfileId?: number;
+  userId?: number;
+  tags?: number[];
+};
diff --git a/server/interfaces/api/serviceInterfaces.ts b/server/interfaces/api/serviceInterfaces.ts
index 1188f24c..3b430b0b 100644
--- a/server/interfaces/api/serviceInterfaces.ts
+++ b/server/interfaces/api/serviceInterfaces.ts
@@ -1,5 +1,5 @@
-import { QualityProfile, RootFolder, Tag } from '../../api/servarr/base';
-import { LanguageProfile } from '../../api/servarr/sonarr';
+import type { QualityProfile, RootFolder, Tag } from '@server/api/servarr/base';
+import type { LanguageProfile } from '@server/api/servarr/sonarr';
 
 export interface ServiceCommonServer {
   id: number;
diff --git a/server/interfaces/api/settingsInterfaces.ts b/server/interfaces/api/settingsInterfaces.ts
index 8e4f66c4..0e5ab45a 100644
--- a/server/interfaces/api/settingsInterfaces.ts
+++ b/server/interfaces/api/settingsInterfaces.ts
@@ -56,4 +56,5 @@ export interface StatusResponse {
   commitTag: string;
   updateAvailable: boolean;
   commitsBehind: number;
+  restartRequired: boolean;
 }
diff --git a/server/interfaces/api/userInterfaces.ts b/server/interfaces/api/userInterfaces.ts
index e5f56482..2ac75c5e 100644
--- a/server/interfaces/api/userInterfaces.ts
+++ b/server/interfaces/api/userInterfaces.ts
@@ -1,7 +1,7 @@
-import Media from '../../entity/Media';
-import { MediaRequest } from '../../entity/MediaRequest';
-import type { User } from '../../entity/User';
-import { PaginatedResponse } from './common';
+import type Media from '@server/entity/Media';
+import type { MediaRequest } from '@server/entity/MediaRequest';
+import type { User } from '@server/entity/User';
+import type { PaginatedResponse } from './common';
 
 export interface UserResultsResponse extends PaginatedResponse {
   results: User[];
@@ -23,6 +23,7 @@ export interface QuotaResponse {
   movie: QuotaStatus;
   tv: QuotaStatus;
 }
+
 export interface UserWatchDataResponse {
   recentlyWatched: Media[];
   playCount: number;
diff --git a/server/interfaces/api/userSettingsInterfaces.ts b/server/interfaces/api/userSettingsInterfaces.ts
index a3e132d6..b5b69245 100644
--- a/server/interfaces/api/userSettingsInterfaces.ts
+++ b/server/interfaces/api/userSettingsInterfaces.ts
@@ -1,4 +1,4 @@
-import { NotificationAgentKey } from '../../lib/settings';
+import type { NotificationAgentKey } from '@server/lib/settings';
 
 export interface UserSettingsGeneralResponse {
   username?: string;
@@ -14,6 +14,8 @@ export interface UserSettingsGeneralResponse {
   globalMovieQuotaLimit?: number;
   globalTvQuotaLimit?: number;
   globalTvQuotaDays?: number;
+  watchlistSyncMovies?: boolean;
+  watchlistSyncTv?: boolean;
 }
 
 export type NotificationAgentTypes = Record<NotificationAgentKey, number>;
diff --git a/server/job/schedule.ts b/server/job/schedule.ts
index 568b28c9..29dabc13 100644
--- a/server/job/schedule.ts
+++ b/server/job/schedule.ts
@@ -1,10 +1,12 @@
+import downloadTracker from '@server/lib/downloadtracker';
+import { plexFullScanner, plexRecentScanner } from '@server/lib/scanners/plex';
+import { radarrScanner } from '@server/lib/scanners/radarr';
+import { sonarrScanner } from '@server/lib/scanners/sonarr';
+import type { JobId } from '@server/lib/settings';
+import { getSettings } from '@server/lib/settings';
+import watchlistSync from '@server/lib/watchlistsync';
+import logger from '@server/logger';
 import schedule from 'node-schedule';
-import downloadTracker from '../lib/downloadtracker';
-import { plexFullScanner, plexRecentScanner } from '../lib/scanners/plex';
-import { radarrScanner } from '../lib/scanners/radarr';
-import { sonarrScanner } from '../lib/scanners/sonarr';
-import { getSettings, JobId } from '../lib/settings';
-import logger from '../logger';
 
 interface ScheduledJob {
   id: JobId;
@@ -12,6 +14,7 @@ interface ScheduledJob {
   name: string;
   type: 'process' | 'command';
   interval: 'short' | 'long' | 'fixed';
+  cronSchedule: string;
   running?: () => boolean;
   cancelFn?: () => void;
 }
@@ -27,6 +30,7 @@ export const startJobs = (): void => {
     name: 'Plex Recently Added Scan',
     type: 'process',
     interval: 'short',
+    cronSchedule: jobs['plex-recently-added-scan'].schedule,
     job: schedule.scheduleJob(jobs['plex-recently-added-scan'].schedule, () => {
       logger.info('Starting scheduled job: Plex Recently Added Scan', {
         label: 'Jobs',
@@ -43,6 +47,7 @@ export const startJobs = (): void => {
     name: 'Plex Full Library Scan',
     type: 'process',
     interval: 'long',
+    cronSchedule: jobs['plex-full-scan'].schedule,
     job: schedule.scheduleJob(jobs['plex-full-scan'].schedule, () => {
       logger.info('Starting scheduled job: Plex Full Library Scan', {
         label: 'Jobs',
@@ -53,12 +58,28 @@ export const startJobs = (): void => {
     cancelFn: () => plexFullScanner.cancel(),
   });
 
+  // Run watchlist sync every 5 minutes
+  scheduledJobs.push({
+    id: 'plex-watchlist-sync',
+    name: 'Plex Watchlist Sync',
+    type: 'process',
+    interval: 'long',
+    cronSchedule: jobs['plex-watchlist-sync'].schedule,
+    job: schedule.scheduleJob(jobs['plex-watchlist-sync'].schedule, () => {
+      logger.info('Starting scheduled job: Plex Watchlist Sync', {
+        label: 'Jobs',
+      });
+      watchlistSync.syncWatchlist();
+    }),
+  });
+
   // Run full radarr scan every 24 hours
   scheduledJobs.push({
     id: 'radarr-scan',
     name: 'Radarr Scan',
     type: 'process',
     interval: 'long',
+    cronSchedule: jobs['radarr-scan'].schedule,
     job: schedule.scheduleJob(jobs['radarr-scan'].schedule, () => {
       logger.info('Starting scheduled job: Radarr Scan', { label: 'Jobs' });
       radarrScanner.run();
@@ -73,6 +94,7 @@ export const startJobs = (): void => {
     name: 'Sonarr Scan',
     type: 'process',
     interval: 'long',
+    cronSchedule: jobs['sonarr-scan'].schedule,
     job: schedule.scheduleJob(jobs['sonarr-scan'].schedule, () => {
       logger.info('Starting scheduled job: Sonarr Scan', { label: 'Jobs' });
       sonarrScanner.run();
@@ -87,6 +109,7 @@ export const startJobs = (): void => {
     name: 'Download Sync',
     type: 'command',
     interval: 'fixed',
+    cronSchedule: jobs['download-sync'].schedule,
     job: schedule.scheduleJob(jobs['download-sync'].schedule, () => {
       logger.debug('Starting scheduled job: Download Sync', {
         label: 'Jobs',
@@ -101,6 +124,7 @@ export const startJobs = (): void => {
     name: 'Download Sync Reset',
     type: 'command',
     interval: 'long',
+    cronSchedule: jobs['download-sync-reset'].schedule,
     job: schedule.scheduleJob(jobs['download-sync-reset'].schedule, () => {
       logger.info('Starting scheduled job: Download Sync Reset', {
         label: 'Jobs',
diff --git a/server/lib/cache.ts b/server/lib/cache.ts
index 7782a05a..e8146662 100644
--- a/server/lib/cache.ts
+++ b/server/lib/cache.ts
@@ -6,7 +6,8 @@ export type AvailableCacheIds =
   | 'sonarr'
   | 'rt'
   | 'github'
-  | 'plexguid';
+  | 'plexguid'
+  | 'plextv';
 
 const DEFAULT_TTL = 300;
 const DEFAULT_CHECK_PERIOD = 120;
@@ -58,6 +59,10 @@ class CacheManager {
       stdTtl: 86400 * 7, // 1 week cache
       checkPeriod: 60 * 30,
     }),
+    plextv: new Cache('plextv', 'Plex TV', {
+      stdTtl: 86400 * 7, // 1 week cache
+      checkPeriod: 60,
+    }),
   };
 
   public getCache(id: AvailableCacheIds): Cache {
diff --git a/server/lib/downloadtracker.ts b/server/lib/downloadtracker.ts
index c62e189d..4aef968f 100644
--- a/server/lib/downloadtracker.ts
+++ b/server/lib/downloadtracker.ts
@@ -1,9 +1,9 @@
+import RadarrAPI from '@server/api/servarr/radarr';
+import SonarrAPI from '@server/api/servarr/sonarr';
+import { MediaType } from '@server/constants/media';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
 import { uniqWith } from 'lodash';
-import RadarrAPI from '../api/servarr/radarr';
-import SonarrAPI from '../api/servarr/sonarr';
-import { MediaType } from '../constants/media';
-import logger from '../logger';
-import { getSettings } from './settings';
 
 export interface DownloadingItem {
   mediaType: MediaType;
diff --git a/server/lib/email/index.ts b/server/lib/email/index.ts
index 1274d6a8..c38892ae 100644
--- a/server/lib/email/index.ts
+++ b/server/lib/email/index.ts
@@ -1,7 +1,8 @@
+import type { NotificationAgentEmail } from '@server/lib/settings';
+import { getSettings } from '@server/lib/settings';
 import Email from 'email-templates';
 import nodemailer from 'nodemailer';
 import { URL } from 'url';
-import { getSettings, NotificationAgentEmail } from '../settings';
 import { openpgpEncrypt } from './openpgpEncrypt';
 
 class PreparedEmail extends Email {
diff --git a/server/lib/email/openpgpEncrypt.ts b/server/lib/email/openpgpEncrypt.ts
index c067a7d5..dd320ea3 100644
--- a/server/lib/email/openpgpEncrypt.ts
+++ b/server/lib/email/openpgpEncrypt.ts
@@ -1,7 +1,8 @@
+import logger from '@server/logger';
 import { randomBytes } from 'crypto';
 import * as openpgp from 'openpgp';
-import { Transform, TransformCallback } from 'stream';
-import logger from '../../logger';
+import type { TransformCallback } from 'stream';
+import { Transform } from 'stream';
 
 interface EncryptorOptions {
   signingKey?: string;
@@ -26,7 +27,7 @@ class PGPEncryptor extends Transform {
 
   // just save the whole message
   _transform = (
-    chunk: any,
+    chunk: Uint8Array,
     _encoding: BufferEncoding,
     callback: TransformCallback
   ): void => {
@@ -184,6 +185,9 @@ class PGPEncryptor extends Transform {
 }
 
 export const openpgpEncrypt = (options: EncryptorOptions) => {
+  // Disabling this line because I don't want to fix it but I am tired
+  // of seeing the lint warning
+  // eslint-disable-next-line @typescript-eslint/no-explicit-any
   return function (mail: any, callback: () => unknown): void {
     if (!options.encryptionKeys.length) {
       setImmediate(callback);
diff --git a/server/lib/notifications/agents/agent.ts b/server/lib/notifications/agents/agent.ts
index edfa1262..d2b0b165 100644
--- a/server/lib/notifications/agents/agent.ts
+++ b/server/lib/notifications/agents/agent.ts
@@ -1,14 +1,15 @@
-import { Notification } from '..';
-import type Issue from '../../../entity/Issue';
-import IssueComment from '../../../entity/IssueComment';
-import Media from '../../../entity/Media';
-import { MediaRequest } from '../../../entity/MediaRequest';
-import { User } from '../../../entity/User';
-import { NotificationAgentConfig } from '../../settings';
+import type Issue from '@server/entity/Issue';
+import type IssueComment from '@server/entity/IssueComment';
+import type Media from '@server/entity/Media';
+import type { MediaRequest } from '@server/entity/MediaRequest';
+import type { User } from '@server/entity/User';
+import type { NotificationAgentConfig } from '@server/lib/settings';
+import type { Notification } from '..';
 
 export interface NotificationPayload {
   event?: string;
   subject: string;
+  notifySystem: boolean;
   notifyAdmin: boolean;
   notifyUser?: User;
   media?: Media;
diff --git a/server/lib/notifications/agents/discord.ts b/server/lib/notifications/agents/discord.ts
index 32120035..67a278bf 100644
--- a/server/lib/notifications/agents/discord.ts
+++ b/server/lib/notifications/agents/discord.ts
@@ -1,19 +1,17 @@
+import { IssueStatus, IssueTypeName } from '@server/constants/issue';
+import { getRepository } from '@server/datasource';
+import { User } from '@server/entity/User';
+import type { NotificationAgentDiscord } from '@server/lib/settings';
+import { getSettings, NotificationAgentKey } from '@server/lib/settings';
+import logger from '@server/logger';
 import axios from 'axios';
-import { getRepository } from 'typeorm';
 import {
   hasNotificationType,
   Notification,
   shouldSendAdminNotification,
 } from '..';
-import { IssueStatus, IssueTypeName } from '../../../constants/issue';
-import { User } from '../../../entity/User';
-import logger from '../../../logger';
-import {
-  getSettings,
-  NotificationAgentDiscord,
-  NotificationAgentKey,
-} from '../../settings';
-import { BaseAgent, NotificationAgent, NotificationPayload } from './agent';
+import type { NotificationAgent, NotificationPayload } from './agent';
+import { BaseAgent } from './agent';
 
 enum EmbedColors {
   DEFAULT = 0,
@@ -245,7 +243,10 @@ class DiscordAgent
   ): Promise<boolean> {
     const settings = this.getSettings();
 
-    if (!hasNotificationType(type, settings.types ?? 0)) {
+    if (
+      !payload.notifySystem ||
+      !hasNotificationType(type, settings.types ?? 0)
+    ) {
       return true;
     }
 
diff --git a/server/lib/notifications/agents/email.ts b/server/lib/notifications/agents/email.ts
index a1dd7e4e..b668b550 100644
--- a/server/lib/notifications/agents/email.ts
+++ b/server/lib/notifications/agents/email.ts
@@ -1,18 +1,16 @@
-import { EmailOptions } from 'email-templates';
+import { IssueType, IssueTypeName } from '@server/constants/issue';
+import { MediaType } from '@server/constants/media';
+import { getRepository } from '@server/datasource';
+import { User } from '@server/entity/User';
+import PreparedEmail from '@server/lib/email';
+import type { NotificationAgentEmail } from '@server/lib/settings';
+import { getSettings, NotificationAgentKey } from '@server/lib/settings';
+import logger from '@server/logger';
+import type { EmailOptions } from 'email-templates';
 import path from 'path';
-import { getRepository } from 'typeorm';
 import { Notification, shouldSendAdminNotification } from '..';
-import { IssueType, IssueTypeName } from '../../../constants/issue';
-import { MediaType } from '../../../constants/media';
-import { User } from '../../../entity/User';
-import logger from '../../../logger';
-import PreparedEmail from '../../email';
-import {
-  getSettings,
-  NotificationAgentEmail,
-  NotificationAgentKey,
-} from '../../settings';
-import { BaseAgent, NotificationAgent, NotificationPayload } from './agent';
+import type { NotificationAgent, NotificationPayload } from './agent';
+import { BaseAgent } from './agent';
 
 class EmailAgent
   extends BaseAgent<NotificationAgentEmail>
@@ -83,6 +81,11 @@ class EmailAgent
             is4k ? 'in 4K ' : ''
           }is pending approval:`;
           break;
+        case Notification.MEDIA_AUTO_REQUESTED:
+          body = `A new request for the following ${mediaType} ${
+            is4k ? 'in 4K ' : ''
+          }was automatically submitted:`;
+          break;
         case Notification.MEDIA_APPROVED:
           body = `Your request for the following ${mediaType} ${
             is4k ? 'in 4K ' : ''
diff --git a/server/lib/notifications/agents/gotify.ts b/server/lib/notifications/agents/gotify.ts
index ecd54ce7..d07caac4 100644
--- a/server/lib/notifications/agents/gotify.ts
+++ b/server/lib/notifications/agents/gotify.ts
@@ -1,15 +1,17 @@
+import { IssueStatus, IssueTypeName } from '@server/constants/issue';
+import type { NotificationAgentGotify } from '@server/lib/settings';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
 import axios from 'axios';
 import { hasNotificationType, Notification } from '..';
-import { IssueStatus, IssueTypeName } from '../../../constants/issue';
-import logger from '../../../logger';
-import { getSettings, NotificationAgentGotify } from '../../settings';
-import { BaseAgent, NotificationAgent, NotificationPayload } from './agent';
+import type { NotificationAgent, NotificationPayload } from './agent';
+import { BaseAgent } from './agent';
 
 interface GotifyPayload {
   title: string;
   message: string;
   priority: number;
-  extras: any;
+  extras: Record<string, unknown>;
 }
 
 class GotifyAgent
@@ -115,7 +117,10 @@ class GotifyAgent
   ): Promise<boolean> {
     const settings = this.getSettings();
 
-    if (!hasNotificationType(type, settings.types ?? 0)) {
+    if (
+      !payload.notifySystem ||
+      !hasNotificationType(type, settings.types ?? 0)
+    ) {
       return true;
     }
 
diff --git a/server/lib/notifications/agents/lunasea.ts b/server/lib/notifications/agents/lunasea.ts
index 0269e260..885b038c 100644
--- a/server/lib/notifications/agents/lunasea.ts
+++ b/server/lib/notifications/agents/lunasea.ts
@@ -1,10 +1,12 @@
+import { IssueStatus, IssueType } from '@server/constants/issue';
+import { MediaStatus } from '@server/constants/media';
+import type { NotificationAgentLunaSea } from '@server/lib/settings';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
 import axios from 'axios';
 import { hasNotificationType, Notification } from '..';
-import { IssueStatus, IssueType } from '../../../constants/issue';
-import { MediaStatus } from '../../../constants/media';
-import logger from '../../../logger';
-import { getSettings, NotificationAgentLunaSea } from '../../settings';
-import { BaseAgent, NotificationAgent, NotificationPayload } from './agent';
+import type { NotificationAgent, NotificationPayload } from './agent';
+import { BaseAgent } from './agent';
 
 class LunaSeaAgent
   extends BaseAgent<NotificationAgentLunaSea>
@@ -85,7 +87,10 @@ class LunaSeaAgent
   ): Promise<boolean> {
     const settings = this.getSettings();
 
-    if (!hasNotificationType(type, settings.types ?? 0)) {
+    if (
+      !payload.notifySystem ||
+      !hasNotificationType(type, settings.types ?? 0)
+    ) {
       return true;
     }
 
diff --git a/server/lib/notifications/agents/pushbullet.ts b/server/lib/notifications/agents/pushbullet.ts
index b7bc1919..eed4fda9 100644
--- a/server/lib/notifications/agents/pushbullet.ts
+++ b/server/lib/notifications/agents/pushbullet.ts
@@ -1,19 +1,18 @@
+import { IssueStatus, IssueTypeName } from '@server/constants/issue';
+import { MediaStatus } from '@server/constants/media';
+import { getRepository } from '@server/datasource';
+import { User } from '@server/entity/User';
+import type { NotificationAgentPushbullet } from '@server/lib/settings';
+import { getSettings, NotificationAgentKey } from '@server/lib/settings';
+import logger from '@server/logger';
 import axios from 'axios';
-import { getRepository } from 'typeorm';
 import {
   hasNotificationType,
   Notification,
   shouldSendAdminNotification,
 } from '..';
-import { IssueStatus, IssueTypeName } from '../../../constants/issue';
-import { User } from '../../../entity/User';
-import logger from '../../../logger';
-import {
-  getSettings,
-  NotificationAgentKey,
-  NotificationAgentPushbullet,
-} from '../../settings';
-import { BaseAgent, NotificationAgent, NotificationPayload } from './agent';
+import type { NotificationAgent, NotificationPayload } from './agent';
+import { BaseAgent } from './agent';
 
 interface PushbulletPayload {
   type: string;
@@ -54,6 +53,12 @@ class PushbulletAgent
 
       let status = '';
       switch (type) {
+        case Notification.MEDIA_AUTO_REQUESTED:
+          status =
+            payload.media?.status === MediaStatus.PENDING
+              ? 'Pending Approval'
+              : 'Processing';
+          break;
         case Notification.MEDIA_PENDING:
           status = 'Pending Approval';
           break;
@@ -106,6 +111,7 @@ class PushbulletAgent
 
     // Send system notification
     if (
+      payload.notifySystem &&
       hasNotificationType(type, settings.types ?? 0) &&
       settings.enabled &&
       settings.options.accessToken
diff --git a/server/lib/notifications/agents/pushover.ts b/server/lib/notifications/agents/pushover.ts
index f8364c3f..d8deb1bd 100644
--- a/server/lib/notifications/agents/pushover.ts
+++ b/server/lib/notifications/agents/pushover.ts
@@ -1,19 +1,18 @@
+import { IssueStatus, IssueTypeName } from '@server/constants/issue';
+import { MediaStatus } from '@server/constants/media';
+import { getRepository } from '@server/datasource';
+import { User } from '@server/entity/User';
+import type { NotificationAgentPushover } from '@server/lib/settings';
+import { getSettings, NotificationAgentKey } from '@server/lib/settings';
+import logger from '@server/logger';
 import axios from 'axios';
-import { getRepository } from 'typeorm';
 import {
   hasNotificationType,
   Notification,
   shouldSendAdminNotification,
 } from '..';
-import { IssueStatus, IssueTypeName } from '../../../constants/issue';
-import { User } from '../../../entity/User';
-import logger from '../../../logger';
-import {
-  getSettings,
-  NotificationAgentKey,
-  NotificationAgentPushover,
-} from '../../settings';
-import { BaseAgent, NotificationAgent, NotificationPayload } from './agent';
+import type { NotificationAgent, NotificationPayload } from './agent';
+import { BaseAgent } from './agent';
 
 interface PushoverPayload {
   token: string;
@@ -63,6 +62,12 @@ class PushoverAgent
 
       let status = '';
       switch (type) {
+        case Notification.MEDIA_AUTO_REQUESTED:
+          status =
+            payload.media?.status === MediaStatus.PENDING
+              ? 'Pending Approval'
+              : 'Processing';
+          break;
         case Notification.MEDIA_PENDING:
           status = 'Pending Approval';
           break;
@@ -137,6 +142,7 @@ class PushoverAgent
 
     // Send system notification
     if (
+      payload.notifySystem &&
       hasNotificationType(type, settings.types ?? 0) &&
       settings.enabled &&
       settings.options.accessToken &&
diff --git a/server/lib/notifications/agents/slack.ts b/server/lib/notifications/agents/slack.ts
index ca10c269..9447cda3 100644
--- a/server/lib/notifications/agents/slack.ts
+++ b/server/lib/notifications/agents/slack.ts
@@ -1,9 +1,11 @@
+import { IssueStatus, IssueTypeName } from '@server/constants/issue';
+import type { NotificationAgentSlack } from '@server/lib/settings';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
 import axios from 'axios';
 import { hasNotificationType, Notification } from '..';
-import { IssueStatus, IssueTypeName } from '../../../constants/issue';
-import logger from '../../../logger';
-import { getSettings, NotificationAgentSlack } from '../../settings';
-import { BaseAgent, NotificationAgent, NotificationPayload } from './agent';
+import type { NotificationAgent, NotificationPayload } from './agent';
+import { BaseAgent } from './agent';
 
 interface EmbedField {
   type: 'plain_text' | 'mrkdwn';
@@ -223,7 +225,10 @@ class SlackAgent
   ): Promise<boolean> {
     const settings = this.getSettings();
 
-    if (!hasNotificationType(type, settings.types ?? 0)) {
+    if (
+      !payload.notifySystem ||
+      !hasNotificationType(type, settings.types ?? 0)
+    ) {
       return true;
     }
 
diff --git a/server/lib/notifications/agents/telegram.ts b/server/lib/notifications/agents/telegram.ts
index 3450a3c2..7d706212 100644
--- a/server/lib/notifications/agents/telegram.ts
+++ b/server/lib/notifications/agents/telegram.ts
@@ -1,19 +1,18 @@
+import { IssueStatus, IssueTypeName } from '@server/constants/issue';
+import { MediaStatus } from '@server/constants/media';
+import { getRepository } from '@server/datasource';
+import { User } from '@server/entity/User';
+import type { NotificationAgentTelegram } from '@server/lib/settings';
+import { getSettings, NotificationAgentKey } from '@server/lib/settings';
+import logger from '@server/logger';
 import axios from 'axios';
-import { getRepository } from 'typeorm';
 import {
   hasNotificationType,
   Notification,
   shouldSendAdminNotification,
 } from '..';
-import { IssueStatus, IssueTypeName } from '../../../constants/issue';
-import { User } from '../../../entity/User';
-import logger from '../../../logger';
-import {
-  getSettings,
-  NotificationAgentKey,
-  NotificationAgentTelegram,
-} from '../../settings';
-import { BaseAgent, NotificationAgent, NotificationPayload } from './agent';
+import type { NotificationAgent, NotificationPayload } from './agent';
+import { BaseAgent } from './agent';
 
 interface TelegramMessagePayload {
   text: string;
@@ -81,6 +80,12 @@ class TelegramAgent
 
       let status = '';
       switch (type) {
+        case Notification.MEDIA_AUTO_REQUESTED:
+          status =
+            payload.media?.status === MediaStatus.PENDING
+              ? 'Pending Approval'
+              : 'Processing';
+          break;
         case Notification.MEDIA_PENDING:
           status = 'Pending Approval';
           break;
@@ -159,6 +164,7 @@ class TelegramAgent
 
     // Send system notification
     if (
+      payload.notifySystem &&
       hasNotificationType(type, settings.types ?? 0) &&
       settings.options.chatId
     ) {
diff --git a/server/lib/notifications/agents/webhook.ts b/server/lib/notifications/agents/webhook.ts
index ba2bf5e5..461cd37f 100644
--- a/server/lib/notifications/agents/webhook.ts
+++ b/server/lib/notifications/agents/webhook.ts
@@ -1,11 +1,13 @@
+import { IssueStatus, IssueType } from '@server/constants/issue';
+import { MediaStatus } from '@server/constants/media';
+import type { NotificationAgentWebhook } from '@server/lib/settings';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
 import axios from 'axios';
 import { get } from 'lodash';
 import { hasNotificationType, Notification } from '..';
-import { IssueStatus, IssueType } from '../../../constants/issue';
-import { MediaStatus } from '../../../constants/media';
-import logger from '../../../logger';
-import { getSettings, NotificationAgentWebhook } from '../../settings';
-import { BaseAgent, NotificationAgent, NotificationPayload } from './agent';
+import type { NotificationAgent, NotificationPayload } from './agent';
+import { BaseAgent } from './agent';
 
 type KeyMapFunction = (
   payload: NotificationPayload,
@@ -162,7 +164,10 @@ class WebhookAgent
   ): Promise<boolean> {
     const settings = this.getSettings();
 
-    if (!hasNotificationType(type, settings.types ?? 0)) {
+    if (
+      !payload.notifySystem ||
+      !hasNotificationType(type, settings.types ?? 0)
+    ) {
       return true;
     }
 
diff --git a/server/lib/notifications/agents/webpush.ts b/server/lib/notifications/agents/webpush.ts
index c87d9496..275a77e8 100644
--- a/server/lib/notifications/agents/webpush.ts
+++ b/server/lib/notifications/agents/webpush.ts
@@ -1,17 +1,15 @@
-import { getRepository } from 'typeorm';
+import { IssueType, IssueTypeName } from '@server/constants/issue';
+import { MediaType } from '@server/constants/media';
+import { getRepository } from '@server/datasource';
+import { User } from '@server/entity/User';
+import { UserPushSubscription } from '@server/entity/UserPushSubscription';
+import type { NotificationAgentConfig } from '@server/lib/settings';
+import { getSettings, NotificationAgentKey } from '@server/lib/settings';
+import logger from '@server/logger';
 import webpush from 'web-push';
 import { Notification, shouldSendAdminNotification } from '..';
-import { IssueType, IssueTypeName } from '../../../constants/issue';
-import { MediaType } from '../../../constants/media';
-import { User } from '../../../entity/User';
-import { UserPushSubscription } from '../../../entity/UserPushSubscription';
-import logger from '../../../logger';
-import {
-  getSettings,
-  NotificationAgentConfig,
-  NotificationAgentKey,
-} from '../../settings';
-import { BaseAgent, NotificationAgent, NotificationPayload } from './agent';
+import type { NotificationAgent, NotificationPayload } from './agent';
+import { BaseAgent } from './agent';
 
 interface PushNotificationPayload {
   notificationType: string;
@@ -59,6 +57,11 @@ class WebPushAgent
       case Notification.TEST_NOTIFICATION:
         message = payload.message;
         break;
+      case Notification.MEDIA_AUTO_REQUESTED:
+        message = `Automatically submitted a new ${
+          is4k ? '4K ' : ''
+        }${mediaType} request.`;
+        break;
       case Notification.MEDIA_APPROVED:
         message = `Your ${
           is4k ? '4K ' : ''
@@ -160,7 +163,7 @@ class WebPushAgent
         true)
     ) {
       const notifySubs = await userPushSubRepository.find({
-        where: { user: payload.notifyUser.id },
+        where: { user: { id: payload.notifyUser.id } },
       });
 
       pushSubs.push(...notifySubs);
diff --git a/server/lib/notifications/index.ts b/server/lib/notifications/index.ts
index b8111d02..71aea8fe 100644
--- a/server/lib/notifications/index.ts
+++ b/server/lib/notifications/index.ts
@@ -1,6 +1,6 @@
-import { User } from '../../entity/User';
-import logger from '../../logger';
-import { Permission } from '../permissions';
+import type { User } from '@server/entity/User';
+import { Permission } from '@server/lib/permissions';
+import logger from '@server/logger';
 import type { NotificationAgent, NotificationPayload } from './agents/agent';
 
 export enum Notification {
@@ -16,6 +16,7 @@ export enum Notification {
   ISSUE_COMMENT = 512,
   ISSUE_RESOLVED = 1024,
   ISSUE_REOPENED = 2048,
+  MEDIA_AUTO_REQUESTED = 4096,
 }
 
 export const hasNotificationType = (
diff --git a/server/lib/permissions.ts b/server/lib/permissions.ts
index 95160d38..98c81a49 100644
--- a/server/lib/permissions.ts
+++ b/server/lib/permissions.ts
@@ -1,7 +1,6 @@
 export enum Permission {
   NONE = 0,
   ADMIN = 2,
-  MANAGE_SETTINGS = 4,
   MANAGE_USERS = 8,
   MANAGE_REQUESTS = 16,
   REQUEST = 32,
@@ -22,6 +21,11 @@ export enum Permission {
   MANAGE_ISSUES = 1048576,
   VIEW_ISSUES = 2097152,
   CREATE_ISSUES = 4194304,
+  AUTO_REQUEST = 8388608,
+  AUTO_REQUEST_MOVIE = 16777216,
+  AUTO_REQUEST_TV = 33554432,
+  RECENT_VIEW = 67108864,
+  WATCHLIST_VIEW = 134217728,
 }
 
 export interface PermissionCheckOptions {
diff --git a/server/lib/scanners/baseScanner.ts b/server/lib/scanners/baseScanner.ts
index f76ea92b..f0f3db7e 100644
--- a/server/lib/scanners/baseScanner.ts
+++ b/server/lib/scanners/baseScanner.ts
@@ -1,12 +1,12 @@
+import TheMovieDb from '@server/api/themoviedb';
+import { MediaStatus, MediaType } from '@server/constants/media';
+import { getRepository } from '@server/datasource';
+import Media from '@server/entity/Media';
+import Season from '@server/entity/Season';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
+import AsyncLock from '@server/utils/asyncLock';
 import { randomUUID } from 'crypto';
-import { getRepository } from 'typeorm';
-import TheMovieDb from '../../api/themoviedb';
-import { MediaStatus, MediaType } from '../../constants/media';
-import Media from '../../entity/Media';
-import Season from '../../entity/Season';
-import logger from '../../logger';
-import AsyncLock from '../../utils/asyncLock';
-import { getSettings } from '../settings';
 
 // Default scan rates (can be overidden)
 const BUNDLE_SIZE = 20;
@@ -210,7 +210,7 @@ class BaseScanner<T> {
   }
 
   /**
-   * processShow takes a TMDb ID and an array of ProcessableSeasons, which
+   * processShow takes a TMDB ID and an array of ProcessableSeasons, which
    * should include the total episodes a sesaon has + the total available
    * episodes that each season currently has. Unlike processMovie, this method
    * does not take an `is4k` option. We handle both the 4k _and_ non 4k status
diff --git a/server/lib/scanners/plex/index.ts b/server/lib/scanners/plex/index.ts
index cd8dbd76..73e4d9b2 100644
--- a/server/lib/scanners/plex/index.ts
+++ b/server/lib/scanners/plex/index.ts
@@ -1,17 +1,20 @@
-import { uniqWith } from 'lodash';
-import { getRepository } from 'typeorm';
-import animeList from '../../../api/animelist';
-import PlexAPI, { PlexLibraryItem, PlexMetadata } from '../../../api/plexapi';
-import { TmdbTvDetails } from '../../../api/themoviedb/interfaces';
-import { User } from '../../../entity/User';
-import cacheManager from '../../cache';
-import { getSettings, Library } from '../../settings';
-import BaseScanner, {
+import animeList from '@server/api/animelist';
+import type { PlexLibraryItem, PlexMetadata } from '@server/api/plexapi';
+import PlexAPI from '@server/api/plexapi';
+import type { TmdbTvDetails } from '@server/api/themoviedb/interfaces';
+import { getRepository } from '@server/datasource';
+import { User } from '@server/entity/User';
+import cacheManager from '@server/lib/cache';
+import type {
   MediaIds,
   ProcessableSeason,
   RunnableScanner,
   StatusBase,
-} from '../baseScanner';
+} from '@server/lib/scanners/baseScanner';
+import BaseScanner from '@server/lib/scanners/baseScanner';
+import type { Library } from '@server/lib/settings';
+import { getSettings } from '@server/lib/settings';
+import { uniqWith } from 'lodash';
 
 const imdbRegex = new RegExp(/imdb:\/\/(tt[0-9]+)/);
 const tmdbRegex = new RegExp(/tmdb:\/\/([0-9]+)/);
@@ -59,8 +62,8 @@ class PlexScanner
     try {
       const userRepository = getRepository(User);
       const admin = await userRepository.findOne({
-        select: ['id', 'plexToken'],
-        order: { id: 'ASC' },
+        select: { id: true, plexToken: true },
+        where: { id: 1 },
       });
 
       if (!admin) {
@@ -141,7 +144,9 @@ class PlexScanner
         'info'
       );
     } catch (e) {
-      this.log('Scan interrupted', 'error', { errorMessage: e.message });
+      this.log('Scan interrupted', 'error', {
+        errorMessage: e.message,
+      });
     } finally {
       this.endRun(sessionId);
     }
@@ -369,7 +374,7 @@ class PlexScanner
         }
       });
 
-      // If we got an IMDb ID, but no TMDb ID, lookup the TMDb ID with the IMDb ID
+      // If we got an IMDb ID, but no TMDB ID, lookup the TMDB ID with the IMDb ID
       if (mediaIds.imdbId && !mediaIds.tmdbId) {
         const tmdbMedia = await this.tmdb.getMediaByImdbId({
           imdbId: mediaIds.imdbId,
@@ -390,7 +395,7 @@ class PlexScanner
         });
         mediaIds.tmdbId = tmdbMedia.id;
       }
-      // Check if the agent is TMDb
+      // Check if the agent is TMDB
     } else if (plexitem.guid.match(tmdbRegex)) {
       const tmdbMatch = plexitem.guid.match(tmdbRegex);
       if (tmdbMatch) {
@@ -409,7 +414,7 @@ class PlexScanner
         mediaIds.tvdbId = Number(matchedtvdb[1]);
         mediaIds.tmdbId = show.id;
       }
-      // Check if the agent (for shows) is TMDb
+      // Check if the agent (for shows) is TMDB
     } else if (plexitem.guid.match(tmdbShowRegex)) {
       const matchedtmdb = plexitem.guid.match(tmdbShowRegex);
       if (matchedtmdb) {
@@ -484,10 +489,10 @@ class PlexScanner
     }
 
     if (!mediaIds.tmdbId) {
-      throw new Error('Unable to find TMDb ID');
+      throw new Error('Unable to find TMDB ID');
     }
 
-    // We check above if we have the TMDb ID, so we can safely assert the type below
+    // We check above if we have the TMDB ID, so we can safely assert the type below
     return mediaIds as MediaIds;
   }
 
diff --git a/server/lib/scanners/radarr/index.ts b/server/lib/scanners/radarr/index.ts
index 5f47b9d9..bc299d7b 100644
--- a/server/lib/scanners/radarr/index.ts
+++ b/server/lib/scanners/radarr/index.ts
@@ -1,7 +1,13 @@
+import type { RadarrMovie } from '@server/api/servarr/radarr';
+import RadarrAPI from '@server/api/servarr/radarr';
+import type {
+  RunnableScanner,
+  StatusBase,
+} from '@server/lib/scanners/baseScanner';
+import BaseScanner from '@server/lib/scanners/baseScanner';
+import type { RadarrSettings } from '@server/lib/settings';
+import { getSettings } from '@server/lib/settings';
 import { uniqWith } from 'lodash';
-import RadarrAPI, { RadarrMovie } from '../../../api/servarr/radarr';
-import { getSettings, RadarrSettings } from '../../settings';
-import BaseScanner, { RunnableScanner, StatusBase } from '../baseScanner';
 
 type SyncStatus = StatusBase & {
   currentServer: RadarrSettings;
diff --git a/server/lib/scanners/sonarr/index.ts b/server/lib/scanners/sonarr/index.ts
index 044f74ec..3256c948 100644
--- a/server/lib/scanners/sonarr/index.ts
+++ b/server/lib/scanners/sonarr/index.ts
@@ -1,14 +1,17 @@
-import { uniqWith } from 'lodash';
-import { getRepository } from 'typeorm';
-import SonarrAPI, { SonarrSeries } from '../../../api/servarr/sonarr';
-import { TmdbTvDetails } from '../../../api/themoviedb/interfaces';
-import Media from '../../../entity/Media';
-import { getSettings, SonarrSettings } from '../../settings';
-import BaseScanner, {
+import type { SonarrSeries } from '@server/api/servarr/sonarr';
+import SonarrAPI from '@server/api/servarr/sonarr';
+import type { TmdbTvDetails } from '@server/api/themoviedb/interfaces';
+import { getRepository } from '@server/datasource';
+import Media from '@server/entity/Media';
+import type {
   ProcessableSeason,
   RunnableScanner,
   StatusBase,
-} from '../baseScanner';
+} from '@server/lib/scanners/baseScanner';
+import BaseScanner from '@server/lib/scanners/baseScanner';
+import type { SonarrSettings } from '@server/lib/settings';
+import { getSettings } from '@server/lib/settings';
+import { uniqWith } from 'lodash';
 
 type SyncStatus = StatusBase & {
   currentServer: SonarrSettings;
diff --git a/server/lib/search.ts b/server/lib/search.ts
index c625f512..be9ee3ae 100644
--- a/server/lib/search.ts
+++ b/server/lib/search.ts
@@ -1,5 +1,5 @@
-import TheMovieDb from '../api/themoviedb';
-import {
+import TheMovieDb from '@server/api/themoviedb';
+import type {
   TmdbMovieDetails,
   TmdbMovieResult,
   TmdbPersonDetails,
@@ -9,13 +9,17 @@ import {
   TmdbSearchTvResponse,
   TmdbTvDetails,
   TmdbTvResult,
-} from '../api/themoviedb/interfaces';
+} from '@server/api/themoviedb/interfaces';
 import {
   mapMovieDetailsToResult,
   mapPersonDetailsToResult,
   mapTvDetailsToResult,
-} from '../models/Search';
-import { isMovie, isMovieDetails, isTvDetails } from '../utils/typeHelpers';
+} from '@server/models/Search';
+import {
+  isMovie,
+  isMovieDetails,
+  isTvDetails,
+} from '@server/utils/typeHelpers';
 
 interface SearchProvider {
   pattern: RegExp;
diff --git a/server/lib/settings.ts b/server/lib/settings.ts
index 7a4f5f93..5a2d2b8a 100644
--- a/server/lib/settings.ts
+++ b/server/lib/settings.ts
@@ -243,6 +243,7 @@ interface JobSettings {
 export type JobId =
   | 'plex-recently-added-scan'
   | 'plex-full-scan'
+  | 'plex-watchlist-sync'
   | 'radarr-scan'
   | 'sonarr-scan'
   | 'download-sync'
@@ -398,6 +399,9 @@ class Settings {
         'plex-full-scan': {
           schedule: '0 0 3 * * *',
         },
+        'plex-watchlist-sync': {
+          schedule: '0 */10 * * * *',
+        },
         'radarr-scan': {
           schedule: '0 0 4 * * *',
         },
diff --git a/server/lib/watchlistsync.ts b/server/lib/watchlistsync.ts
new file mode 100644
index 00000000..46147f3f
--- /dev/null
+++ b/server/lib/watchlistsync.ts
@@ -0,0 +1,163 @@
+import PlexTvAPI from '@server/api/plextv';
+import { MediaStatus, MediaType } from '@server/constants/media';
+import { getRepository } from '@server/datasource';
+import Media from '@server/entity/Media';
+import {
+  DuplicateMediaRequestError,
+  MediaRequest,
+  NoSeasonsAvailableError,
+  QuotaRestrictedError,
+  RequestPermissionError,
+} from '@server/entity/MediaRequest';
+import { User } from '@server/entity/User';
+import logger from '@server/logger';
+import { Permission } from './permissions';
+
+class WatchlistSync {
+  public async syncWatchlist() {
+    const userRepository = getRepository(User);
+
+    // Get users who actually have plex tokens
+    const users = await userRepository
+      .createQueryBuilder('user')
+      .addSelect('user.plexToken')
+      .leftJoinAndSelect('user.settings', 'settings')
+      .where("user.plexToken != ''")
+      .getMany();
+
+    for (const user of users) {
+      await this.syncUserWatchlist(user);
+    }
+  }
+
+  private async syncUserWatchlist(user: User) {
+    if (!user.plexToken) {
+      logger.warn('Skipping user watchlist sync for user without plex token', {
+        label: 'Plex Watchlist Sync',
+        user: user.displayName,
+      });
+      return;
+    }
+
+    if (
+      !user.hasPermission(
+        [
+          Permission.AUTO_REQUEST,
+          Permission.AUTO_REQUEST_MOVIE,
+          Permission.AUTO_APPROVE_TV,
+        ],
+        { type: 'or' }
+      )
+    ) {
+      return;
+    }
+
+    if (
+      !user.settings?.watchlistSyncMovies &&
+      !user.settings?.watchlistSyncTv
+    ) {
+      // Skip sync if user settings have it disabled
+      return;
+    }
+
+    const plexTvApi = new PlexTvAPI(user.plexToken);
+
+    const response = await plexTvApi.getWatchlist({ size: 200 });
+
+    const mediaItems = await Media.getRelatedMedia(
+      response.items.map((i) => i.tmdbId)
+    );
+
+    const unavailableItems = response.items.filter(
+      // If we can find watchlist items in our database that are also available, we should exclude them
+      (i) =>
+        !mediaItems.find(
+          (m) =>
+            m.tmdbId === i.tmdbId &&
+            ((m.status !== MediaStatus.UNKNOWN && m.mediaType === 'movie') ||
+              (m.mediaType === 'tv' && m.status === MediaStatus.AVAILABLE))
+        )
+    );
+
+    await Promise.all(
+      unavailableItems.map(async (mediaItem) => {
+        try {
+          logger.info("Creating media request from user's Plex Watchlist", {
+            label: 'Watchlist Sync',
+            userId: user.id,
+            mediaTitle: mediaItem.title,
+          });
+
+          if (mediaItem.type === 'show' && !mediaItem.tvdbId) {
+            throw new Error('Missing TVDB ID from Plex Metadata');
+          }
+
+          // Check if they have auto-request permissons and watchlist sync
+          // enabled for the media type
+          if (
+            ((!user.hasPermission(
+              [Permission.AUTO_REQUEST, Permission.AUTO_REQUEST_MOVIE],
+              { type: 'or' }
+            ) ||
+              !user.settings?.watchlistSyncMovies) &&
+              mediaItem.type === 'movie') ||
+            ((!user.hasPermission(
+              [Permission.AUTO_REQUEST, Permission.AUTO_REQUEST_TV],
+              { type: 'or' }
+            ) ||
+              !user.settings?.watchlistSyncTv) &&
+              mediaItem.type === 'show')
+          ) {
+            return;
+          }
+
+          await MediaRequest.request(
+            {
+              mediaId: mediaItem.tmdbId,
+              mediaType:
+                mediaItem.type === 'show' ? MediaType.TV : MediaType.MOVIE,
+              seasons: mediaItem.type === 'show' ? 'all' : undefined,
+              tvdbId: mediaItem.tvdbId,
+              is4k: false,
+            },
+            user,
+            { isAutoRequest: true }
+          );
+        } catch (e) {
+          if (!(e instanceof Error)) {
+            return;
+          }
+
+          switch (e.constructor) {
+            // During watchlist sync, these errors aren't necessarily
+            // a problem with Overseerr. Since we are auto syncing these constantly, it's
+            // possible they are unexpectedly at their quota limit, for example. So we'll
+            // instead log these as debug messages.
+            case RequestPermissionError:
+            case DuplicateMediaRequestError:
+            case QuotaRestrictedError:
+            case NoSeasonsAvailableError:
+              logger.debug('Failed to create media request from watchlist', {
+                label: 'Watchlist Sync',
+                userId: user.id,
+                mediaTitle: mediaItem.title,
+                errorMessage: e.message,
+              });
+              break;
+            default:
+              logger.error('Failed to create media request from watchlist', {
+                label: 'Watchlist Sync',
+                userId: user.id,
+                mediaTitle: mediaItem.title,
+                errorMessage: e.message,
+              });
+          }
+        }
+      })
+    );
+  }
+}
+
+const watchlistSync = new WatchlistSync();
+
+export default watchlistSync;
diff --git a/server/logger.ts b/server/logger.ts
index 4f736e4a..d5809a0e 100644
--- a/server/logger.ts
+++ b/server/logger.ts
@@ -26,7 +26,7 @@ const hformat = winston.format.printf(
 );
 
 const logger = winston.createLogger({
-  level: process.env.LOG_LEVEL || 'debug',
+  level: process.env.LOG_LEVEL?.toLowerCase() || 'debug',
   format: winston.format.combine(
     winston.format.splat(),
     winston.format.timestamp(),
diff --git a/server/middleware/auth.ts b/server/middleware/auth.ts
index 68869222..326d460d 100644
--- a/server/middleware/auth.ts
+++ b/server/middleware/auth.ts
@@ -1,11 +1,14 @@
-import { getRepository } from 'typeorm';
-import { User } from '../entity/User';
-import { Permission, PermissionCheckOptions } from '../lib/permissions';
-import { getSettings } from '../lib/settings';
+import { getRepository } from '@server/datasource';
+import { User } from '@server/entity/User';
+import type {
+  Permission,
+  PermissionCheckOptions,
+} from '@server/lib/permissions';
+import { getSettings } from '@server/lib/settings';
 
 export const checkUser: Middleware = async (req, _res, next) => {
   const settings = getSettings();
-  let user: User | undefined;
+  let user: User | undefined | null;
 
   if (req.header('X-API-Key') === settings.main.apiKey) {
     const userRepository = getRepository(User);
diff --git a/server/migration/1603944374840-InitialMigration.ts b/server/migration/1603944374840-InitialMigration.ts
index 73640565..db71471a 100644
--- a/server/migration/1603944374840-InitialMigration.ts
+++ b/server/migration/1603944374840-InitialMigration.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class InitialMigration1603944374840 implements MigrationInterface {
   name = 'InitialMigration1603944374840';
diff --git a/server/migration/1605085519544-SeasonStatus.ts b/server/migration/1605085519544-SeasonStatus.ts
index bcff6f60..059c6bf5 100644
--- a/server/migration/1605085519544-SeasonStatus.ts
+++ b/server/migration/1605085519544-SeasonStatus.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class SeasonStatus1605085519544 implements MigrationInterface {
   name = 'SeasonStatus1605085519544';
diff --git a/server/migration/1606730060700-CascadeMigration.ts b/server/migration/1606730060700-CascadeMigration.ts
index 341bc00b..3b1ae070 100644
--- a/server/migration/1606730060700-CascadeMigration.ts
+++ b/server/migration/1606730060700-CascadeMigration.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class CascadeMigration1606730060700 implements MigrationInterface {
   name = 'CascadeMigration1606730060700';
diff --git a/server/migration/1607928251245-DropImdbIdConstraint.ts b/server/migration/1607928251245-DropImdbIdConstraint.ts
index 97baa861..f602ea7f 100644
--- a/server/migration/1607928251245-DropImdbIdConstraint.ts
+++ b/server/migration/1607928251245-DropImdbIdConstraint.ts
@@ -1,4 +1,5 @@
-import { MigrationInterface, QueryRunner, TableUnique } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
+import { TableUnique } from 'typeorm';
 
 export class DropImdbIdConstraint1607928251245 implements MigrationInterface {
   public async up(queryRunner: QueryRunner): Promise<void> {
diff --git a/server/migration/1608217312474-AddUserRequestDeleteCascades.ts b/server/migration/1608217312474-AddUserRequestDeleteCascades.ts
index e2aa8865..622a2c90 100644
--- a/server/migration/1608217312474-AddUserRequestDeleteCascades.ts
+++ b/server/migration/1608217312474-AddUserRequestDeleteCascades.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class AddUserRequestDeleteCascades1608219049304
   implements MigrationInterface
diff --git a/server/migration/1608477467935-AddLastSeasonChangeMedia.ts b/server/migration/1608477467935-AddLastSeasonChangeMedia.ts
index fba7af7f..e5ab0250 100644
--- a/server/migration/1608477467935-AddLastSeasonChangeMedia.ts
+++ b/server/migration/1608477467935-AddLastSeasonChangeMedia.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class AddLastSeasonChangeMedia1608477467935
   implements MigrationInterface
diff --git a/server/migration/1608477467936-ForceDropImdbUniqueConstraint.ts b/server/migration/1608477467936-ForceDropImdbUniqueConstraint.ts
index 6a109e4d..d54c450e 100644
--- a/server/migration/1608477467936-ForceDropImdbUniqueConstraint.ts
+++ b/server/migration/1608477467936-ForceDropImdbUniqueConstraint.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class ForceDropImdbUniqueConstraint1608477467935
   implements MigrationInterface
diff --git a/server/migration/1609236552057-RemoveTmdbIdUniqueConstraint.ts b/server/migration/1609236552057-RemoveTmdbIdUniqueConstraint.ts
index 2cd5415e..50056892 100644
--- a/server/migration/1609236552057-RemoveTmdbIdUniqueConstraint.ts
+++ b/server/migration/1609236552057-RemoveTmdbIdUniqueConstraint.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class RemoveTmdbIdUniqueConstraint1609236552057
   implements MigrationInterface
diff --git a/server/migration/1610070934506-LocalUsers.ts b/server/migration/1610070934506-LocalUsers.ts
index 0ece00f4..88b0ae60 100644
--- a/server/migration/1610070934506-LocalUsers.ts
+++ b/server/migration/1610070934506-LocalUsers.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class LocalUsers1610070934506 implements MigrationInterface {
   name = 'LocalUsers1610070934506';
diff --git a/server/migration/1610370640747-Add4kStatusFields.ts b/server/migration/1610370640747-Add4kStatusFields.ts
index a313bf13..5502b9c0 100644
--- a/server/migration/1610370640747-Add4kStatusFields.ts
+++ b/server/migration/1610370640747-Add4kStatusFields.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class Add4kStatusFields1610370640747 implements MigrationInterface {
   name = 'Add4kStatusFields1610370640747';
diff --git a/server/migration/1610522845513-AddMediaAddedFieldToMedia.ts b/server/migration/1610522845513-AddMediaAddedFieldToMedia.ts
index 25e42a74..d6574d39 100644
--- a/server/migration/1610522845513-AddMediaAddedFieldToMedia.ts
+++ b/server/migration/1610522845513-AddMediaAddedFieldToMedia.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class AddMediaAddedFieldToMedia1610522845513
   implements MigrationInterface
diff --git a/server/migration/1611508672722-AddDisplayNameToUser.ts b/server/migration/1611508672722-AddDisplayNameToUser.ts
index cacea059..6a36f29a 100644
--- a/server/migration/1611508672722-AddDisplayNameToUser.ts
+++ b/server/migration/1611508672722-AddDisplayNameToUser.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class AddDisplayNameToUser1611508672722 implements MigrationInterface {
   name = 'AddDisplayNameToUser1611508672722';
diff --git a/server/migration/1611757511674-SonarrRadarrSyncServiceFields.ts b/server/migration/1611757511674-SonarrRadarrSyncServiceFields.ts
index 355384a0..5a5b6553 100644
--- a/server/migration/1611757511674-SonarrRadarrSyncServiceFields.ts
+++ b/server/migration/1611757511674-SonarrRadarrSyncServiceFields.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class SonarrRadarrSyncServiceFields1611757511674
   implements MigrationInterface
diff --git a/server/migration/1611801511397-AddRatingKeysToMedia.ts b/server/migration/1611801511397-AddRatingKeysToMedia.ts
index f9865c8f..92ab4d4b 100644
--- a/server/migration/1611801511397-AddRatingKeysToMedia.ts
+++ b/server/migration/1611801511397-AddRatingKeysToMedia.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class AddRatingKeysToMedia1611801511397 implements MigrationInterface {
   name = 'AddRatingKeysToMedia1611801511397';
diff --git a/server/migration/1612482778137-AddResetPasswordGuidAndExpiryDate.ts b/server/migration/1612482778137-AddResetPasswordGuidAndExpiryDate.ts
index 7d191d10..55a20a39 100644
--- a/server/migration/1612482778137-AddResetPasswordGuidAndExpiryDate.ts
+++ b/server/migration/1612482778137-AddResetPasswordGuidAndExpiryDate.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class AddResetPasswordGuidAndExpiryDate1612482778137
   implements MigrationInterface
diff --git a/server/migration/1612571545781-AddLanguageProfileId.ts b/server/migration/1612571545781-AddLanguageProfileId.ts
index fa89d81b..7694f4e4 100644
--- a/server/migration/1612571545781-AddLanguageProfileId.ts
+++ b/server/migration/1612571545781-AddLanguageProfileId.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class AddLanguageProfileId1612571545781 implements MigrationInterface {
   name = 'AddLanguageProfileId1612571545781';
diff --git a/server/migration/1613615266968-CreateUserSettings.ts b/server/migration/1613615266968-CreateUserSettings.ts
index 4d4a973e..fbe85339 100644
--- a/server/migration/1613615266968-CreateUserSettings.ts
+++ b/server/migration/1613615266968-CreateUserSettings.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class CreateUserSettings1613615266968 implements MigrationInterface {
   name = 'CreateUserSettings1613615266968';
diff --git a/server/migration/1613955393450-UpdateUserSettingsRegions.ts b/server/migration/1613955393450-UpdateUserSettingsRegions.ts
index d33df4ee..69060a0c 100644
--- a/server/migration/1613955393450-UpdateUserSettingsRegions.ts
+++ b/server/migration/1613955393450-UpdateUserSettingsRegions.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class UpdateUserSettingsRegions1613955393450
   implements MigrationInterface
diff --git a/server/migration/1614334195680-AddTelegramSettingsToUserSettings.ts b/server/migration/1614334195680-AddTelegramSettingsToUserSettings.ts
index 5e480d48..6e2598ab 100644
--- a/server/migration/1614334195680-AddTelegramSettingsToUserSettings.ts
+++ b/server/migration/1614334195680-AddTelegramSettingsToUserSettings.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class AddTelegramSettingsToUserSettings1614334195680
   implements MigrationInterface
diff --git a/server/migration/1615333940450-AddPGPToUserSettings.ts b/server/migration/1615333940450-AddPGPToUserSettings.ts
index b88e0dca..6940d4ad 100644
--- a/server/migration/1615333940450-AddPGPToUserSettings.ts
+++ b/server/migration/1615333940450-AddPGPToUserSettings.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class AddPGPToUserSettings1615333940450 implements MigrationInterface {
   name = 'AddPGPToUserSettings1615333940450';
diff --git a/server/migration/1616576677254-AddUserQuotaFields.ts b/server/migration/1616576677254-AddUserQuotaFields.ts
index 44947bab..e20c3d72 100644
--- a/server/migration/1616576677254-AddUserQuotaFields.ts
+++ b/server/migration/1616576677254-AddUserQuotaFields.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class AddUserQuotaFields1616576677254 implements MigrationInterface {
   name = 'AddUserQuotaFields1616576677254';
diff --git a/server/migration/1617624225464-CreateTagsFieldonMediaRequest.ts b/server/migration/1617624225464-CreateTagsFieldonMediaRequest.ts
index d498a8b1..9e676182 100644
--- a/server/migration/1617624225464-CreateTagsFieldonMediaRequest.ts
+++ b/server/migration/1617624225464-CreateTagsFieldonMediaRequest.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class CreateTagsFieldonMediaRequest1617624225464
   implements MigrationInterface
diff --git a/server/migration/1617730837489-AddUserSettingsNotificationAgentsField.ts b/server/migration/1617730837489-AddUserSettingsNotificationAgentsField.ts
index 79cd061b..9dd9288e 100644
--- a/server/migration/1617730837489-AddUserSettingsNotificationAgentsField.ts
+++ b/server/migration/1617730837489-AddUserSettingsNotificationAgentsField.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class AddUserSettingsNotificationAgentsField1617730837489
   implements MigrationInterface
diff --git a/server/migration/1618912653565-CreateUserPushSubscriptions.ts b/server/migration/1618912653565-CreateUserPushSubscriptions.ts
index 539221d1..97070599 100644
--- a/server/migration/1618912653565-CreateUserPushSubscriptions.ts
+++ b/server/migration/1618912653565-CreateUserPushSubscriptions.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class CreateUserPushSubscriptions1618912653565
   implements MigrationInterface
diff --git a/server/migration/1619239659754-AddUserSettingsLocale.ts b/server/migration/1619239659754-AddUserSettingsLocale.ts
index 9842bca7..ba182b03 100644
--- a/server/migration/1619239659754-AddUserSettingsLocale.ts
+++ b/server/migration/1619239659754-AddUserSettingsLocale.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class AddUserSettingsLocale1619239659754 implements MigrationInterface {
   name = 'AddUserSettingsLocale1619239659754';
diff --git a/server/migration/1619339817343-AddUserSettingsNotificationTypes.ts b/server/migration/1619339817343-AddUserSettingsNotificationTypes.ts
index cccdae2f..50de959b 100644
--- a/server/migration/1619339817343-AddUserSettingsNotificationTypes.ts
+++ b/server/migration/1619339817343-AddUserSettingsNotificationTypes.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class AddUserSettingsNotificationTypes1619339817343
   implements MigrationInterface
diff --git a/server/migration/1634904083966-AddIssues.ts b/server/migration/1634904083966-AddIssues.ts
index 0c6116f9..ebcf8d89 100644
--- a/server/migration/1634904083966-AddIssues.ts
+++ b/server/migration/1634904083966-AddIssues.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class AddIssues1634904083966 implements MigrationInterface {
   name = 'AddIssues1634904083966';
diff --git a/server/migration/1635079863457-AddPushbulletPushoverUserSettings.ts b/server/migration/1635079863457-AddPushbulletPushoverUserSettings.ts
index 8934866f..c29cef6d 100644
--- a/server/migration/1635079863457-AddPushbulletPushoverUserSettings.ts
+++ b/server/migration/1635079863457-AddPushbulletPushoverUserSettings.ts
@@ -1,4 +1,4 @@
-import { MigrationInterface, QueryRunner } from 'typeorm';
+import type { MigrationInterface, QueryRunner } from 'typeorm';
 
 export class AddPushbulletPushoverUserSettings1635079863457
   implements MigrationInterface
diff --git a/server/migration/1660632269368-AddWatchlistSyncUserSetting.ts b/server/migration/1660632269368-AddWatchlistSyncUserSetting.ts
new file mode 100644
index 00000000..c0d0e947
--- /dev/null
+++ b/server/migration/1660632269368-AddWatchlistSyncUserSetting.ts
@@ -0,0 +1,33 @@
+import type { MigrationInterface, QueryRunner } from 'typeorm';
+
+export class AddWatchlistSyncUserSetting1660632269368
+  implements MigrationInterface
+{
+  name = 'AddWatchlistSyncUserSetting1660632269368';
+
+  public async up(queryRunner: QueryRunner): Promise<void> {
+    await queryRunner.query(
+      `CREATE TABLE "temporary_user_settings" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "notificationTypes" text, "discordId" varchar, "userId" integer, "region" varchar, "originalLanguage" varchar, "telegramChatId" varchar, "telegramSendSilently" boolean, "pgpKey" varchar, "locale" varchar NOT NULL DEFAULT (''), "pushbulletAccessToken" varchar, "pushoverApplicationToken" varchar, "pushoverUserKey" varchar, "watchlistSyncMovies" boolean, "watchlistSyncTv" boolean, CONSTRAINT "UQ_986a2b6d3c05eb4091bb8066f78" UNIQUE ("userId"), CONSTRAINT "FK_986a2b6d3c05eb4091bb8066f78" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`
+    );
+    await queryRunner.query(
+      `INSERT INTO "temporary_user_settings"("id", "notificationTypes", "discordId", "userId", "region", "originalLanguage", "telegramChatId", "telegramSendSilently", "pgpKey", "locale", "pushbulletAccessToken", "pushoverApplicationToken", "pushoverUserKey") SELECT "id", "notificationTypes", "discordId", "userId", "region", "originalLanguage", "telegramChatId", "telegramSendSilently", "pgpKey", "locale", "pushbulletAccessToken", "pushoverApplicationToken", "pushoverUserKey" FROM "user_settings"`
+    );
+    await queryRunner.query(`DROP TABLE "user_settings"`);
+    await queryRunner.query(
+      `ALTER TABLE "temporary_user_settings" RENAME TO "user_settings"`
+    );
+  }
+
+  public async down(queryRunner: QueryRunner): Promise<void> {
+    await queryRunner.query(
+      `ALTER TABLE "user_settings" RENAME TO "temporary_user_settings"`
+    );
+    await queryRunner.query(
+      `CREATE TABLE "user_settings" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "notificationTypes" text, "discordId" varchar, "userId" integer, "region" varchar, "originalLanguage" varchar, "telegramChatId" varchar, "telegramSendSilently" boolean, "pgpKey" varchar, "locale" varchar NOT NULL DEFAULT (''), "pushbulletAccessToken" varchar, "pushoverApplicationToken" varchar, "pushoverUserKey" varchar, CONSTRAINT "UQ_986a2b6d3c05eb4091bb8066f78" UNIQUE ("userId"), CONSTRAINT "FK_986a2b6d3c05eb4091bb8066f78" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`
+    );
+    await queryRunner.query(
+      `INSERT INTO "user_settings"("id", "notificationTypes", "discordId", "userId", "region", "originalLanguage", "telegramChatId", "telegramSendSilently", "pgpKey", "locale", "pushbulletAccessToken", "pushoverApplicationToken", "pushoverUserKey") SELECT "id", "notificationTypes", "discordId", "userId", "region", "originalLanguage", "telegramChatId", "telegramSendSilently", "pgpKey", "locale", "pushbulletAccessToken", "pushoverApplicationToken", "pushoverUserKey" FROM "temporary_user_settings"`
+    );
+    await queryRunner.query(`DROP TABLE "temporary_user_settings"`);
+  }
+}
diff --git a/server/migration/1660714479373-AddMediaRequestIsAutoRequestedField.ts b/server/migration/1660714479373-AddMediaRequestIsAutoRequestedField.ts
new file mode 100644
index 00000000..8580bb4e
--- /dev/null
+++ b/server/migration/1660714479373-AddMediaRequestIsAutoRequestedField.ts
@@ -0,0 +1,33 @@
+import type { MigrationInterface, QueryRunner } from 'typeorm';
+
+export class AddMediaRequestIsAutoRequestedField1660714479373
+  implements MigrationInterface
+{
+  name = 'AddMediaRequestIsAutoRequestedField1660714479373';
+
+  public async up(queryRunner: QueryRunner): Promise<void> {
+    await queryRunner.query(
+      `CREATE TABLE "temporary_media_request" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "status" integer NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "type" varchar NOT NULL, "mediaId" integer, "requestedById" integer, "modifiedById" integer, "is4k" boolean NOT NULL DEFAULT (0), "serverId" integer, "profileId" integer, "rootFolder" varchar, "languageProfileId" integer, "tags" text, "isAutoRequest" boolean NOT NULL DEFAULT (0), CONSTRAINT "FK_a1aa713f41c99e9d10c48da75a0" FOREIGN KEY ("mediaId") REFERENCES "media" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_6997bee94720f1ecb7f31137095" FOREIGN KEY ("requestedById") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_f4fc4efa14c3ba2b29c4525fa15" FOREIGN KEY ("modifiedById") REFERENCES "user" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)`
+    );
+    await queryRunner.query(
+      `INSERT INTO "temporary_media_request"("id", "status", "createdAt", "updatedAt", "type", "mediaId", "requestedById", "modifiedById", "is4k", "serverId", "profileId", "rootFolder", "languageProfileId", "tags") SELECT "id", "status", "createdAt", "updatedAt", "type", "mediaId", "requestedById", "modifiedById", "is4k", "serverId", "profileId", "rootFolder", "languageProfileId", "tags" FROM "media_request"`
+    );
+    await queryRunner.query(`DROP TABLE "media_request"`);
+    await queryRunner.query(
+      `ALTER TABLE "temporary_media_request" RENAME TO "media_request"`
+    );
+  }
+
+  public async down(queryRunner: QueryRunner): Promise<void> {
+    await queryRunner.query(
+      `ALTER TABLE "media_request" RENAME TO "temporary_media_request"`
+    );
+    await queryRunner.query(
+      `CREATE TABLE "media_request" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "status" integer NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "type" varchar NOT NULL, "mediaId" integer, "requestedById" integer, "modifiedById" integer, "is4k" boolean NOT NULL DEFAULT (0), "serverId" integer, "profileId" integer, "rootFolder" varchar, "languageProfileId" integer, "tags" text, CONSTRAINT "FK_a1aa713f41c99e9d10c48da75a0" FOREIGN KEY ("mediaId") REFERENCES "media" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_6997bee94720f1ecb7f31137095" FOREIGN KEY ("requestedById") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION, CONSTRAINT "FK_f4fc4efa14c3ba2b29c4525fa15" FOREIGN KEY ("modifiedById") REFERENCES "user" ("id") ON DELETE SET NULL ON UPDATE NO ACTION)`
+    );
+    await queryRunner.query(
+      `INSERT INTO "media_request"("id", "status", "createdAt", "updatedAt", "type", "mediaId", "requestedById", "modifiedById", "is4k", "serverId", "profileId", "rootFolder", "languageProfileId", "tags") SELECT "id", "status", "createdAt", "updatedAt", "type", "mediaId", "requestedById", "modifiedById", "is4k", "serverId", "profileId", "rootFolder", "languageProfileId", "tags" FROM "temporary_media_request"`
+    );
+    await queryRunner.query(`DROP TABLE "temporary_media_request"`);
+  }
+}
diff --git a/server/models/Collection.ts b/server/models/Collection.ts
index 9cc4f378..20a3c715 100644
--- a/server/models/Collection.ts
+++ b/server/models/Collection.ts
@@ -1,8 +1,9 @@
+import type { TmdbCollection } from '@server/api/themoviedb/interfaces';
+import { MediaType } from '@server/constants/media';
+import type Media from '@server/entity/Media';
 import { sortBy } from 'lodash';
-import type { TmdbCollection } from '../api/themoviedb/interfaces';
-import { MediaType } from '../constants/media';
-import Media from '../entity/Media';
-import { mapMovieResult, MovieResult } from './Search';
+import type { MovieResult } from './Search';
+import { mapMovieResult } from './Search';
 
 export interface Collection {
   id: number;
diff --git a/server/models/Movie.ts b/server/models/Movie.ts
index ff8a96a4..3c4686b2 100644
--- a/server/models/Movie.ts
+++ b/server/models/Movie.ts
@@ -2,20 +2,22 @@ import type {
   TmdbMovieDetails,
   TmdbMovieReleaseResult,
   TmdbProductionCompany,
-} from '../api/themoviedb/interfaces';
-import Media from '../entity/Media';
-import {
+} from '@server/api/themoviedb/interfaces';
+import type Media from '@server/entity/Media';
+import type {
   Cast,
   Crew,
   ExternalIds,
   Genre,
+  ProductionCompany,
+  WatchProviders,
+} from './common';
+import {
   mapCast,
   mapCrew,
   mapExternalIds,
   mapVideos,
   mapWatchProviders,
-  ProductionCompany,
-  WatchProviders,
 } from './common';
 
 export interface Video {
diff --git a/server/models/Person.ts b/server/models/Person.ts
index 087ab1c7..998585ee 100644
--- a/server/models/Person.ts
+++ b/server/models/Person.ts
@@ -2,8 +2,8 @@ import type {
   TmdbPersonCreditCast,
   TmdbPersonCreditCrew,
   TmdbPersonDetails,
-} from '../api/themoviedb/interfaces';
-import Media from '../entity/Media';
+} from '@server/api/themoviedb/interfaces';
+import type Media from '@server/entity/Media';
 
 export interface PersonDetails {
   id: number;
diff --git a/server/models/Search.ts b/server/models/Search.ts
index 73427a37..6ab696fe 100644
--- a/server/models/Search.ts
+++ b/server/models/Search.ts
@@ -5,9 +5,9 @@ import type {
   TmdbPersonResult,
   TmdbTvDetails,
   TmdbTvResult,
-} from '../api/themoviedb/interfaces';
-import { MediaType as MainMediaType } from '../constants/media';
-import Media from '../entity/Media';
+} from '@server/api/themoviedb/interfaces';
+import { MediaType as MainMediaType } from '@server/constants/media';
+import type Media from '@server/entity/Media';
 
 export type MediaType = 'tv' | 'movie' | 'person';
 
diff --git a/server/models/Tv.ts b/server/models/Tv.ts
index b596b1d2..7f809cbf 100644
--- a/server/models/Tv.ts
+++ b/server/models/Tv.ts
@@ -5,24 +5,26 @@ import type {
   TmdbTvEpisodeResult,
   TmdbTvRatingResult,
   TmdbTvSeasonResult,
-} from '../api/themoviedb/interfaces';
-import type Media from '../entity/Media';
-import {
+} from '@server/api/themoviedb/interfaces';
+import type Media from '@server/entity/Media';
+import type {
   Cast,
   Crew,
   ExternalIds,
   Genre,
   Keyword,
+  ProductionCompany,
+  TvNetwork,
+  WatchProviders,
+} from './common';
+import {
   mapAggregateCast,
   mapCrew,
   mapExternalIds,
   mapVideos,
   mapWatchProviders,
-  ProductionCompany,
-  TvNetwork,
-  WatchProviders,
 } from './common';
-import { Video } from './Movie';
+import type { Video } from './Movie';
 
 interface Episode {
   id: number;
diff --git a/server/models/common.ts b/server/models/common.ts
index 49e2305c..30b40d98 100644
--- a/server/models/common.ts
+++ b/server/models/common.ts
@@ -7,8 +7,8 @@ import type {
   TmdbVideoResult,
   TmdbWatchProviderDetails,
   TmdbWatchProviders,
-} from '../api/themoviedb/interfaces';
-import { Video } from '../models/Movie';
+} from '@server/api/themoviedb/interfaces';
+import type { Video } from '@server/models/Movie';
 
 export interface ProductionCompany {
   id: number;
diff --git a/server/routes/auth.ts b/server/routes/auth.ts
index b6394d17..cf4a4e86 100644
--- a/server/routes/auth.ts
+++ b/server/routes/auth.ts
@@ -1,12 +1,12 @@
+import PlexTvAPI from '@server/api/plextv';
+import { UserType } from '@server/constants/user';
+import { getRepository } from '@server/datasource';
+import { User } from '@server/entity/User';
+import { Permission } from '@server/lib/permissions';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
+import { isAuthenticated } from '@server/middleware/auth';
 import { Router } from 'express';
-import { getRepository } from 'typeorm';
-import PlexTvAPI from '../api/plextv';
-import { UserType } from '../constants/user';
-import { User } from '../entity/User';
-import { Permission } from '../lib/permissions';
-import { getSettings } from '../lib/settings';
-import logger from '../logger';
-import { isAuthenticated } from '../middleware/auth';
 
 const authRoutes = Router();
 
@@ -64,8 +64,8 @@ authRoutes.post('/plex', async (req, res, next) => {
       await userRepository.save(user);
     } else {
       const mainUser = await userRepository.findOneOrFail({
-        select: ['id', 'plexToken', 'plexId'],
-        order: { id: 'ASC' },
+        select: { id: true, plexToken: true, plexId: true },
+        where: { id: 1 },
       });
       const mainPlexTv = new PlexTvAPI(mainUser.plexToken ?? '');
 
@@ -204,8 +204,8 @@ authRoutes.post('/local', async (req, res, next) => {
     }
 
     const mainUser = await userRepository.findOneOrFail({
-      select: ['id', 'plexToken', 'plexId'],
-      order: { id: 'ASC' },
+      select: { id: true, plexToken: true, plexId: true },
+      where: { id: 1 },
     });
     const mainPlexTv = new PlexTvAPI(mainUser.plexToken ?? '');
 
diff --git a/server/routes/collection.ts b/server/routes/collection.ts
index aa894873..d58b0357 100644
--- a/server/routes/collection.ts
+++ b/server/routes/collection.ts
@@ -1,8 +1,8 @@
+import TheMovieDb from '@server/api/themoviedb';
+import Media from '@server/entity/Media';
+import logger from '@server/logger';
+import { mapCollection } from '@server/models/Collection';
 import { Router } from 'express';
-import TheMovieDb from '../api/themoviedb';
-import Media from '../entity/Media';
-import logger from '../logger';
-import { mapCollection } from '../models/Collection';
 
 const collectionRoutes = Router();
 
diff --git a/server/routes/discover.ts b/server/routes/discover.ts
index ea78bf03..b39a8332 100644
--- a/server/routes/discover.ts
+++ b/server/routes/discover.ts
@@ -1,16 +1,25 @@
+import PlexTvAPI from '@server/api/plextv';
+import TheMovieDb from '@server/api/themoviedb';
+import { MediaType } from '@server/constants/media';
+import { getRepository } from '@server/datasource';
+import Media from '@server/entity/Media';
+import { User } from '@server/entity/User';
+import type {
+  GenreSliderItem,
+  WatchlistResponse,
+} from '@server/interfaces/api/discoverInterfaces';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
+import { mapProductionCompany } from '@server/models/Movie';
+import {
+  mapMovieResult,
+  mapPersonResult,
+  mapTvResult,
+} from '@server/models/Search';
+import { mapNetwork } from '@server/models/Tv';
+import { isMovie, isPerson } from '@server/utils/typeHelpers';
 import { Router } from 'express';
 import { sortBy } from 'lodash';
-import TheMovieDb from '../api/themoviedb';
-import { MediaType } from '../constants/media';
-import Media from '../entity/Media';
-import { User } from '../entity/User';
-import { GenreSliderItem } from '../interfaces/api/discoverInterfaces';
-import { getSettings } from '../lib/settings';
-import logger from '../logger';
-import { mapProductionCompany } from '../models/Movie';
-import { mapMovieResult, mapPersonResult, mapTvResult } from '../models/Search';
-import { mapNetwork } from '../models/Tv';
-import { isMovie, isPerson } from '../utils/typeHelpers';
 
 export const createTmdbWithRegionLanguage = (user?: User): TheMovieDb => {
   const settings = getSettings();
@@ -704,4 +713,45 @@ discoverRoutes.get<{ language: string }, GenreSliderItem[]>(
   }
 );
 
+discoverRoutes.get<{ page?: number }, WatchlistResponse>(
+  '/watchlist',
+  async (req, res) => {
+    const userRepository = getRepository(User);
+    const itemsPerPage = 20;
+    const page = req.params.page ?? 1;
+    const offset = (page - 1) * itemsPerPage;
+
+    const activeUser = await userRepository.findOne({
+      where: { id: req.user?.id },
+      select: ['id', 'plexToken'],
+    });
+
+    if (!activeUser?.plexToken) {
+      // We will just return an empty array if the user has no Plex token
+      return res.json({
+        page: 1,
+        totalPages: 1,
+        totalResults: 0,
+        results: [],
+      });
+    }
+
+    const plexTV = new PlexTvAPI(activeUser.plexToken);
+
+    const watchlist = await plexTV.getWatchlist({ offset });
+
+    return res.json({
+      page,
+      totalPages: Math.ceil(watchlist.size / itemsPerPage),
+      totalResults: watchlist.size,
+      results: watchlist.items.map((item) => ({
+        ratingKey: item.ratingKey,
+        title: item.title,
+        mediaType: item.type === 'show' ? 'tv' : 'movie',
+        tmdbId: item.tmdbId,
+      })),
+    });
+  }
+);
+
 export default discoverRoutes;
diff --git a/server/routes/index.ts b/server/routes/index.ts
index e2866638..9561e171 100644
--- a/server/routes/index.ts
+++ b/server/routes/index.ts
@@ -1,17 +1,22 @@
+import GithubAPI from '@server/api/github';
+import TheMovieDb from '@server/api/themoviedb';
+import type {
+  TmdbMovieResult,
+  TmdbTvResult,
+} from '@server/api/themoviedb/interfaces';
+import type { StatusResponse } from '@server/interfaces/api/settingsInterfaces';
+import { Permission } from '@server/lib/permissions';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
+import { checkUser, isAuthenticated } from '@server/middleware/auth';
+import { mapProductionCompany } from '@server/models/Movie';
+import { mapNetwork } from '@server/models/Tv';
+import settingsRoutes from '@server/routes/settings';
+import { appDataPath, appDataStatus } from '@server/utils/appDataVolume';
+import { getAppVersion, getCommitTag } from '@server/utils/appVersion';
+import restartFlag from '@server/utils/restartFlag';
+import { isPerson } from '@server/utils/typeHelpers';
 import { Router } from 'express';
-import GithubAPI from '../api/github';
-import TheMovieDb from '../api/themoviedb';
-import { TmdbMovieResult, TmdbTvResult } from '../api/themoviedb/interfaces';
-import { StatusResponse } from '../interfaces/api/settingsInterfaces';
-import { Permission } from '../lib/permissions';
-import { getSettings } from '../lib/settings';
-import logger from '../logger';
-import { checkUser, isAuthenticated } from '../middleware/auth';
-import { mapProductionCompany } from '../models/Movie';
-import { mapNetwork } from '../models/Tv';
-import { appDataPath, appDataStatus } from '../utils/appDataVolume';
-import { getAppVersion, getCommitTag } from '../utils/appVersion';
-import { isPerson } from '../utils/typeHelpers';
 import authRoutes from './auth';
 import collectionRoutes from './collection';
 import discoverRoutes, { createTmdbWithRegionLanguage } from './discover';
@@ -23,7 +28,6 @@ import personRoutes from './person';
 import requestRoutes from './request';
 import searchRoutes from './search';
 import serviceRoutes from './service';
-import settingsRoutes from './settings';
 import tvRoutes from './tv';
 import user from './user';
 
@@ -75,6 +79,7 @@ router.get<unknown, StatusResponse>('/status', async (req, res) => {
     commitTag: getCommitTag(),
     updateAvailable,
     commitsBehind,
+    restartRequired: restartFlag.isSet(),
   });
 });
 
@@ -97,11 +102,7 @@ router.get('/settings/public', async (req, res) => {
     return res.status(200).json(settings.fullPublicSettings);
   }
 });
-router.use(
-  '/settings',
-  isAuthenticated(Permission.MANAGE_SETTINGS),
-  settingsRoutes
-);
+router.use('/settings', isAuthenticated(Permission.ADMIN), settingsRoutes);
 router.use('/search', isAuthenticated(), searchRoutes);
 router.use('/discover', isAuthenticated(), discoverRoutes);
 router.use('/request', isAuthenticated(), requestRoutes);
diff --git a/server/routes/issue.ts b/server/routes/issue.ts
index c7db5232..6349bb74 100644
--- a/server/routes/issue.ts
+++ b/server/routes/issue.ts
@@ -1,13 +1,13 @@
+import { IssueStatus, IssueType } from '@server/constants/issue';
+import { getRepository } from '@server/datasource';
+import Issue from '@server/entity/Issue';
+import IssueComment from '@server/entity/IssueComment';
+import Media from '@server/entity/Media';
+import type { IssueResultsResponse } from '@server/interfaces/api/issueInterfaces';
+import { Permission } from '@server/lib/permissions';
+import logger from '@server/logger';
+import { isAuthenticated } from '@server/middleware/auth';
 import { Router } from 'express';
-import { getRepository } from 'typeorm';
-import { IssueStatus } from '../constants/issue';
-import Issue from '../entity/Issue';
-import IssueComment from '../entity/IssueComment';
-import Media from '../entity/Media';
-import { IssueResultsResponse } from '../interfaces/api/issueInterfaces';
-import { Permission } from '../lib/permissions';
-import logger from '../logger';
-import { isAuthenticated } from '../middleware/auth';
 
 const issueRoutes = Router();
 
@@ -146,6 +146,68 @@ issueRoutes.post<
   }
 );
 
+issueRoutes.get('/count', async (req, res, next) => {
+  const issueRepository = getRepository(Issue);
+
+  try {
+    const query = issueRepository.createQueryBuilder('issue');
+
+    const totalCount = await query.getCount();
+
+    const videoCount = await query
+      .where('issue.issueType = :issueType', {
+        issueType: IssueType.VIDEO,
+      })
+      .getCount();
+
+    const audioCount = await query
+      .where('issue.issueType = :issueType', {
+        issueType: IssueType.AUDIO,
+      })
+      .getCount();
+
+    const subtitlesCount = await query
+      .where('issue.issueType = :issueType', {
+        issueType: IssueType.SUBTITLES,
+      })
+      .getCount();
+
+    const othersCount = await query
+      .where('issue.issueType = :issueType', {
+        issueType: IssueType.OTHER,
+      })
+      .getCount();
+
+    const openCount = await query
+      .where('issue.status = :issueStatus', {
+        issueStatus: IssueStatus.OPEN,
+      })
+      .getCount();
+
+    const closedCount = await query
+      .where('issue.status = :issueStatus', {
+        issueStatus: IssueStatus.RESOLVED,
+      })
+      .getCount();
+
+    return res.status(200).json({
+      total: totalCount,
+      video: videoCount,
+      audio: audioCount,
+      subtitles: subtitlesCount,
+      others: othersCount,
+      open: openCount,
+      closed: closedCount,
+    });
+  } catch (e) {
+    logger.debug('Something went wrong retrieving issue counts.', {
+      label: 'API',
+      errorMessage: e.message,
+    });
+    next({ status: 500, message: 'Unable to retrieve issue counts.' });
+  }
+});
+
 issueRoutes.get<{ issueId: string }>(
   '/:issueId',
   isAuthenticated(
@@ -303,7 +365,7 @@ issueRoutes.delete(
     try {
       const issue = await issueRepository.findOneOrFail({
         where: { id: Number(req.params.issueId) },
-        relations: ['createdBy'],
+        relations: { createdBy: true },
       });
 
       if (
diff --git a/server/routes/issueComment.ts b/server/routes/issueComment.ts
index c54bce5b..85e41aaa 100644
--- a/server/routes/issueComment.ts
+++ b/server/routes/issueComment.ts
@@ -1,9 +1,9 @@
+import { getRepository } from '@server/datasource';
+import IssueComment from '@server/entity/IssueComment';
+import { Permission } from '@server/lib/permissions';
+import logger from '@server/logger';
+import { isAuthenticated } from '@server/middleware/auth';
 import { Router } from 'express';
-import { getRepository } from 'typeorm';
-import IssueComment from '../entity/IssueComment';
-import { Permission } from '../lib/permissions';
-import logger from '../logger';
-import { isAuthenticated } from '../middleware/auth';
 
 const issueCommentRoutes = Router();
 
diff --git a/server/routes/media.ts b/server/routes/media.ts
index 429b2010..8f93116c 100644
--- a/server/routes/media.ts
+++ b/server/routes/media.ts
@@ -1,17 +1,19 @@
-import { Router } from 'express';
-import { FindOneOptions, FindOperator, getRepository, In } from 'typeorm';
-import TautulliAPI from '../api/tautulli';
-import { MediaStatus, MediaType } from '../constants/media';
-import Media from '../entity/Media';
-import { User } from '../entity/User';
-import {
+import TautulliAPI from '@server/api/tautulli';
+import { MediaStatus, MediaType } from '@server/constants/media';
+import { getRepository } from '@server/datasource';
+import Media from '@server/entity/Media';
+import { User } from '@server/entity/User';
+import type {
   MediaResultsResponse,
   MediaWatchDataResponse,
-} from '../interfaces/api/mediaInterfaces';
-import { Permission } from '../lib/permissions';
-import { getSettings } from '../lib/settings';
-import logger from '../logger';
-import { isAuthenticated } from '../middleware/auth';
+} from '@server/interfaces/api/mediaInterfaces';
+import { Permission } from '@server/lib/permissions';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
+import { isAuthenticated } from '@server/middleware/auth';
+import { Router } from 'express';
+import type { FindOneOptions } from 'typeorm';
+import { In } from 'typeorm';
 
 const mediaRoutes = Router();
 
@@ -21,8 +23,7 @@ mediaRoutes.get('/', async (req, res, next) => {
   const pageSize = req.query.take ? Number(req.query.take) : 20;
   const skip = req.query.skip ? Number(req.query.skip) : 0;
 
-  let statusFilter: MediaStatus | FindOperator<MediaStatus> | undefined =
-    undefined;
+  let statusFilter = undefined;
 
   switch (req.query.filter) {
     case 'available':
@@ -66,7 +67,7 @@ mediaRoutes.get('/', async (req, res, next) => {
   try {
     const [media, mediaCount] = await mediaRepository.findAndCount({
       order: sortFilter,
-      where: {
+      where: statusFilter && {
         status: statusFilter,
       },
       take: pageSize,
@@ -151,7 +152,7 @@ mediaRoutes.delete(
       const mediaRepository = getRepository(Media);
 
       const media = await mediaRepository.findOneOrFail({
-        where: { id: req.params.id },
+        where: { id: Number(req.params.id) },
       });
 
       await mediaRepository.remove(media);
diff --git a/server/routes/movie.ts b/server/routes/movie.ts
index 98474c78..f11cead8 100644
--- a/server/routes/movie.ts
+++ b/server/routes/movie.ts
@@ -1,11 +1,11 @@
+import RottenTomatoes from '@server/api/rottentomatoes';
+import TheMovieDb from '@server/api/themoviedb';
+import { MediaType } from '@server/constants/media';
+import Media from '@server/entity/Media';
+import logger from '@server/logger';
+import { mapMovieDetails } from '@server/models/Movie';
+import { mapMovieResult } from '@server/models/Search';
 import { Router } from 'express';
-import RottenTomatoes from '../api/rottentomatoes';
-import TheMovieDb from '../api/themoviedb';
-import { MediaType } from '../constants/media';
-import Media from '../entity/Media';
-import logger from '../logger';
-import { mapMovieDetails } from '../models/Movie';
-import { mapMovieResult } from '../models/Search';
 
 const movieRoutes = Router();
 
diff --git a/server/routes/person.ts b/server/routes/person.ts
index 5093ae46..7f5d6223 100644
--- a/server/routes/person.ts
+++ b/server/routes/person.ts
@@ -1,12 +1,12 @@
-import { Router } from 'express';
-import TheMovieDb from '../api/themoviedb';
-import Media from '../entity/Media';
-import logger from '../logger';
+import TheMovieDb from '@server/api/themoviedb';
+import Media from '@server/entity/Media';
+import logger from '@server/logger';
 import {
   mapCastCredits,
   mapCrewCredits,
   mapPersonDetails,
-} from '../models/Person';
+} from '@server/models/Person';
+import { Router } from 'express';
 
 const personRoutes = Router();
 
diff --git a/server/routes/request.ts b/server/routes/request.ts
index cd269f4e..9c9d96a8 100644
--- a/server/routes/request.ts
+++ b/server/routes/request.ts
@@ -1,15 +1,27 @@
+import {
+  MediaRequestStatus,
+  MediaStatus,
+  MediaType,
+} from '@server/constants/media';
+import { getRepository } from '@server/datasource';
+import Media from '@server/entity/Media';
+import {
+  DuplicateMediaRequestError,
+  MediaRequest,
+  NoSeasonsAvailableError,
+  QuotaRestrictedError,
+  RequestPermissionError,
+} from '@server/entity/MediaRequest';
+import SeasonRequest from '@server/entity/SeasonRequest';
+import { User } from '@server/entity/User';
+import type {
+  MediaRequestBody,
+  RequestResultsResponse,
+} from '@server/interfaces/api/requestInterfaces';
+import { Permission } from '@server/lib/permissions';
+import logger from '@server/logger';
+import { isAuthenticated } from '@server/middleware/auth';
 import { Router } from 'express';
-import { getRepository } from 'typeorm';
-import TheMovieDb from '../api/themoviedb';
-import { MediaRequestStatus, MediaStatus, MediaType } from '../constants/media';
-import Media from '../entity/Media';
-import { MediaRequest } from '../entity/MediaRequest';
-import SeasonRequest from '../entity/SeasonRequest';
-import { User } from '../entity/User';
-import { RequestResultsResponse } from '../interfaces/api/requestInterfaces';
-import { Permission } from '../lib/permissions';
-import logger from '../logger';
-import { isAuthenticated } from '../middleware/auth';
 
 const requestRoutes = Router();
 
@@ -40,11 +52,15 @@ requestRoutes.get<Record<string, unknown>, RequestResultsResponse>(
             MediaRequestStatus.APPROVED,
           ];
           break;
+        case 'failed':
+          statusFilter = [MediaRequestStatus.FAILED];
+          break;
         default:
           statusFilter = [
             MediaRequestStatus.PENDING,
             MediaRequestStatus.APPROVED,
             MediaRequestStatus.DECLINED,
+            MediaRequestStatus.FAILED,
           ];
       }
 
@@ -142,302 +158,38 @@ requestRoutes.get<Record<string, unknown>, RequestResultsResponse>(
   }
 );
 
-requestRoutes.post('/', async (req, res, next) => {
-  const tmdb = new TheMovieDb();
-  const mediaRepository = getRepository(Media);
-  const requestRepository = getRepository(MediaRequest);
-  const userRepository = getRepository(User);
-
-  try {
-    let requestUser = req.user;
-
-    if (
-      req.body.userId &&
-      !req.user?.hasPermission([
-        Permission.MANAGE_USERS,
-        Permission.MANAGE_REQUESTS,
-      ])
-    ) {
-      return next({
-        status: 403,
-        message: 'You do not have permission to modify the request user.',
-      });
-    } else if (req.body.userId) {
-      requestUser = await userRepository.findOneOrFail({
-        where: { id: req.body.userId },
-      });
-    }
-
-    if (!requestUser) {
-      return next({
-        status: 500,
-        message: 'User missing from request context.',
-      });
-    }
-
-    if (
-      req.body.mediaType === MediaType.MOVIE &&
-      !req.user?.hasPermission(
-        req.body.is4k
-          ? [Permission.REQUEST_4K, Permission.REQUEST_4K_MOVIE]
-          : [Permission.REQUEST, Permission.REQUEST_MOVIE],
-        {
-          type: 'or',
-        }
-      )
-    ) {
-      return next({
-        status: 403,
-        message: `You do not have permission to make ${
-          req.body.is4k ? '4K ' : ''
-        }movie requests.`,
-      });
-    } else if (
-      req.body.mediaType === MediaType.TV &&
-      !req.user?.hasPermission(
-        req.body.is4k
-          ? [Permission.REQUEST_4K, Permission.REQUEST_4K_TV]
-          : [Permission.REQUEST, Permission.REQUEST_TV],
-        {
-          type: 'or',
-        }
-      )
-    ) {
-      return next({
-        status: 403,
-        message: `You do not have permission to make ${
-          req.body.is4k ? '4K ' : ''
-        }series requests.`,
-      });
-    }
-
-    const quotas = await requestUser.getQuota();
-
-    if (req.body.mediaType === MediaType.MOVIE && quotas.movie.restricted) {
-      return next({
-        status: 403,
-        message: 'Movie Quota Exceeded',
-      });
-    } else if (req.body.mediaType === MediaType.TV && quotas.tv.restricted) {
-      return next({
-        status: 403,
-        message: 'Series Quota Exceeded',
-      });
-    }
-
-    const tmdbMedia =
-      req.body.mediaType === MediaType.MOVIE
-        ? await tmdb.getMovie({ movieId: req.body.mediaId })
-        : await tmdb.getTvShow({ tvId: req.body.mediaId });
-
-    let media = await mediaRepository.findOne({
-      where: { tmdbId: req.body.mediaId, mediaType: req.body.mediaType },
-      relations: ['requests'],
-    });
-
-    if (!media) {
-      media = new Media({
-        tmdbId: tmdbMedia.id,
-        tvdbId: req.body.tvdbId ?? tmdbMedia.external_ids.tvdb_id,
-        status: !req.body.is4k ? MediaStatus.PENDING : MediaStatus.UNKNOWN,
-        status4k: req.body.is4k ? MediaStatus.PENDING : MediaStatus.UNKNOWN,
-        mediaType: req.body.mediaType,
-      });
-    } else {
-      if (media.status === MediaStatus.UNKNOWN && !req.body.is4k) {
-        media.status = MediaStatus.PENDING;
-      }
-
-      if (media.status4k === MediaStatus.UNKNOWN && req.body.is4k) {
-        media.status4k = MediaStatus.PENDING;
-      }
-    }
-
-    if (req.body.mediaType === MediaType.MOVIE) {
-      const existing = await requestRepository
-        .createQueryBuilder('request')
-        .leftJoin('request.media', 'media')
-        .where('request.is4k = :is4k', { is4k: req.body.is4k })
-        .andWhere('media.tmdbId = :tmdbId', { tmdbId: tmdbMedia.id })
-        .andWhere('media.mediaType = :mediaType', {
-          mediaType: MediaType.MOVIE,
-        })
-        .andWhere('request.status != :requestStatus', {
-          requestStatus: MediaRequestStatus.DECLINED,
-        })
-        .getOne();
-
-      if (existing) {
-        logger.warn('Duplicate request for media blocked', {
-          tmdbId: tmdbMedia.id,
-          mediaType: req.body.mediaType,
-          is4k: req.body.is4k,
-          label: 'Media Request',
-        });
+requestRoutes.post<never, MediaRequest, MediaRequestBody>(
+  '/',
+  async (req, res, next) => {
+    try {
+      if (!req.user) {
         return next({
-          status: 409,
-          message: 'Request for this media already exists.',
+          status: 401,
+          message: 'You must be logged in to request media.',
         });
       }
+      const request = await MediaRequest.request(req.body, req.user);
 
-      await mediaRepository.save(media);
-
-      const request = new MediaRequest({
-        type: MediaType.MOVIE,
-        media,
-        requestedBy: requestUser,
-        // If the user is an admin or has the "auto approve" permission, automatically approve the request
-        status: req.user?.hasPermission(
-          [
-            req.body.is4k
-              ? Permission.AUTO_APPROVE_4K
-              : Permission.AUTO_APPROVE,
-            req.body.is4k
-              ? Permission.AUTO_APPROVE_4K_MOVIE
-              : Permission.AUTO_APPROVE_MOVIE,
-            Permission.MANAGE_REQUESTS,
-          ],
-          { type: 'or' }
-        )
-          ? MediaRequestStatus.APPROVED
-          : MediaRequestStatus.PENDING,
-        modifiedBy: req.user?.hasPermission(
-          [
-            req.body.is4k
-              ? Permission.AUTO_APPROVE_4K
-              : Permission.AUTO_APPROVE,
-            req.body.is4k
-              ? Permission.AUTO_APPROVE_4K_MOVIE
-              : Permission.AUTO_APPROVE_MOVIE,
-            Permission.MANAGE_REQUESTS,
-          ],
-          { type: 'or' }
-        )
-          ? req.user
-          : undefined,
-        is4k: req.body.is4k,
-        serverId: req.body.serverId,
-        profileId: req.body.profileId,
-        rootFolder: req.body.rootFolder,
-        tags: req.body.tags,
-      });
-
-      await requestRepository.save(request);
       return res.status(201).json(request);
-    } else if (req.body.mediaType === MediaType.TV) {
-      const requestedSeasons = req.body.seasons as number[];
-      let existingSeasons: number[] = [];
-
-      // We need to check existing requests on this title to make sure we don't double up on seasons that were
-      // already requested. In the case they were, we just throw out any duplicates but still approve the request.
-      // (Unless there are no seasons, in which case we abort)
-      if (media.requests) {
-        existingSeasons = media.requests
-          .filter(
-            (request) =>
-              request.is4k === req.body.is4k &&
-              request.status !== MediaRequestStatus.DECLINED
-          )
-          .reduce((seasons, request) => {
-            const combinedSeasons = request.seasons.map(
-              (season) => season.seasonNumber
-            );
-
-            return [...seasons, ...combinedSeasons];
-          }, [] as number[]);
+    } catch (error) {
+      if (!(error instanceof Error)) {
+        return;
       }
 
-      const finalSeasons = requestedSeasons.filter(
-        (rs) => !existingSeasons.includes(rs)
-      );
-
-      if (finalSeasons.length === 0) {
-        return next({
-          status: 202,
-          message: 'No seasons available to request',
-        });
-      } else if (
-        quotas.tv.limit &&
-        finalSeasons.length > (quotas.tv.remaining ?? 0)
-      ) {
-        return next({
-          status: 403,
-          message: 'Series Quota Exceeded',
-        });
+      switch (error.constructor) {
+        case RequestPermissionError:
+        case QuotaRestrictedError:
+          return next({ status: 403, message: error.message });
+        case DuplicateMediaRequestError:
+          return next({ status: 409, message: error.message });
+        case NoSeasonsAvailableError:
+          return next({ status: 202, message: error.message });
+        default:
+          return next({ status: 500, message: error.message });
       }
-
-      await mediaRepository.save(media);
-
-      const request = new MediaRequest({
-        type: MediaType.TV,
-        media,
-        requestedBy: requestUser,
-        // If the user is an admin or has the "auto approve" permission, automatically approve the request
-        status: req.user?.hasPermission(
-          [
-            req.body.is4k
-              ? Permission.AUTO_APPROVE_4K
-              : Permission.AUTO_APPROVE,
-            req.body.is4k
-              ? Permission.AUTO_APPROVE_4K_TV
-              : Permission.AUTO_APPROVE_TV,
-            Permission.MANAGE_REQUESTS,
-          ],
-          { type: 'or' }
-        )
-          ? MediaRequestStatus.APPROVED
-          : MediaRequestStatus.PENDING,
-        modifiedBy: req.user?.hasPermission(
-          [
-            req.body.is4k
-              ? Permission.AUTO_APPROVE_4K
-              : Permission.AUTO_APPROVE,
-            req.body.is4k
-              ? Permission.AUTO_APPROVE_4K_TV
-              : Permission.AUTO_APPROVE_TV,
-            Permission.MANAGE_REQUESTS,
-          ],
-          { type: 'or' }
-        )
-          ? req.user
-          : undefined,
-        is4k: req.body.is4k,
-        serverId: req.body.serverId,
-        profileId: req.body.profileId,
-        rootFolder: req.body.rootFolder,
-        languageProfileId: req.body.languageProfileId,
-        tags: req.body.tags,
-        seasons: finalSeasons.map(
-          (sn) =>
-            new SeasonRequest({
-              seasonNumber: sn,
-              status: req.user?.hasPermission(
-                [
-                  req.body.is4k
-                    ? Permission.AUTO_APPROVE_4K
-                    : Permission.AUTO_APPROVE,
-                  req.body.is4k
-                    ? Permission.AUTO_APPROVE_4K_TV
-                    : Permission.AUTO_APPROVE_TV,
-                  Permission.MANAGE_REQUESTS,
-                ],
-                { type: 'or' }
-              )
-                ? MediaRequestStatus.APPROVED
-                : MediaRequestStatus.PENDING,
-            })
-        ),
-      });
-
-      await requestRepository.save(request);
-      return res.status(201).json(request);
     }
-
-    next({ status: 500, message: 'Invalid media type' });
-  } catch (e) {
-    next({ status: 500, message: e.message });
   }
-});
+);
 
 requestRoutes.get('/count', async (_req, res, next) => {
   const requestRepository = getRepository(MediaRequest);
@@ -528,7 +280,7 @@ requestRoutes.get('/:requestId', async (req, res, next) => {
   try {
     const request = await requestRepository.findOneOrFail({
       where: { id: Number(req.params.requestId) },
-      relations: ['requestedBy', 'modifiedBy'],
+      relations: { requestedBy: true, modifiedBy: true },
     });
 
     if (
@@ -560,9 +312,11 @@ requestRoutes.put<{ requestId: string }>(
     const requestRepository = getRepository(MediaRequest);
     const userRepository = getRepository(User);
     try {
-      const request = await requestRepository.findOne(
-        Number(req.params.requestId)
-      );
+      const request = await requestRepository.findOne({
+        where: {
+          id: Number(req.params.requestId),
+        },
+      });
 
       if (!request) {
         return next({ status: 404, message: 'Request not found.' });
@@ -628,7 +382,7 @@ requestRoutes.put<{ requestId: string }>(
         // Get existing media so we can work with all the requests
         const media = await mediaRepository.findOneOrFail({
           where: { tmdbId: request.media.tmdbId, mediaType: MediaType.TV },
-          relations: ['requests'],
+          relations: { requests: true },
         });
 
         // Get all requested seasons that are not part of this request we are editing
@@ -698,7 +452,7 @@ requestRoutes.delete('/:requestId', async (req, res, next) => {
   try {
     const request = await requestRepository.findOneOrFail({
       where: { id: Number(req.params.requestId) },
-      relations: ['requestedBy', 'modifiedBy'],
+      relations: { requestedBy: true, modifiedBy: true },
     });
 
     if (
@@ -735,7 +489,7 @@ requestRoutes.post<{
     try {
       const request = await requestRepository.findOneOrFail({
         where: { id: Number(req.params.requestId) },
-        relations: ['requestedBy', 'modifiedBy'],
+        relations: { requestedBy: true, modifiedBy: true },
       });
 
       await request.updateParentStatus();
@@ -763,7 +517,7 @@ requestRoutes.post<{
     try {
       const request = await requestRepository.findOneOrFail({
         where: { id: Number(req.params.requestId) },
-        relations: ['requestedBy', 'modifiedBy'],
+        relations: { requestedBy: true, modifiedBy: true },
       });
 
       let newStatus: MediaRequestStatus;
diff --git a/server/routes/search.ts b/server/routes/search.ts
index 3f26a393..1152bce3 100644
--- a/server/routes/search.ts
+++ b/server/routes/search.ts
@@ -1,10 +1,10 @@
+import TheMovieDb from '@server/api/themoviedb';
+import type { TmdbSearchMultiResponse } from '@server/api/themoviedb/interfaces';
+import Media from '@server/entity/Media';
+import { findSearchProvider } from '@server/lib/search';
+import logger from '@server/logger';
+import { mapSearchResults } from '@server/models/Search';
 import { Router } from 'express';
-import TheMovieDb from '../api/themoviedb';
-import { TmdbSearchMultiResponse } from '../api/themoviedb/interfaces';
-import Media from '../entity/Media';
-import { findSearchProvider } from '../lib/search';
-import logger from '../logger';
-import { mapSearchResults } from '../models/Search';
 
 const searchRoutes = Router();
 
diff --git a/server/routes/service.ts b/server/routes/service.ts
index 862ab374..b77d58c9 100644
--- a/server/routes/service.ts
+++ b/server/routes/service.ts
@@ -1,13 +1,13 @@
-import { Router } from 'express';
-import RadarrAPI from '../api/servarr/radarr';
-import SonarrAPI from '../api/servarr/sonarr';
-import TheMovieDb from '../api/themoviedb';
-import {
+import RadarrAPI from '@server/api/servarr/radarr';
+import SonarrAPI from '@server/api/servarr/sonarr';
+import TheMovieDb from '@server/api/themoviedb';
+import type {
   ServiceCommonServer,
   ServiceCommonServerWithDetails,
-} from '../interfaces/api/serviceInterfaces';
-import { getSettings } from '../lib/settings';
-import logger from '../logger';
+} from '@server/interfaces/api/serviceInterfaces';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
+import { Router } from 'express';
 
 const serviceRoutes = Router();
 
@@ -191,7 +191,7 @@ serviceRoutes.get<{ tmdbId: string }>(
     try {
       const tv = await tmdb.getTvShow({
         tvId: Number(req.params.tmdbId),
-        language: req.locale ?? (req.query.language as string),
+        language: 'en',
       });
 
       const response = await sonarr.getSeriesByTitle(tv.name);
diff --git a/server/routes/settings/index.ts b/server/routes/settings/index.ts
index bd9c1164..41d2c745 100644
--- a/server/routes/settings/index.ts
+++ b/server/routes/settings/index.ts
@@ -1,33 +1,35 @@
+import PlexAPI from '@server/api/plexapi';
+import PlexTvAPI from '@server/api/plextv';
+import TautulliAPI from '@server/api/tautulli';
+import { getRepository } from '@server/datasource';
+import Media from '@server/entity/Media';
+import { MediaRequest } from '@server/entity/MediaRequest';
+import { User } from '@server/entity/User';
+import type { PlexConnection } from '@server/interfaces/api/plexInterfaces';
+import type {
+  LogMessage,
+  LogsResultsResponse,
+  SettingsAboutResponse,
+} from '@server/interfaces/api/settingsInterfaces';
+import { scheduledJobs } from '@server/job/schedule';
+import type { AvailableCacheIds } from '@server/lib/cache';
+import cacheManager from '@server/lib/cache';
+import { Permission } from '@server/lib/permissions';
+import { plexFullScanner } from '@server/lib/scanners/plex';
+import type { MainSettings } from '@server/lib/settings';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
+import { isAuthenticated } from '@server/middleware/auth';
+import { appDataPath } from '@server/utils/appDataVolume';
+import { getAppVersion } from '@server/utils/appVersion';
 import { Router } from 'express';
 import rateLimit from 'express-rate-limit';
 import fs from 'fs';
-import { merge, omit, set, sortBy } from 'lodash';
+import { escapeRegExp, merge, omit, set, sortBy } from 'lodash';
 import { rescheduleJob } from 'node-schedule';
 import path from 'path';
 import semver from 'semver';
-import { getRepository } from 'typeorm';
 import { URL } from 'url';
-import PlexAPI from '../../api/plexapi';
-import PlexTvAPI from '../../api/plextv';
-import TautulliAPI from '../../api/tautulli';
-import Media from '../../entity/Media';
-import { MediaRequest } from '../../entity/MediaRequest';
-import { User } from '../../entity/User';
-import { PlexConnection } from '../../interfaces/api/plexInterfaces';
-import {
-  LogMessage,
-  LogsResultsResponse,
-  SettingsAboutResponse,
-} from '../../interfaces/api/settingsInterfaces';
-import { scheduledJobs } from '../../job/schedule';
-import cacheManager, { AvailableCacheIds } from '../../lib/cache';
-import { Permission } from '../../lib/permissions';
-import { plexFullScanner } from '../../lib/scanners/plex';
-import { getSettings, MainSettings } from '../../lib/settings';
-import logger from '../../logger';
-import { isAuthenticated } from '../../middleware/auth';
-import { appDataPath } from '../../utils/appDataVolume';
-import { getAppVersion } from '../../utils/appVersion';
 import notificationRoutes from './notifications';
 import radarrRoutes from './radarr';
 import sonarrRoutes from './sonarr';
@@ -91,8 +93,8 @@ settingsRoutes.post('/plex', async (req, res, next) => {
   const settings = getSettings();
   try {
     const admin = await userRepository.findOneOrFail({
-      select: ['id', 'plexToken'],
-      order: { id: 'ASC' },
+      select: { id: true, plexToken: true },
+      where: { id: 1 },
     });
 
     Object.assign(settings.plex, req.body);
@@ -127,8 +129,8 @@ settingsRoutes.get('/plex/devices/servers', async (req, res, next) => {
   const userRepository = getRepository(User);
   try {
     const admin = await userRepository.findOneOrFail({
-      select: ['id', 'plexToken'],
-      order: { id: 'ASC' },
+      select: { id: true, plexToken: true },
+      where: { id: 1 },
     });
     const plexTvClient = admin.plexToken
       ? new PlexTvAPI(admin.plexToken)
@@ -206,8 +208,8 @@ settingsRoutes.get('/plex/library', async (req, res) => {
   if (req.query.sync) {
     const userRepository = getRepository(User);
     const admin = await userRepository.findOneOrFail({
-      select: ['id', 'plexToken'],
-      order: { id: 'ASC' },
+      select: { id: true, plexToken: true },
+      where: { id: 1 },
     });
     const plexapi = new PlexAPI({ plexToken: admin.plexToken });
 
@@ -282,8 +284,8 @@ settingsRoutes.get(
 
     try {
       const admin = await userRepository.findOneOrFail({
-        select: ['id', 'plexToken'],
-        order: { id: 'ASC' },
+        select: { id: true, plexToken: true },
+        where: { id: 1 },
       });
       const plexApi = new PlexTvAPI(admin.plexToken ?? '');
       const plexUsers = (await plexApi.getUsers()).MediaContainer.User.map(
@@ -342,6 +344,8 @@ settingsRoutes.get(
   (req, res, next) => {
     const pageSize = req.query.take ? Number(req.query.take) : 25;
     const skip = req.query.skip ? Number(req.query.skip) : 0;
+    const search = (req.query.search as string) ?? '';
+    const searchRegexp = new RegExp(escapeRegExp(search), 'i');
 
     let filter: string[] = [];
     switch (req.query.filter) {
@@ -373,6 +377,22 @@ settingsRoutes.get(
       'data',
     ];
 
+    const deepValueStrings = (obj: Record<string, unknown>): string[] => {
+      const values = [];
+
+      for (const val of Object.values(obj)) {
+        if (typeof val === 'string') {
+          values.push(val);
+        } else if (typeof val === 'number') {
+          values.push(val.toString());
+        } else if (val !== null && typeof val === 'object') {
+          values.push(...deepValueStrings(val as Record<string, unknown>));
+        }
+      }
+
+      return values;
+    };
+
     try {
       fs.readFileSync(logFile, 'utf-8')
         .split('\n')
@@ -397,6 +417,19 @@ settingsRoutes.get(
               });
           }
 
+          if (req.query.search) {
+            if (
+              // label and data are sometimes undefined
+              !searchRegexp.test(logMessage.label ?? '') &&
+              !searchRegexp.test(logMessage.message) &&
+              !deepValueStrings(logMessage.data ?? {}).some((val) =>
+                searchRegexp.test(val)
+              )
+            ) {
+              return;
+            }
+          }
+
           logs.push(logMessage);
         });
 
@@ -431,6 +464,7 @@ settingsRoutes.get('/jobs', (_req, res) => {
       name: job.name,
       type: job.type,
       interval: job.interval,
+      cronSchedule: job.cronSchedule,
       nextExecutionTime: job.job.nextInvocation(),
       running: job.running ? job.running() : false,
     }))
@@ -451,6 +485,7 @@ settingsRoutes.post<{ jobId: string }>('/jobs/:jobId/run', (req, res, next) => {
     name: scheduledJob.name,
     type: scheduledJob.type,
     interval: scheduledJob.interval,
+    cronSchedule: scheduledJob.cronSchedule,
     nextExecutionTime: scheduledJob.job.nextInvocation(),
     running: scheduledJob.running ? scheduledJob.running() : false,
   });
@@ -476,6 +511,7 @@ settingsRoutes.post<{ jobId: string }>(
       name: scheduledJob.name,
       type: scheduledJob.type,
       interval: scheduledJob.interval,
+      cronSchedule: scheduledJob.cronSchedule,
       nextExecutionTime: scheduledJob.job.nextInvocation(),
       running: scheduledJob.running ? scheduledJob.running() : false,
     });
@@ -500,11 +536,14 @@ settingsRoutes.post<{ jobId: string }>(
       settings.jobs[scheduledJob.id].schedule = req.body.schedule;
       settings.save();
 
+      scheduledJob.cronSchedule = req.body.schedule;
+
       return res.status(200).json({
         id: scheduledJob.id,
         name: scheduledJob.name,
         type: scheduledJob.type,
         interval: scheduledJob.interval,
+        cronSchedule: scheduledJob.cronSchedule,
         nextExecutionTime: scheduledJob.job.nextInvocation(),
         running: scheduledJob.running ? scheduledJob.running() : false,
       });
diff --git a/server/routes/settings/notifications.ts b/server/routes/settings/notifications.ts
index 5a337237..5a38555c 100644
--- a/server/routes/settings/notifications.ts
+++ b/server/routes/settings/notifications.ts
@@ -1,23 +1,24 @@
+import type { User } from '@server/entity/User';
+import { Notification } from '@server/lib/notifications';
+import type { NotificationAgent } from '@server/lib/notifications/agents/agent';
+import DiscordAgent from '@server/lib/notifications/agents/discord';
+import EmailAgent from '@server/lib/notifications/agents/email';
+import GotifyAgent from '@server/lib/notifications/agents/gotify';
+import LunaSeaAgent from '@server/lib/notifications/agents/lunasea';
+import PushbulletAgent from '@server/lib/notifications/agents/pushbullet';
+import PushoverAgent from '@server/lib/notifications/agents/pushover';
+import SlackAgent from '@server/lib/notifications/agents/slack';
+import TelegramAgent from '@server/lib/notifications/agents/telegram';
+import WebhookAgent from '@server/lib/notifications/agents/webhook';
+import WebPushAgent from '@server/lib/notifications/agents/webpush';
+import { getSettings } from '@server/lib/settings';
 import { Router } from 'express';
-import { User } from '../../entity/User';
-import { Notification } from '../../lib/notifications';
-import { NotificationAgent } from '../../lib/notifications/agents/agent';
-import DiscordAgent from '../../lib/notifications/agents/discord';
-import EmailAgent from '../../lib/notifications/agents/email';
-import GotifyAgent from '../../lib/notifications/agents/gotify';
-import LunaSeaAgent from '../../lib/notifications/agents/lunasea';
-import PushbulletAgent from '../../lib/notifications/agents/pushbullet';
-import PushoverAgent from '../../lib/notifications/agents/pushover';
-import SlackAgent from '../../lib/notifications/agents/slack';
-import TelegramAgent from '../../lib/notifications/agents/telegram';
-import WebhookAgent from '../../lib/notifications/agents/webhook';
-import WebPushAgent from '../../lib/notifications/agents/webpush';
-import { getSettings } from '../../lib/settings';
 
 const notificationRoutes = Router();
 
 const sendTestNotification = async (agent: NotificationAgent, user: User) =>
   await agent.send(Notification.TEST_NOTIFICATION, {
+    notifySystem: true,
     notifyAdmin: false,
     notifyUser: user,
     subject: 'Test Notification',
@@ -247,7 +248,7 @@ notificationRoutes.post('/webpush/test', async (req, res, next) => {
   if (!req.user) {
     return next({
       status: 500,
-      message: 'User information missing from request',
+      message: 'User information is missing from the request.',
     });
   }
 
@@ -363,7 +364,7 @@ notificationRoutes.post('/lunasea/test', async (req, res, next) => {
   if (!req.user) {
     return next({
       status: 500,
-      message: 'User information missing from request',
+      message: 'User information is missing from the request.',
     });
   }
 
@@ -384,34 +385,26 @@ notificationRoutes.get('/gotify', (_req, res) => {
   res.status(200).json(settings.notifications.agents.gotify);
 });
 
-notificationRoutes.post('/gotify', (req, rest) => {
+notificationRoutes.post('/gotify', (req, res) => {
   const settings = getSettings();
 
   settings.notifications.agents.gotify = req.body;
   settings.save();
 
-  rest.status(200).json(settings.notifications.agents.gotify);
+  res.status(200).json(settings.notifications.agents.gotify);
 });
 
-notificationRoutes.post('/gotify/test', async (req, rest, next) => {
+notificationRoutes.post('/gotify/test', async (req, res, next) => {
   if (!req.user) {
     return next({
       status: 500,
-      message: 'User information is missing from request',
+      message: 'User information is missing from the request.',
     });
   }
 
   const gotifyAgent = new GotifyAgent(req.body);
-  if (
-    await gotifyAgent.send(Notification.TEST_NOTIFICATION, {
-      notifyAdmin: false,
-      notifyUser: req.user,
-      subject: 'Test Notification',
-      message:
-        'This is a test notification! Check check, 1, 2, 3. Are we coming in clear?',
-    })
-  ) {
-    return rest.status(204).send();
+  if (await sendTestNotification(gotifyAgent, req.user)) {
+    return res.status(204).send();
   } else {
     return next({
       status: 500,
diff --git a/server/routes/settings/radarr.ts b/server/routes/settings/radarr.ts
index a33bfcdb..c2b0a6f5 100644
--- a/server/routes/settings/radarr.ts
+++ b/server/routes/settings/radarr.ts
@@ -1,7 +1,8 @@
+import RadarrAPI from '@server/api/servarr/radarr';
+import type { RadarrSettings } from '@server/lib/settings';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
 import { Router } from 'express';
-import RadarrAPI from '../../api/servarr/radarr';
-import { getSettings, RadarrSettings } from '../../lib/settings';
-import logger from '../../logger';
 
 const radarrRoutes = Router();
 
diff --git a/server/routes/settings/sonarr.ts b/server/routes/settings/sonarr.ts
index da5a5bb3..358d0700 100644
--- a/server/routes/settings/sonarr.ts
+++ b/server/routes/settings/sonarr.ts
@@ -1,7 +1,8 @@
+import SonarrAPI from '@server/api/servarr/sonarr';
+import type { SonarrSettings } from '@server/lib/settings';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
 import { Router } from 'express';
-import SonarrAPI from '../../api/servarr/sonarr';
-import { getSettings, SonarrSettings } from '../../lib/settings';
-import logger from '../../logger';
 
 const sonarrRoutes = Router();
 
diff --git a/server/routes/tv.ts b/server/routes/tv.ts
index 201e7afe..d45e4062 100644
--- a/server/routes/tv.ts
+++ b/server/routes/tv.ts
@@ -1,11 +1,11 @@
+import RottenTomatoes from '@server/api/rottentomatoes';
+import TheMovieDb from '@server/api/themoviedb';
+import { MediaType } from '@server/constants/media';
+import Media from '@server/entity/Media';
+import logger from '@server/logger';
+import { mapTvResult } from '@server/models/Search';
+import { mapSeasonWithEpisodes, mapTvDetails } from '@server/models/Tv';
 import { Router } from 'express';
-import RottenTomatoes from '../api/rottentomatoes';
-import TheMovieDb from '../api/themoviedb';
-import { MediaType } from '../constants/media';
-import Media from '../entity/Media';
-import logger from '../logger';
-import { mapTvResult } from '../models/Search';
-import { mapSeasonWithEpisodes, mapTvDetails } from '../models/Tv';
 
 const tvRoutes = Router();
 
diff --git a/server/routes/user/index.ts b/server/routes/user/index.ts
index a4e8861e..f77b7e51 100644
--- a/server/routes/user/index.ts
+++ b/server/routes/user/index.ts
@@ -1,25 +1,27 @@
-import { Router } from 'express';
-import gravatarUrl from 'gravatar-url';
-import { findIndex, sortBy } from 'lodash';
-import { getRepository, In, Not } from 'typeorm';
-import PlexTvAPI from '../../api/plextv';
-import TautulliAPI from '../../api/tautulli';
-import { MediaType } from '../../constants/media';
-import { UserType } from '../../constants/user';
-import Media from '../../entity/Media';
-import { MediaRequest } from '../../entity/MediaRequest';
-import { User } from '../../entity/User';
-import { UserPushSubscription } from '../../entity/UserPushSubscription';
-import {
+import PlexTvAPI from '@server/api/plextv';
+import TautulliAPI from '@server/api/tautulli';
+import { MediaType } from '@server/constants/media';
+import { UserType } from '@server/constants/user';
+import { getRepository } from '@server/datasource';
+import Media from '@server/entity/Media';
+import { MediaRequest } from '@server/entity/MediaRequest';
+import { User } from '@server/entity/User';
+import { UserPushSubscription } from '@server/entity/UserPushSubscription';
+import type { WatchlistResponse } from '@server/interfaces/api/discoverInterfaces';
+import type {
   QuotaResponse,
   UserRequestsResponse,
   UserResultsResponse,
   UserWatchDataResponse,
-} from '../../interfaces/api/userInterfaces';
-import { hasPermission, Permission } from '../../lib/permissions';
-import { getSettings } from '../../lib/settings';
-import logger from '../../logger';
-import { isAuthenticated } from '../../middleware/auth';
+} from '@server/interfaces/api/userInterfaces';
+import { hasPermission, Permission } from '@server/lib/permissions';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
+import { isAuthenticated } from '@server/middleware/auth';
+import { Router } from 'express';
+import gravatarUrl from 'gravatar-url';
+import { findIndex, sortBy } from 'lodash';
+import { In } from 'typeorm';
 import userSettingsRoutes from './usersettings';
 
 const router = Router();
@@ -258,12 +260,7 @@ export const canMakePermissionsChange = (
   user?: User
 ): boolean =>
   // Only let the owner grant admin privileges
-  !(hasPermission(Permission.ADMIN, permissions) && user?.id !== 1) ||
-  // Only let users with the manage settings permission, grant the same permission
-  !(
-    hasPermission(Permission.MANAGE_SETTINGS, permissions) &&
-    !hasPermission(Permission.MANAGE_SETTINGS, user?.permissions ?? 0)
-  );
+  !(hasPermission(Permission.ADMIN, permissions) && user?.id !== 1);
 
 router.put<
   Record<string, never>,
@@ -282,8 +279,12 @@ router.put<
 
     const userRepository = getRepository(User);
 
-    const users = await userRepository.findByIds(req.body.ids, {
-      ...(!isOwner ? { id: Not(1) } : {}),
+    const users: User[] = await userRepository.find({
+      where: {
+        id: In(
+          isOwner ? req.body.ids : req.body.ids.filter((id) => Number(id) !== 1)
+        ),
+      },
     });
 
     const updatedUsers = await Promise.all(
@@ -350,7 +351,7 @@ router.delete<{ id: string }>(
 
       const user = await userRepository.findOne({
         where: { id: Number(req.params.id) },
-        relations: ['requests'],
+        relations: { requests: true },
       });
 
       if (!user) {
@@ -409,8 +410,8 @@ router.post(
 
       // taken from auth.ts
       const mainUser = await userRepository.findOneOrFail({
-        select: ['id', 'plexToken'],
-        order: { id: 'ASC' },
+        select: { id: true, plexToken: true },
+        where: { id: 1 },
       });
       const mainPlexTv = new PlexTvAPI(mainUser.plexToken ?? '');
 
@@ -524,7 +525,7 @@ router.get<{ id: string }, UserWatchDataResponse>(
     try {
       const user = await getRepository(User).findOneOrFail({
         where: { id: Number(req.params.id) },
-        select: ['id', 'plexId'],
+        select: { id: true, plexId: true },
       });
 
       const tautulli = new TautulliAPI(settings);
@@ -606,4 +607,60 @@ router.get<{ id: string }, UserWatchDataResponse>(
   }
 );
 
+router.get<{ id: string; page?: number }, WatchlistResponse>(
+  '/:id/watchlist',
+  async (req, res, next) => {
+    if (
+      Number(req.params.id) !== req.user?.id &&
+      !req.user?.hasPermission(
+        [Permission.MANAGE_REQUESTS, Permission.WATCHLIST_VIEW],
+        {
+          type: 'or',
+        }
+      )
+    ) {
+      return next({
+        status: 403,
+        message:
+          "You do not have permission to view this user's Plex Watchlist.",
+      });
+    }
+
+    const itemsPerPage = 20;
+    const page = req.params.page ?? 1;
+    const offset = (page - 1) * itemsPerPage;
+
+    const user = await getRepository(User).findOneOrFail({
+      where: { id: Number(req.params.id) },
+      select: { id: true, plexToken: true },
+    });
+
+    if (!user?.plexToken) {
+      // We will just return an empty array if the user has no Plex token
+      return res.json({
+        page: 1,
+        totalPages: 1,
+        totalResults: 0,
+        results: [],
+      });
+    }
+
+    const plexTV = new PlexTvAPI(user.plexToken);
+
+    const watchlist = await plexTV.getWatchlist({ offset });
+
+    return res.json({
+      page,
+      totalPages: Math.ceil(watchlist.size / itemsPerPage),
+      totalResults: watchlist.size,
+      results: watchlist.items.map((item) => ({
+        ratingKey: item.ratingKey,
+        title: item.title,
+        mediaType: item.type === 'show' ? 'tv' : 'movie',
+        tmdbId: item.tmdbId,
+      })),
+    });
+  }
+);
+
 export default router;
diff --git a/server/routes/user/usersettings.ts b/server/routes/user/usersettings.ts
index 0c53c94a..875309f3 100644
--- a/server/routes/user/usersettings.ts
+++ b/server/routes/user/usersettings.ts
@@ -1,16 +1,16 @@
-import { Router } from 'express';
-import { getRepository } from 'typeorm';
-import { canMakePermissionsChange } from '.';
-import { User } from '../../entity/User';
-import { UserSettings } from '../../entity/UserSettings';
-import {
+import { getRepository } from '@server/datasource';
+import { User } from '@server/entity/User';
+import { UserSettings } from '@server/entity/UserSettings';
+import type {
   UserSettingsGeneralResponse,
   UserSettingsNotificationsResponse,
-} from '../../interfaces/api/userSettingsInterfaces';
-import { Permission } from '../../lib/permissions';
-import { getSettings } from '../../lib/settings';
-import logger from '../../logger';
-import { isAuthenticated } from '../../middleware/auth';
+} from '@server/interfaces/api/userSettingsInterfaces';
+import { Permission } from '@server/lib/permissions';
+import { getSettings } from '@server/lib/settings';
+import logger from '@server/logger';
+import { isAuthenticated } from '@server/middleware/auth';
+import { Router } from 'express';
+import { canMakePermissionsChange } from '.';
 
 const isOwnProfileOrAdmin = (): Middleware => {
   const authMiddleware: Middleware = (req, res, next) => {
@@ -63,6 +63,8 @@ userSettingsRoutes.get<{ id: string }, UserSettingsGeneralResponse>(
         globalMovieQuotaLimit: defaultQuotas.movie.quotaLimit,
         globalTvQuotaDays: defaultQuotas.tv.quotaDays,
         globalTvQuotaLimit: defaultQuotas.tv.quotaLimit,
+        watchlistSyncMovies: user.settings?.watchlistSyncMovies,
+        watchlistSyncTv: user.settings?.watchlistSyncTv,
       });
     } catch (e) {
       next({ status: 500, message: e.message });
@@ -114,12 +116,16 @@ userSettingsRoutes.post<
         locale: req.body.locale,
         region: req.body.region,
         originalLanguage: req.body.originalLanguage,
+        watchlistSyncMovies: req.body.watchlistSyncMovies,
+        watchlistSyncTv: req.body.watchlistSyncTv,
       });
     } else {
       user.settings.discordId = req.body.discordId;
       user.settings.locale = req.body.locale;
       user.settings.region = req.body.region;
       user.settings.originalLanguage = req.body.originalLanguage;
+      user.settings.watchlistSyncMovies = req.body.watchlistSyncMovies;
+      user.settings.watchlistSyncTv = req.body.watchlistSyncTv;
     }
 
     await userRepository.save(user);
@@ -130,6 +136,8 @@ userSettingsRoutes.post<
       locale: user.settings.locale,
       region: user.settings.region,
       originalLanguage: user.settings.originalLanguage,
+      watchlistSyncMovies: user.settings.watchlistSyncMovies,
+      watchlistSyncTv: user.settings.watchlistSyncTv,
     });
   } catch (e) {
     next({ status: 500, message: e.message });
diff --git a/server/scripts/prepareTestDb.ts b/server/scripts/prepareTestDb.ts
new file mode 100644
index 00000000..7caede41
--- /dev/null
+++ b/server/scripts/prepareTestDb.ts
@@ -0,0 +1,72 @@
+import { UserType } from '@server/constants/user';
+import dataSource, { getRepository } from '@server/datasource';
+import { User } from '@server/entity/User';
+import { copyFileSync } from 'fs';
+import gravatarUrl from 'gravatar-url';
+import path from 'path';
+
+const prepareDb = async () => {
+  // Copy over test settings.json
+  copyFileSync(
+    path.join(__dirname, '../../cypress/config/settings.cypress.json'),
+    path.join(__dirname, '../../config/settings.json')
+  );
+
+  // Connect to DB and seed test data
+  const dbConnection = await dataSource.initialize();
+
+  if (process.env.PRESERVE_DB !== 'true') {
+    await dbConnection.dropDatabase();
+  }
+
+  // Run migrations in production
+  if (process.env.WITH_MIGRATIONS === 'true') {
+    await dbConnection.runMigrations();
+  } else {
+    await dbConnection.synchronize();
+  }
+
+  const userRepository = getRepository(User);
+
+  const admin = await userRepository.findOne({
+    select: { id: true, plexId: true },
+    where: { id: 1 },
+  });
+
+  // Create the admin user
+  const user =
+    (await userRepository.findOne({
+      where: { email: 'admin@seerr.dev' },
+    })) ?? new User();
+  user.plexId = admin?.plexId ?? 1;
+  user.plexToken = '1234';
+  user.plexUsername = 'admin';
+  user.username = 'admin';
+  user.email = 'admin@seerr.dev';
+  user.userType = UserType.PLEX;
+  await user.setPassword('test1234');
+  user.permissions = 2;
+  user.avatar = gravatarUrl('admin@seerr.dev', { default: 'mm', size: 200 });
+  await userRepository.save(user);
+
+  // Create the other user
+  const otherUser =
+    (await userRepository.findOne({
+      where: { email: 'friend@seerr.dev' },
+    })) ?? new User();
+  otherUser.plexId = admin?.plexId ?? 1;
+  otherUser.plexToken = '1234';
+  otherUser.plexUsername = 'friend';
+  otherUser.username = 'friend';
+  otherUser.email = 'friend@seerr.dev';
+  otherUser.userType = UserType.PLEX;
+  await otherUser.setPassword('test1234');
+  otherUser.permissions = 32;
+  otherUser.avatar = gravatarUrl('friend@seerr.dev', {
+    default: 'mm',
+    size: 200,
+  });
+  await userRepository.save(otherUser);
+};
+
+prepareDb();
diff --git a/server/subscriber/IssueCommentSubscriber.ts b/server/subscriber/IssueCommentSubscriber.ts
index 1b1b7b55..cb95ba00 100644
--- a/server/subscriber/IssueCommentSubscriber.ts
+++ b/server/subscriber/IssueCommentSubscriber.ts
@@ -1,18 +1,15 @@
+import TheMovieDb from '@server/api/themoviedb';
+import { IssueType, IssueTypeName } from '@server/constants/issue';
+import { MediaType } from '@server/constants/media';
+import { getRepository } from '@server/datasource';
+import IssueComment from '@server/entity/IssueComment';
+import Media from '@server/entity/Media';
+import notificationManager, { Notification } from '@server/lib/notifications';
+import { Permission } from '@server/lib/permissions';
+import logger from '@server/logger';
 import { sortBy } from 'lodash';
-import {
-  EntitySubscriberInterface,
-  EventSubscriber,
-  getRepository,
-  InsertEvent,
-} from 'typeorm';
-import TheMovieDb from '../api/themoviedb';
-import { IssueType, IssueTypeName } from '../constants/issue';
-import { MediaType } from '../constants/media';
-import IssueComment from '../entity/IssueComment';
-import Media from '../entity/Media';
-import notificationManager, { Notification } from '../lib/notifications';
-import { Permission } from '../lib/permissions';
-import logger from '../logger';
+import type { EntitySubscriberInterface, InsertEvent } from 'typeorm';
+import { EventSubscriber } from 'typeorm';
 
 @EventSubscriber()
 export class IssueCommentSubscriber
@@ -31,7 +28,7 @@ export class IssueCommentSubscriber
       const issue = (
         await getRepository(IssueComment).findOneOrFail({
           where: { id: entity.id },
-          relations: ['issue'],
+          relations: { issue: true },
         })
       ).issue;
 
@@ -72,6 +69,7 @@ export class IssueCommentSubscriber
           media,
           image,
           notifyAdmin: true,
+          notifySystem: true,
           notifyUser:
             !issue.createdBy.hasPermission(Permission.MANAGE_ISSUES) &&
             issue.createdBy.id !== entity.user.id
diff --git a/server/subscriber/IssueSubscriber.ts b/server/subscriber/IssueSubscriber.ts
index b593095c..eb402041 100644
--- a/server/subscriber/IssueSubscriber.ts
+++ b/server/subscriber/IssueSubscriber.ts
@@ -1,17 +1,17 @@
+import TheMovieDb from '@server/api/themoviedb';
+import { IssueStatus, IssueType, IssueTypeName } from '@server/constants/issue';
+import { MediaType } from '@server/constants/media';
+import Issue from '@server/entity/Issue';
+import notificationManager, { Notification } from '@server/lib/notifications';
+import { Permission } from '@server/lib/permissions';
+import logger from '@server/logger';
 import { sortBy } from 'lodash';
-import {
+import type {
   EntitySubscriberInterface,
-  EventSubscriber,
   InsertEvent,
   UpdateEvent,
 } from 'typeorm';
-import TheMovieDb from '../api/themoviedb';
-import { IssueStatus, IssueType, IssueTypeName } from '../constants/issue';
-import { MediaType } from '../constants/media';
-import Issue from '../entity/Issue';
-import notificationManager, { Notification } from '../lib/notifications';
-import { Permission } from '../lib/permissions';
-import logger from '../logger';
+import { EventSubscriber } from 'typeorm';
 
 @EventSubscriber()
 export class IssueSubscriber implements EntitySubscriberInterface<Issue> {
@@ -84,6 +84,7 @@ export class IssueSubscriber implements EntitySubscriberInterface<Issue> {
         image,
         extra,
         notifyAdmin: true,
+        notifySystem: true,
         notifyUser:
           !entity.createdBy.hasPermission(Permission.MANAGE_ISSUES) &&
           (type === Notification.ISSUE_RESOLVED ||
diff --git a/server/subscriber/MediaSubscriber.ts b/server/subscriber/MediaSubscriber.ts
index 01752b0d..eecfe6f3 100644
--- a/server/subscriber/MediaSubscriber.ts
+++ b/server/subscriber/MediaSubscriber.ts
@@ -1,18 +1,18 @@
-import { truncate } from 'lodash';
+import TheMovieDb from '@server/api/themoviedb';
 import {
-  EntitySubscriberInterface,
-  EventSubscriber,
-  getRepository,
-  Not,
-  UpdateEvent,
-} from 'typeorm';
-import TheMovieDb from '../api/themoviedb';
-import { MediaRequestStatus, MediaStatus, MediaType } from '../constants/media';
-import Media from '../entity/Media';
-import { MediaRequest } from '../entity/MediaRequest';
-import Season from '../entity/Season';
-import notificationManager, { Notification } from '../lib/notifications';
-import logger from '../logger';
+  MediaRequestStatus,
+  MediaStatus,
+  MediaType,
+} from '@server/constants/media';
+import { getRepository } from '@server/datasource';
+import Media from '@server/entity/Media';
+import { MediaRequest } from '@server/entity/MediaRequest';
+import Season from '@server/entity/Season';
+import notificationManager, { Notification } from '@server/lib/notifications';
+import logger from '@server/logger';
+import { truncate } from 'lodash';
+import type { EntitySubscriberInterface, UpdateEvent } from 'typeorm';
+import { EventSubscriber, In, Not } from 'typeorm';
 
 @EventSubscriber()
 export class MediaSubscriber implements EntitySubscriberInterface<Media> {
@@ -29,7 +29,9 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
         const requestRepository = getRepository(MediaRequest);
         const relatedRequests = await requestRepository.find({
           where: {
-            media: entity,
+            media: {
+              id: entity.id,
+            },
             is4k,
             status: Not(MediaRequestStatus.DECLINED),
           },
@@ -47,6 +49,7 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
                 {
                   event: `${is4k ? '4K ' : ''}Movie Request Now Available`,
                   notifyAdmin: false,
+                  notifySystem: true,
                   notifyUser: request.requestedBy,
                   subject: `${movie.title}${
                     movie.release_date
@@ -89,7 +92,7 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
       )
       .map((season) => season.seasonNumber);
     const oldSeasonIds = dbEntity.seasons.map((season) => season.id);
-    const oldSeasons = await seasonRepository.findByIds(oldSeasonIds);
+    const oldSeasons = await seasonRepository.findBy({ id: In(oldSeasonIds) });
     const oldAvailableSeasons = oldSeasons
       .filter(
         (season) =>
@@ -109,7 +112,9 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
       for (const changedSeasonNumber of changedSeasons) {
         const requests = await requestRepository.find({
           where: {
-            media: entity,
+            media: {
+              id: entity.id,
+            },
             is4k,
             status: Not(MediaRequestStatus.DECLINED),
           },
@@ -143,6 +148,7 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
                 omission: '…',
               }),
               notifyAdmin: false,
+              notifySystem: true,
               notifyUser: request.requestedBy,
               image: `https://image.tmdb.org/t/p/w600_and_h900_bestv2${tv.poster_path}`,
               media: entity,
@@ -172,7 +178,7 @@ export class MediaSubscriber implements EntitySubscriberInterface<Media> {
     const requestRepository = getRepository(MediaRequest);
 
     const requests = await requestRepository.find({
-      where: { media: event.id },
+      where: { media: { id: event.id } },
     });
 
     for (const request of requests) {
diff --git a/server/tsconfig.json b/server/tsconfig.json
index d245100d..ec4b9004 100644
--- a/server/tsconfig.json
+++ b/server/tsconfig.json
@@ -4,7 +4,11 @@
     "target": "ES2020",
     "module": "commonjs",
     "outDir": "../dist",
-    "noEmit": false
+    "noEmit": false,
+    "baseUrl": ".",
+    "paths": {
+      "@server/*": ["*"]
+    }
   },
   "include": ["**/*.ts"]
 }
diff --git a/server/types/express.d.ts b/server/types/express.d.ts
index ee7fd972..7b82477a 100644
--- a/server/types/express.d.ts
+++ b/server/types/express.d.ts
@@ -1,6 +1,6 @@
 /* eslint-disable @typescript-eslint/no-unused-vars */
+import type { User } from '@server/entity/User';
 import type { NextFunction, Request, Response } from 'express';
-import type { User } from '../entity/User';
 
 declare global {
   namespace Express {
diff --git a/server/utils/appVersion.ts b/server/utils/appVersion.ts
index 923d4708..d01a08a9 100644
--- a/server/utils/appVersion.ts
+++ b/server/utils/appVersion.ts
@@ -1,6 +1,6 @@
+import logger from '@server/logger';
 import { existsSync } from 'fs';
 import path from 'path';
-import logger from '../logger';
 
 const COMMIT_TAG_PATH = path.join(__dirname, '../../committag.json');
 let commitTag = 'local';
diff --git a/server/utils/dateHelpers.ts b/server/utils/dateHelpers.ts
new file mode 100644
index 00000000..4684d783
--- /dev/null
+++ b/server/utils/dateHelpers.ts
@@ -0,0 +1,4 @@
+import { addYears } from 'date-fns';
+import { Between } from 'typeorm';
+
+export const AfterDate = (date: Date) => Between(date, addYears(date, 100));
diff --git a/server/utils/restartFlag.ts b/server/utils/restartFlag.ts
new file mode 100644
index 00000000..387ec5ce
--- /dev/null
+++ b/server/utils/restartFlag.ts
@@ -0,0 +1,23 @@
+import type { MainSettings } from '@server/lib/settings';
+import { getSettings } from '@server/lib/settings';
+
+class RestartFlag {
+  private settings: MainSettings;
+
+  public initializeSettings(settings: MainSettings): void {
+    this.settings = { ...settings };
+  }
+
+  public isSet(): boolean {
+    const settings = getSettings().main;
+
+    return (
+      this.settings.csrfProtection !== settings.csrfProtection ||
+      this.settings.trustProxy !== settings.trustProxy
+    );
+  }
+}
+
+const restartFlag = new RestartFlag();
+
+export default restartFlag;
diff --git a/server/utils/typeHelpers.ts b/server/utils/typeHelpers.ts
index 04070244..507ece8c 100644
--- a/server/utils/typeHelpers.ts
+++ b/server/utils/typeHelpers.ts
@@ -5,7 +5,7 @@ import type {
   TmdbPersonResult,
   TmdbTvDetails,
   TmdbTvResult,
-} from '../api/themoviedb/interfaces';
+} from '@server/api/themoviedb/interfaces';
 
 export const isMovie = (
   movie: TmdbMovieResult | TmdbTvResult | TmdbPersonResult
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
index 0a7099cc..3b693643 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -8,10 +8,15 @@ description: >
 base: core18
 confinement: strict
 
+architectures:
+  - build-on: amd64
+  - build-on: arm64
+  - build-on: armhf
+
 parts:
   overseerr:
     plugin: nodejs
-    nodejs-version: '16.14.0'
+    nodejs-version: '16.17.0'
     nodejs-package-manager: 'yarn'
     nodejs-yarn-version: v1.22.17
     build-packages:
@@ -31,13 +36,16 @@ parts:
     override-pull: |
       snapcraftctl pull
       # Get information to determine snap grade and version
+      git config --global --add safe.directory /data/parts/overseerr/src
+      #setup yarn.rc
+      echo "--install.frozen-lockfile\n--install.network-timeout 1000000" > .yarnrc
       BRANCH=$(git rev-parse --abbrev-ref HEAD)
       COMMIT=$(git rev-parse HEAD)
       COMMIT_SHORT=$(git rev-parse --short HEAD)
       VERSION='v'$(cat package.json | grep 'version' | head -1 | sed 's/.*"\(.*\)"\,/\1/')
       if [ "$VERSION" = "v0.1.0" ]; then
         SNAP_VERSION=$COMMIT_SHORT
-        GRADE=devel
+        GRADE=stable
       else
         SNAP_VERSION=$VERSION
         GRADE=stable
@@ -57,6 +65,7 @@ parts:
       snapcraftctl set-grade "$GRADE"
     build-environment:
       - PATH: '$SNAPCRAFT_PART_BUILD/node_modules/.bin:$SNAPCRAFT_PART_BUILD/../npm/bin:$PATH'
+      - CYPRESS_INSTALL_BINARY: '0'
     override-build: |
       set -e
       # Set COMMIT_TAG before the build begins
@@ -77,7 +86,7 @@ parts:
     prime: [.next, ./*]
 
 apps:
-  deamon:
+  daemon:
     command: /bin/sh -c "cd $SNAP && node dist/index.js"
     daemon: simple
     restart-condition: on-failure
diff --git a/src/assets/infinity.svg b/src/assets/infinity.svg
new file mode 100644
index 00000000..054149f8
--- /dev/null
+++ b/src/assets/infinity.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.1.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M494.9 96.01c-38.78 0-75.22 15.09-102.6 42.5L320 210.8L247.8 138.5c-27.41-27.41-63.84-42.5-102.6-42.5C65.11 96.01 0 161.1 0 241.1v29.75c0 80.03 65.11 145.1 145.1 145.1c38.78 0 75.22-15.09 102.6-42.5L320 301.3l72.23 72.25c27.41 27.41 63.84 42.5 102.6 42.5C574.9 416 640 350.9 640 270.9v-29.75C640 161.1 574.9 96.01 494.9 96.01zM202.5 328.3c-15.31 15.31-35.69 23.75-57.38 23.75C100.4 352 64 315.6 64 270.9v-29.75c0-44.72 36.41-81.13 81.14-81.13c21.69 0 42.06 8.438 57.38 23.75l72.23 72.25L202.5 328.3zM576 270.9c0 44.72-36.41 81.13-81.14 81.13c-21.69 0-42.06-8.438-57.38-23.75l-72.23-72.25l72.23-72.25c15.31-15.31 35.69-23.75 57.38-23.75C539.6 160 576 196.4 576 241.1V270.9z" fill="currentColor" /></svg>
\ No newline at end of file
diff --git a/src/components/AirDateBadge/index.tsx b/src/components/AirDateBadge/index.tsx
new file mode 100644
index 00000000..fb9268f6
--- /dev/null
+++ b/src/components/AirDateBadge/index.tsx
@@ -0,0 +1,62 @@
+import Badge from '@app/components/Common/Badge';
+import { defineMessages, FormattedRelativeTime, useIntl } from 'react-intl';
+
+const messages = defineMessages({
+  airedrelative: 'Aired {relativeTime}',
+  airsrelative: 'Airing {relativeTime}',
+});
+
+type AirDateBadgeProps = {
+  airDate: string;
+};
+
+const AirDateBadge = ({ airDate }: AirDateBadgeProps) => {
+  const WEEK = 1000 * 60 * 60 * 24 * 8;
+  const intl = useIntl();
+  const dAirDate = new Date(airDate);
+  const nowDate = new Date();
+  const alreadyAired = dAirDate.getTime() < nowDate.getTime();
+
+  const compareWeek = new Date(
+    alreadyAired ? Date.now() - WEEK : Date.now() + WEEK
+  );
+
+  let showRelative = false;
+
+  if (
+    (alreadyAired && dAirDate.getTime() > compareWeek.getTime()) ||
+    (!alreadyAired && dAirDate.getTime() < compareWeek.getTime())
+  ) {
+    showRelative = true;
+  }
+
+  return (
+    <div className="flex items-center space-x-2">
+      <Badge badgeType="light">
+        {intl.formatDate(dAirDate, {
+          year: 'numeric',
+          month: 'long',
+          day: 'numeric',
+        })}
+      </Badge>
+      {showRelative && (
+        <Badge badgeType="light">
+          {intl.formatMessage(
+            alreadyAired ? messages.airedrelative : messages.airsrelative,
+            {
+              relativeTime: (
+                <FormattedRelativeTime
+                  value={(dAirDate.getTime() - Date.now()) / 1000}
+                  numeric="auto"
+                  updateIntervalInSeconds={1}
+                />
+              ),
+            }
+          )}
+        </Badge>
+      )}
+    </div>
+  );
+};
+
+export default AirDateBadge;
diff --git a/src/components/AppDataWarning/index.tsx b/src/components/AppDataWarning/index.tsx
index fce97bd5..21c3dbae 100644
--- a/src/components/AppDataWarning/index.tsx
+++ b/src/components/AppDataWarning/index.tsx
@@ -1,14 +1,13 @@
-import React from 'react';
+import Alert from '@app/components/Common/Alert';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import Alert from '../Common/Alert';
 
 const messages = defineMessages({
   dockerVolumeMissingDescription:
     'The <code>{appDataPath}</code> volume mount was not configured properly. All data will be cleared when the container is stopped or restarted.',
 });
 
-const AppDataWarning: React.FC = () => {
+const AppDataWarning = () => {
   const intl = useIntl();
   const { data, error } = useSWR<{ appData: boolean; appDataPath: string }>(
     '/api/v1/status/appdata'
@@ -27,9 +26,9 @@ const AppDataWarning: React.FC = () => {
       {!data.appData && (
         <Alert
           title={intl.formatMessage(messages.dockerVolumeMissingDescription, {
-            code: function code(msg) {
-              return <code className="bg-opacity-50">{msg}</code>;
-            },
+            code: (msg: React.ReactNode) => (
+              <code className="bg-opacity-50">{msg}</code>
+            ),
             appDataPath: data.appDataPath,
           })}
         />
diff --git a/src/components/CollectionDetails/index.tsx b/src/components/CollectionDetails/index.tsx
index 839f019a..52bd8a26 100644
--- a/src/components/CollectionDetails/index.tsx
+++ b/src/components/CollectionDetails/index.tsx
@@ -1,24 +1,24 @@
+import ButtonWithDropdown from '@app/components/Common/ButtonWithDropdown';
+import CachedImage from '@app/components/Common/CachedImage';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import RequestModal from '@app/components/RequestModal';
+import Slider from '@app/components/Slider';
+import StatusBadge from '@app/components/StatusBadge';
+import TitleCard from '@app/components/TitleCard';
+import useSettings from '@app/hooks/useSettings';
+import { Permission, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import Error from '@app/pages/_error';
 import { DownloadIcon } from '@heroicons/react/outline';
+import { MediaStatus } from '@server/constants/media';
+import type { Collection } from '@server/models/Collection';
 import { uniq } from 'lodash';
 import Link from 'next/link';
 import { useRouter } from 'next/router';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import { MediaStatus } from '../../../server/constants/media';
-import type { Collection } from '../../../server/models/Collection';
-import useSettings from '../../hooks/useSettings';
-import { Permission, useUser } from '../../hooks/useUser';
-import globalMessages from '../../i18n/globalMessages';
-import Error from '../../pages/_error';
-import ButtonWithDropdown from '../Common/ButtonWithDropdown';
-import CachedImage from '../Common/CachedImage';
-import LoadingSpinner from '../Common/LoadingSpinner';
-import PageTitle from '../Common/PageTitle';
-import RequestModal from '../RequestModal';
-import Slider from '../Slider';
-import StatusBadge from '../StatusBadge';
-import TitleCard from '../TitleCard';
 
 const messages = defineMessages({
   overview: 'Overview',
@@ -31,9 +31,7 @@ interface CollectionDetailsProps {
   collection?: Collection;
 }
 
-const CollectionDetails: React.FC<CollectionDetailsProps> = ({
-  collection,
-}) => {
+const CollectionDetails = ({ collection }: CollectionDetailsProps) => {
   const intl = useIntl();
   const router = useRouter();
   const settings = useSettings();
diff --git a/src/components/Common/Accordion/index.tsx b/src/components/Common/Accordion/index.tsx
index 67e883fe..49187bd0 100644
--- a/src/components/Common/Accordion/index.tsx
+++ b/src/components/Common/Accordion/index.tsx
@@ -1,9 +1,9 @@
-import * as React from 'react';
+import type * as React from 'react';
 import { useState } from 'react';
 import AnimateHeight from 'react-animate-height';
 
 export interface AccordionProps {
-  children: (args: AccordionChildProps) => React.ReactElement<any, any> | null;
+  children: (args: AccordionChildProps) => JSX.Element;
   /** If true, only one accordion item can be open at any time */
   single?: boolean;
   /** If true, at least one accordion item will always be open */
@@ -13,22 +13,27 @@ export interface AccordionProps {
 export interface AccordionChildProps {
   openIndexes: number[];
   handleClick(index: number): void;
-  AccordionContent: any;
+  AccordionContent: typeof AccordionContent;
 }
 
-export const AccordionContent: React.FC<{ isOpen: boolean }> = ({
+type AccordionContentProps = {
+  isOpen: boolean;
+  children: React.ReactNode;
+};
+
+export const AccordionContent = ({
   isOpen,
   children,
-}) => {
+}: AccordionContentProps) => {
   return <AnimateHeight height={isOpen ? 'auto' : 0}>{children}</AnimateHeight>;
 };
 
-const Accordion: React.FC<AccordionProps> = ({
+const Accordion = ({
   single,
   atLeastOne,
   initialOpenIndexes,
   children,
-}) => {
+}: AccordionProps) => {
   const initialState = initialOpenIndexes || (atLeastOne && [0]) || [];
   const [openIndexes, setOpenIndexes] = useState<number[]>(initialState);
 
diff --git a/src/components/Common/Alert/index.tsx b/src/components/Common/Alert/index.tsx
index e9789c70..8ffb4a25 100644
--- a/src/components/Common/Alert/index.tsx
+++ b/src/components/Common/Alert/index.tsx
@@ -3,16 +3,17 @@ import {
   InformationCircleIcon,
   XCircleIcon,
 } from '@heroicons/react/solid';
-import React from 'react';
 
 interface AlertProps {
   title?: React.ReactNode;
   type?: 'warning' | 'info' | 'error';
+  children?: React.ReactNode;
 }
 
-const Alert: React.FC<AlertProps> = ({ title, children, type }) => {
+const Alert = ({ title, children, type }: AlertProps) => {
   let design = {
-    bgColor: 'bg-yellow-600',
+    bgColor:
+      'border border-yellow-500 backdrop-blur bg-yellow-400 bg-opacity-20',
     titleColor: 'text-yellow-100',
     textColor: 'text-yellow-300',
     svg: <ExclamationIcon className="h-5 w-5" />,
@@ -21,9 +22,10 @@ const Alert: React.FC<AlertProps> = ({ title, children, type }) => {
   switch (type) {
     case 'info':
       design = {
-        bgColor: 'bg-indigo-600',
-        titleColor: 'text-indigo-100',
-        textColor: 'text-indigo-300',
+        bgColor:
+          'border border-indigo-500 backdrop-blur bg-indigo-400 bg-opacity-20',
+        titleColor: 'text-gray-100',
+        textColor: 'text-gray-300',
         svg: <InformationCircleIcon className="h-5 w-5" />,
       };
       break;
diff --git a/src/components/Common/Badge/index.tsx b/src/components/Common/Badge/index.tsx
index 33e55ab7..47ce6586 100644
--- a/src/components/Common/Badge/index.tsx
+++ b/src/components/Common/Badge/index.tsx
@@ -2,17 +2,23 @@ import Link from 'next/link';
 import React from 'react';
 
 interface BadgeProps {
-  badgeType?: 'default' | 'primary' | 'danger' | 'warning' | 'success';
+  badgeType?:
+    | 'default'
+    | 'primary'
+    | 'danger'
+    | 'warning'
+    | 'success'
+    | 'dark'
+    | 'light';
   className?: string;
   href?: string;
+  children: React.ReactNode;
 }
 
-const Badge: React.FC<BadgeProps> = ({
-  badgeType = 'default',
-  className,
-  href,
-  children,
-}) => {
+const Badge = (
+  { badgeType = 'default', className, href, children }: BadgeProps,
+  ref?: React.Ref<HTMLElement>
+) => {
   const badgeStyle = [
     'px-2 inline-flex text-xs leading-5 font-semibold rounded-full whitespace-nowrap',
   ];
@@ -25,27 +31,47 @@ const Badge: React.FC<BadgeProps> = ({
 
   switch (badgeType) {
     case 'danger':
-      badgeStyle.push('bg-red-600 !text-red-100');
+      badgeStyle.push(
+        'bg-red-600 bg-opacity-80 border-red-500 border !text-red-100'
+      );
       if (href) {
-        badgeStyle.push('hover:bg-red-500');
+        badgeStyle.push('hover:bg-red-500 bg-opacity-100');
       }
       break;
     case 'warning':
-      badgeStyle.push('bg-yellow-500 !text-yellow-100');
+      badgeStyle.push(
+        'bg-yellow-500 bg-opacity-80 border-yellow-500 border !text-yellow-100'
+      );
       if (href) {
-        badgeStyle.push('hover:bg-yellow-400');
+        badgeStyle.push('hover:bg-yellow-500 hover:bg-opacity-100');
       }
       break;
     case 'success':
-      badgeStyle.push('bg-green-500 !text-green-100');
+      badgeStyle.push(
+        'bg-green-500 bg-opacity-80 border border-green-500 !text-green-100'
+      );
       if (href) {
-        badgeStyle.push('hover:bg-green-400');
+        badgeStyle.push('hover:bg-green-500 hover:bg-opacity-100');
+      }
+      break;
+    case 'dark':
+      badgeStyle.push('bg-gray-900 !text-gray-400');
+      if (href) {
+        badgeStyle.push('hover:bg-gray-800');
+      }
+      break;
+    case 'light':
+      badgeStyle.push('bg-gray-700 !text-gray-300');
+      if (href) {
+        badgeStyle.push('hover:bg-gray-600');
       }
       break;
     default:
-      badgeStyle.push('bg-indigo-500 !text-indigo-100');
+      badgeStyle.push(
+        'bg-indigo-500 bg-opacity-80 border border-indigo-500 !text-indigo-100'
+      );
       if (href) {
-        badgeStyle.push('hover:bg-indigo-400');
+        badgeStyle.push('hover:bg-indigo-500 bg-opacity-100');
       }
   }
 
@@ -60,6 +86,7 @@ const Badge: React.FC<BadgeProps> = ({
         target="_blank"
         rel="noopener noreferrer"
         className={badgeStyle.join(' ')}
+        ref={ref as React.Ref<HTMLAnchorElement>}
       >
         {children}
       </a>
@@ -67,12 +94,24 @@ const Badge: React.FC<BadgeProps> = ({
   } else if (href) {
     return (
       <Link href={href}>
-        <a className={badgeStyle.join(' ')}>{children}</a>
+        <a
+          className={badgeStyle.join(' ')}
+          ref={ref as React.Ref<HTMLAnchorElement>}
+        >
+          {children}
+        </a>
       </Link>
     );
   } else {
-    return <span className={badgeStyle.join(' ')}>{children}</span>;
+    return (
+      <span
+        className={badgeStyle.join(' ')}
+        ref={ref as React.Ref<HTMLSpanElement>}
+      >
+        {children}
+      </span>
+    );
   }
 };
 
-export default Badge;
+export default React.forwardRef(Badge) as typeof Badge;
diff --git a/src/components/Common/Button/index.tsx b/src/components/Common/Button/index.tsx
index f1083e5b..d3f96ae9 100644
--- a/src/components/Common/Button/index.tsx
+++ b/src/components/Common/Button/index.tsx
@@ -1,4 +1,5 @@
-import React, { ForwardedRef } from 'react';
+import type { ForwardedRef } from 'react';
+import React from 'react';
 
 export type ButtonType =
   | 'default'
@@ -50,22 +51,22 @@ function Button<P extends ElementTypes = 'button'>(
   switch (buttonType) {
     case 'primary':
       buttonStyle.push(
-        'text-white bg-indigo-600 border-indigo-600 hover:bg-indigo-500 hover:border-indigo-500 focus:border-indigo-700 focus:ring-indigo active:bg-indigo-700 active:border-indigo-700'
+        'text-white border border-indigo-500 bg-indigo-600 bg-opacity-80 hover:bg-opacity-100 hover:border-indigo-500 focus:border-indigo-700 focus:ring-indigo active:bg-opacity-100 active:border-indigo-700'
       );
       break;
     case 'danger':
       buttonStyle.push(
-        'text-white bg-red-600 border-red-600 hover:bg-red-500 hover:border-red-500 focus:border-red-700 focus:ring-red active:bg-red-700 active:border-red-700'
+        'text-white bg-red-600 bg-opacity-80 border-red-500 hover:bg-opacity-100 hover:border-red-500 focus:border-red-700 focus:ring-red active:bg-red-700 active:border-red-700'
       );
       break;
     case 'warning':
       buttonStyle.push(
-        'text-white bg-yellow-500 border-yellow-500 hover:bg-yellow-400 hover:border-yellow-400 focus:border-yellow-700 focus:ring-yellow active:bg-yellow-700 active:border-yellow-700'
+        'text-white border border-yellow-500 backdrop-blur bg-yellow-500 bg-opacity-80 hover:bg-opacity-100 hover:border-yellow-400 focus:border-yellow-700 focus:ring-yellow active:bg-opacity-100 active:border-yellow-700'
       );
       break;
     case 'success':
       buttonStyle.push(
-        'text-white bg-green-500 border-green-500 hover:bg-green-400 hover:border-green-400 focus:border-green-700 focus:ring-green active:bg-green-700 active:border-green-700'
+        'text-white bg-green-500 bg-opacity-80 border-green-500 hover:bg-opacity-100 hover:border-green-400 focus:border-green-700 focus:ring-green active:bg-opacity-100 active:border-green-700'
       );
       break;
     case 'ghost':
@@ -75,7 +76,7 @@ function Button<P extends ElementTypes = 'button'>(
       break;
     default:
       buttonStyle.push(
-        'text-gray-200 bg-gray-600 border-gray-600 hover:text-white hover:bg-gray-500 hover:border-gray-500 group-hover:text-white group-hover:bg-gray-500 group-hover:border-gray-500 focus:border-blue-300 focus:ring-blue active:text-gray-200 active:bg-gray-500 active:border-gray-500'
+        'text-gray-200 bg-gray-800 bg-opacity-80 border-gray-600 hover:text-white hover:bg-gray-700 hover:border-gray-600 group-hover:text-white group-hover:bg-gray-700 group-hover:border-gray-600 focus:border-blue-300 focus:ring-blue active:text-gray-200 active:bg-gray-700 active:border-gray-600'
       );
   }
 
diff --git a/src/components/Common/ButtonWithDropdown/index.tsx b/src/components/Common/ButtonWithDropdown/index.tsx
index 6edb4a11..be6815b9 100644
--- a/src/components/Common/ButtonWithDropdown/index.tsx
+++ b/src/components/Common/ButtonWithDropdown/index.tsx
@@ -1,34 +1,29 @@
+import useClickOutside from '@app/hooks/useClickOutside';
+import { withProperties } from '@app/utils/typeHelpers';
+import { Transition } from '@headlessui/react';
 import { ChevronDownIcon } from '@heroicons/react/solid';
-import React, {
-  AnchorHTMLAttributes,
-  ButtonHTMLAttributes,
-  ReactNode,
-  useRef,
-  useState,
-} from 'react';
-import useClickOutside from '../../../hooks/useClickOutside';
-import { withProperties } from '../../../utils/typeHelpers';
-import Transition from '../../Transition';
+import type { AnchorHTMLAttributes, ButtonHTMLAttributes } from 'react';
+import { Fragment, useRef, useState } from 'react';
 
 interface DropdownItemProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
   buttonType?: 'primary' | 'ghost';
 }
 
-const DropdownItem: React.FC<DropdownItemProps> = ({
+const DropdownItem = ({
   children,
   buttonType = 'primary',
   ...props
-}) => {
+}: DropdownItemProps) => {
   let styleClass = 'button-md text-white';
 
   switch (buttonType) {
     case 'ghost':
       styleClass +=
-        ' bg-gray-700 hover:bg-gray-600 focus:border-gray-500 focus:text-white';
+        ' bg-transparent rounded hover:bg-gradient-to-br from-indigo-600 to-purple-600 text-white focus:border-gray-500 focus:text-white';
       break;
     default:
       styleClass +=
-        ' bg-indigo-600 hover:bg-indigo-500 focus:border-indigo-700 focus:text-white';
+        ' bg-indigo-600 rounded hover:bg-indigo-500 focus:border-indigo-700 focus:text-white';
   }
   return (
     <a
@@ -42,19 +37,19 @@ const DropdownItem: React.FC<DropdownItemProps> = ({
 
 interface ButtonWithDropdownProps
   extends ButtonHTMLAttributes<HTMLButtonElement> {
-  text: ReactNode;
-  dropdownIcon?: ReactNode;
+  text: React.ReactNode;
+  dropdownIcon?: React.ReactNode;
   buttonType?: 'primary' | 'ghost';
 }
 
-const ButtonWithDropdown: React.FC<ButtonWithDropdownProps> = ({
+const ButtonWithDropdown = ({
   text,
   children,
   dropdownIcon,
   className,
   buttonType = 'primary',
   ...props
-}) => {
+}: ButtonWithDropdownProps) => {
   const [isOpen, setIsOpen] = useState(false);
   const buttonRef = useRef<HTMLButtonElement>(null);
   useClickOutside(buttonRef, () => setIsOpen(false));
@@ -70,14 +65,15 @@ const ButtonWithDropdown: React.FC<ButtonWithDropdownProps> = ({
       styleClasses.mainButtonClasses +=
         ' bg-transparent border-gray-600 hover:border-gray-200 focus:border-gray-100 active:border-gray-100';
       styleClasses.dropdownSideButtonClasses = styleClasses.mainButtonClasses;
-      styleClasses.dropdownClasses += ' bg-gray-700';
+      styleClasses.dropdownClasses +=
+        ' bg-gray-800 border border-gray-700 bg-opacity-80 p-1 backdrop-blur';
       break;
     default:
       styleClasses.mainButtonClasses +=
-        ' bg-indigo-600 border-indigo-600 hover:bg-indigo-500 hover:border-indigo-500 active:bg-indigo-700 active:border-indigo-700 focus:ring-blue';
+        ' bg-indigo-600 border-indigo-500 bg-opacity-80 hover:bg-opacity-100 hover:border-indigo-500 active:bg-indigo-700 active:border-indigo-700 focus:ring-blue';
       styleClasses.dropdownSideButtonClasses +=
-        ' bg-indigo-700 border-indigo-600 hover:bg-indigo-500 active:bg-indigo-700 focus:ring-blue';
-      styleClasses.dropdownClasses += ' bg-indigo-600';
+        ' bg-indigo-600 bg-opacity-80 border-indigo-500 hover:bg-opacity-100 active:bg-opacity-100 focus:ring-blue';
+      styleClasses.dropdownClasses += ' bg-indigo-600 p-1';
   }
 
   return (
@@ -103,6 +99,7 @@ const ButtonWithDropdown: React.FC<ButtonWithDropdownProps> = ({
             {dropdownIcon ? dropdownIcon : <ChevronDownIcon />}
           </button>
           <Transition
+            as={Fragment}
             show={isOpen}
             enter="transition ease-out duration-100 opacity-0"
             enterFrom="transform opacity-0 scale-95"
diff --git a/src/components/Common/CachedImage/index.tsx b/src/components/Common/CachedImage/index.tsx
index c91f0946..b1695937 100644
--- a/src/components/Common/CachedImage/index.tsx
+++ b/src/components/Common/CachedImage/index.tsx
@@ -1,6 +1,6 @@
-import Image, { ImageProps } from 'next/image';
-import React from 'react';
-import useSettings from '../../../hooks/useSettings';
+import useSettings from '@app/hooks/useSettings';
+import type { ImageProps } from 'next/image';
+import Image from 'next/image';
 
 /**
  * The CachedImage component should be used wherever
@@ -9,7 +9,7 @@ import useSettings from '../../../hooks/useSettings';
  * It uses the `next/image` Image component but overrides
  * the `unoptimized` prop based on the application setting `cacheImages`.
  **/
-const CachedImage: React.FC<ImageProps> = (props) => {
+const CachedImage = (props: ImageProps) => {
   const { currentSettings } = useSettings();
 
   return <Image unoptimized={!currentSettings.cacheImages} {...props} />;
diff --git a/src/components/Common/ConfirmButton/index.tsx b/src/components/Common/ConfirmButton/index.tsx
index df3c6572..1f5756cb 100644
--- a/src/components/Common/ConfirmButton/index.tsx
+++ b/src/components/Common/ConfirmButton/index.tsx
@@ -1,19 +1,20 @@
-import React, { useRef, useState } from 'react';
-import useClickOutside from '../../../hooks/useClickOutside';
-import Button from '../Button';
+import Button from '@app/components/Common/Button';
+import useClickOutside from '@app/hooks/useClickOutside';
+import { useRef, useState } from 'react';
 
 interface ConfirmButtonProps {
   onClick: () => void;
   confirmText: React.ReactNode;
   className?: string;
+  children: React.ReactNode;
 }
 
-const ConfirmButton: React.FC<ConfirmButtonProps> = ({
+const ConfirmButton = ({
   onClick,
   children,
   confirmText,
   className,
-}) => {
+}: ConfirmButtonProps) => {
   const ref = useRef(null);
   useClickOutside(ref, () => setIsClicked(false));
   const [isClicked, setIsClicked] = useState(false);
diff --git a/src/components/Common/Header/index.tsx b/src/components/Common/Header/index.tsx
index b7c88ddd..1653a457 100644
--- a/src/components/Common/Header/index.tsx
+++ b/src/components/Common/Header/index.tsx
@@ -1,22 +1,18 @@
-import React from 'react';
-
 interface HeaderProps {
   extraMargin?: number;
   subtext?: React.ReactNode;
+  children: React.ReactNode;
 }
 
-const Header: React.FC<HeaderProps> = ({
-  children,
-  extraMargin = 0,
-  subtext,
-}) => {
+const Header = ({ children, extraMargin = 0, subtext }: HeaderProps) => {
   return (
     <div className="mt-8 md:flex md:items-center md:justify-between">
       <div className={`min-w-0 flex-1 mx-${extraMargin}`}>
-        <h2 className="mb-4 truncate text-2xl font-bold leading-7 text-gray-100 sm:overflow-visible sm:text-4xl sm:leading-9 md:mb-0">
-          <span className="bg-gradient-to-br from-indigo-400 to-purple-400 bg-clip-text text-transparent">
-            {children}
-          </span>
+        <h2
+          className="mb-4 truncate text-2xl font-bold leading-7 text-gray-100 sm:overflow-visible sm:text-4xl sm:leading-9 md:mb-0"
+          data-testid="page-header"
+        >
+          <span className="text-overseerr">{children}</span>
         </h2>
         {subtext && <div className="mt-2 text-gray-400">{subtext}</div>}
       </div>
diff --git a/src/components/Common/ImageFader/index.tsx b/src/components/Common/ImageFader/index.tsx
index 5f68376c..a5717241 100644
--- a/src/components/Common/ImageFader/index.tsx
+++ b/src/components/Common/ImageFader/index.tsx
@@ -1,10 +1,6 @@
-import React, {
-  ForwardRefRenderFunction,
-  HTMLAttributes,
-  useEffect,
-  useState,
-} from 'react';
-import CachedImage from '../CachedImage';
+import CachedImage from '@app/components/Common/CachedImage';
+import type { ForwardRefRenderFunction, HTMLAttributes } from 'react';
+import React, { useEffect, useState } from 'react';
 
 interface ImageFaderProps extends HTMLAttributes<HTMLDivElement> {
   backgroundImages: string[];
diff --git a/src/components/Common/List/index.tsx b/src/components/Common/List/index.tsx
index a4b91723..32057ed1 100644
--- a/src/components/Common/List/index.tsx
+++ b/src/components/Common/List/index.tsx
@@ -1,12 +1,12 @@
-import React from 'react';
-import { withProperties } from '../../../utils/typeHelpers';
+import { withProperties } from '@app/utils/typeHelpers';
 
 interface ListItemProps {
   title: string;
   className?: string;
+  children: React.ReactNode;
 }
 
-const ListItem: React.FC<ListItemProps> = ({ title, className, children }) => {
+const ListItem = ({ title, className, children }: ListItemProps) => {
   return (
     <div>
       <div className="max-w-6xl py-4 sm:grid sm:grid-cols-3 sm:gap-4">
@@ -22,9 +22,10 @@ const ListItem: React.FC<ListItemProps> = ({ title, className, children }) => {
 interface ListProps {
   title: string;
   subTitle?: string;
+  children: React.ReactNode;
 }
 
-const List: React.FC<ListProps> = ({ title, subTitle, children }) => {
+const List = ({ title, subTitle, children }: ListProps) => {
   return (
     <>
       <div>
diff --git a/src/components/Common/ListView/index.tsx b/src/components/Common/ListView/index.tsx
index 0c2a0e4e..6f09f768 100644
--- a/src/components/Common/ListView/index.tsx
+++ b/src/components/Common/ListView/index.tsx
@@ -1,30 +1,33 @@
-import React from 'react';
-import { useIntl } from 'react-intl';
-import {
+import PersonCard from '@app/components/PersonCard';
+import TitleCard from '@app/components/TitleCard';
+import TmdbTitleCard from '@app/components/TitleCard/TmdbTitleCard';
+import useVerticalScroll from '@app/hooks/useVerticalScroll';
+import globalMessages from '@app/i18n/globalMessages';
+import type { WatchlistItem } from '@server/interfaces/api/discoverInterfaces';
+import type {
   MovieResult,
   PersonResult,
   TvResult,
-} from '../../../../server/models/Search';
-import useVerticalScroll from '../../../hooks/useVerticalScroll';
-import globalMessages from '../../../i18n/globalMessages';
-import PersonCard from '../../PersonCard';
-import TitleCard from '../../TitleCard';
+} from '@server/models/Search';
+import { useIntl } from 'react-intl';
 
-interface ListViewProps {
+type ListViewProps = {
   items?: (TvResult | MovieResult | PersonResult)[];
+  plexItems?: WatchlistItem[];
   isEmpty?: boolean;
   isLoading?: boolean;
   isReachingEnd?: boolean;
   onScrollBottom: () => void;
-}
+};
 
-const ListView: React.FC<ListViewProps> = ({
+const ListView = ({
   items,
   isEmpty,
   isLoading,
   onScrollBottom,
   isReachingEnd,
-}) => {
+  plexItems,
+}: ListViewProps) => {
   const intl = useIntl();
   useVerticalScroll(onScrollBottom, !isLoading && !isEmpty && !isReachingEnd);
   return (
@@ -35,6 +38,18 @@ const ListView: React.FC<ListViewProps> = ({
         </div>
       )}
       <ul className="cards-vertical">
+        {plexItems?.map((title, index) => {
+          return (
+            <li key={`${title.ratingKey}-${index}`}>
+              <TmdbTitleCard
+                id={title.tmdbId}
+                tmdbId={title.tmdbId}
+                type={title.mediaType}
+                canExpand
+              />
+            </li>
+          );
+        })}
         {items?.map((title, index) => {
           let titleCard: React.ReactNode;
 
diff --git a/src/components/Common/LoadingSpinner/index.tsx b/src/components/Common/LoadingSpinner/index.tsx
index be65f009..8f922ef3 100644
--- a/src/components/Common/LoadingSpinner/index.tsx
+++ b/src/components/Common/LoadingSpinner/index.tsx
@@ -1,6 +1,4 @@
-import React from 'react';
-
-export const SmallLoadingSpinner: React.FC = () => {
+export const SmallLoadingSpinner = () => {
   return (
     <div className="inset-0 flex h-full w-full items-center justify-center text-gray-200">
       <svg
@@ -29,7 +27,7 @@ export const SmallLoadingSpinner: React.FC = () => {
   );
 };
 
-const LoadingSpinner: React.FC = () => {
+const LoadingSpinner = () => {
   return (
     <div className="inset-0 flex h-64 items-center justify-center text-gray-200">
       <svg
diff --git a/src/components/Common/Modal/index.tsx b/src/components/Common/Modal/index.tsx
index ac8d9fea..0d7eff19 100644
--- a/src/components/Common/Modal/index.tsx
+++ b/src/components/Common/Modal/index.tsx
@@ -1,16 +1,19 @@
-import React, { MouseEvent, ReactNode, useRef } from 'react';
+import type { ButtonType } from '@app/components/Common/Button';
+import Button from '@app/components/Common/Button';
+import CachedImage from '@app/components/Common/CachedImage';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import useClickOutside from '@app/hooks/useClickOutside';
+import { useLockBodyScroll } from '@app/hooks/useLockBodyScroll';
+import globalMessages from '@app/i18n/globalMessages';
+import { Transition } from '@headlessui/react';
+import type { MouseEvent } from 'react';
+import React, { Fragment, useRef } from 'react';
 import ReactDOM from 'react-dom';
 import { useIntl } from 'react-intl';
-import useClickOutside from '../../../hooks/useClickOutside';
-import { useLockBodyScroll } from '../../../hooks/useLockBodyScroll';
-import globalMessages from '../../../i18n/globalMessages';
-import Transition from '../../Transition';
-import Button, { ButtonType } from '../Button';
-import CachedImage from '../CachedImage';
-import LoadingSpinner from '../LoadingSpinner';
 
 interface ModalProps {
   title?: string;
+  subTitle?: string;
   onCancel?: (e?: MouseEvent<HTMLElement>) => void;
   onOk?: (e?: MouseEvent<HTMLButtonElement>) => void;
   onSecondary?: (e?: MouseEvent<HTMLButtonElement>) => void;
@@ -28,87 +31,94 @@ interface ModalProps {
   tertiaryButtonType?: ButtonType;
   disableScrollLock?: boolean;
   backgroundClickable?: boolean;
-  iconSvg?: ReactNode;
   loading?: boolean;
   backdrop?: string;
+  children?: React.ReactNode;
 }
 
-const Modal: React.FC<ModalProps> = ({
-  title,
-  onCancel,
-  onOk,
-  cancelText,
-  okText,
-  okDisabled = false,
-  cancelButtonType = 'default',
-  okButtonType = 'primary',
-  children,
-  disableScrollLock,
-  backgroundClickable = true,
-  iconSvg,
-  loading = false,
-  secondaryButtonType = 'default',
-  secondaryDisabled = false,
-  onSecondary,
-  secondaryText,
-  tertiaryButtonType = 'default',
-  tertiaryDisabled = false,
-  tertiaryText,
-  onTertiary,
-  backdrop,
-}) => {
-  const intl = useIntl();
-  const modalRef = useRef<HTMLDivElement>(null);
-  useClickOutside(modalRef, () => {
-    typeof onCancel === 'function' && backgroundClickable
-      ? onCancel()
-      : undefined;
-  });
-  useLockBodyScroll(true, disableScrollLock);
+const Modal = React.forwardRef<HTMLDivElement, ModalProps>(
+  (
+    {
+      title,
+      subTitle,
+      onCancel,
+      onOk,
+      cancelText,
+      okText,
+      okDisabled = false,
+      cancelButtonType = 'default',
+      okButtonType = 'primary',
+      children,
+      disableScrollLock,
+      backgroundClickable = true,
+      secondaryButtonType = 'default',
+      secondaryDisabled = false,
+      onSecondary,
+      secondaryText,
+      tertiaryButtonType = 'default',
+      tertiaryDisabled = false,
+      tertiaryText,
+      loading = false,
+      onTertiary,
+      backdrop,
+    },
+    parentRef
+  ) => {
+    const intl = useIntl();
+    const modalRef = useRef<HTMLDivElement>(null);
+    useClickOutside(modalRef, () => {
+      if (onCancel && backgroundClickable) {
+        onCancel();
+      }
+    });
+    useLockBodyScroll(true, disableScrollLock);
 
-  return ReactDOM.createPortal(
-    // eslint-disable-next-line jsx-a11y/no-static-element-interactions
-    <div
-      className="fixed top-0 bottom-0 left-0 right-0 z-50 flex h-full w-full items-center justify-center bg-gray-800 bg-opacity-70"
-      onKeyDown={(e) => {
-        if (e.key === 'Escape') {
-          typeof onCancel === 'function' && backgroundClickable
-            ? onCancel()
-            : undefined;
-        }
-      }}
-    >
-      <Transition
-        enter="transition opacity-0 duration-300 transform scale-75"
-        enterFrom="opacity-0 scale-75"
-        enterTo="opacity-100 scale-100"
+    return ReactDOM.createPortal(
+      <Transition.Child
+        appear
+        as="div"
+        className="fixed top-0 bottom-0 left-0 right-0 z-50 flex h-full w-full items-center justify-center bg-gray-800 bg-opacity-70"
+        enter="transition opacity-0 duration-300"
+        enterFrom="opacity-0"
+        enterTo="opacity-100"
         leave="transition opacity-100 duration-300"
         leaveFrom="opacity-100"
         leaveTo="opacity-0"
-        show={loading}
+        ref={parentRef}
       >
-        <div style={{ position: 'absolute' }}>
-          <LoadingSpinner />
-        </div>
-      </Transition>
-      <Transition
-        enter="transition opacity-0 duration-300 transform scale-75"
-        enterFrom="opacity-0 scale-75"
-        enterTo="opacity-100 scale-100"
-        leave="transition opacity-100 duration-300"
-        leaveFrom="opacity-100"
-        leaveTo="opacity-0"
-        show={!loading}
-      >
-        <div
-          className="relative inline-block w-full transform overflow-auto bg-gray-700 px-4 pt-5 pb-4 text-left align-bottom shadow-xl ring-1 ring-gray-500 transition-all sm:my-8 sm:max-w-3xl sm:rounded-lg sm:align-middle"
+        <Transition
+          appear
+          as={Fragment}
+          enter="transition opacity-0 duration-300 transform scale-75"
+          enterFrom="opacity-0 scale-75"
+          enterTo="opacity-100 scale-100"
+          leave="transition opacity-100 duration-300"
+          leaveFrom="opacity-100"
+          leaveTo="opacity-0"
+          show={loading}
+        >
+          <div style={{ position: 'absolute' }}>
+            <LoadingSpinner />
+          </div>
+        </Transition>
+        <Transition
+          className="hide-scrollbar relative inline-block w-full transform overflow-auto bg-gray-800 px-4 pt-4 pb-4 text-left align-bottom shadow-xl ring-1 ring-gray-700 transition-all sm:my-8 sm:max-w-3xl sm:rounded-lg sm:align-middle"
           role="dialog"
           aria-modal="true"
           aria-labelledby="modal-headline"
-          ref={modalRef}
           style={{
             maxHeight: 'calc(100% - env(safe-area-inset-top) * 2)',
           }}
+          appear
+          as="div"
+          enter="transition opacity-0 duration-300 transform scale-75"
+          enterFrom="opacity-0 scale-75"
+          enterTo="opacity-100 scale-100"
+          leave="transition opacity-100 duration-300"
+          leaveFrom="opacity-100"
+          leaveTo="opacity-0"
+          show={!loading}
+          ref={modalRef}
         >
           {backdrop && (
             <div className="absolute top-0 left-0 right-0 z-0 h-64 max-h-full w-full">
@@ -123,30 +133,45 @@ const Modal: React.FC<ModalProps> = ({
                 className="absolute inset-0"
                 style={{
                   backgroundImage:
-                    'linear-gradient(180deg, rgba(55, 65, 81, 0.85) 0%, rgba(55, 65, 81, 1) 100%)',
+                    'linear-gradient(180deg, rgba(31, 41, 55, 0.75) 0%, rgba(31, 41, 55, 1) 100%)',
                 }}
               />
             </div>
           )}
-          <div className="relative overflow-x-hidden sm:flex sm:items-center">
-            {iconSvg && <div className="modal-icon">{iconSvg}</div>}
+          <div className="relative -mx-4 overflow-x-hidden px-4 pt-0.5 sm:flex sm:items-center">
             <div
-              className={`mt-3 truncate text-center text-white sm:mt-0 sm:text-left ${
-                iconSvg ? 'sm:ml-4' : 'sm:mb-4'
-              }`}
+              className={`mt-3 truncate text-center text-white sm:mt-0 sm:text-left`}
             >
-              {title && (
-                <span
-                  className="truncate text-lg font-bold leading-6"
-                  id="modal-headline"
-                >
-                  {title}
-                </span>
+              {(title || subTitle) && (
+                <div className="flex flex-col space-y-1">
+                  {title && (
+                    <span
+                      className="text-overseerr truncate pb-0.5 text-2xl font-bold leading-6"
+                      id="modal-headline"
+                      data-testid="modal-title"
+                    >
+                      {title}
+                    </span>
+                  )}
+                  {subTitle && (
+                    <span
+                      className="truncate text-lg font-semibold leading-6 text-gray-200"
+                      id="modal-headline"
+                      data-testid="modal-title"
+                    >
+                      {subTitle}
+                    </span>
+                  )}
+                </div>
               )}
             </div>
           </div>
           {children && (
-            <div className="relative mt-4 text-sm leading-5 text-gray-300">
+            <div
+              className={`relative mt-4 text-sm leading-5 text-gray-300 ${
+                !(onCancel || onOk || onSecondary || onTertiary) ? 'mb-3' : ''
+              }`}
+            >
               {children}
             </div>
           )}
@@ -158,6 +183,7 @@ const Modal: React.FC<ModalProps> = ({
                   onClick={onOk}
                   className="ml-3"
                   disabled={okDisabled}
+                  data-testid="modal-ok-button"
                 >
                   {okText ? okText : 'Ok'}
                 </Button>
@@ -168,6 +194,7 @@ const Modal: React.FC<ModalProps> = ({
                   onClick={onSecondary}
                   className="ml-3"
                   disabled={secondaryDisabled}
+                  data-testid="modal-secondary-button"
                 >
                   {secondaryText}
                 </Button>
@@ -187,6 +214,7 @@ const Modal: React.FC<ModalProps> = ({
                   buttonType={cancelButtonType}
                   onClick={onCancel}
                   className="ml-3 sm:ml-0"
+                  data-testid="modal-cancel-button"
                 >
                   {cancelText
                     ? cancelText
@@ -195,11 +223,13 @@ const Modal: React.FC<ModalProps> = ({
               )}
             </div>
           )}
-        </div>
-      </Transition>
-    </div>,
-    document.body
-  );
-};
+        </Transition>
+      </Transition.Child>,
+      document.body
+    );
+  }
+);
+
+Modal.displayName = 'Modal';
 
 export default Modal;
diff --git a/src/components/Common/PageTitle/index.tsx b/src/components/Common/PageTitle/index.tsx
index a7224b22..288a0b37 100644
--- a/src/components/Common/PageTitle/index.tsx
+++ b/src/components/Common/PageTitle/index.tsx
@@ -1,20 +1,20 @@
-import React from 'react';
-import useSettings from '../../../hooks/useSettings';
+import useSettings from '@app/hooks/useSettings';
 import Head from 'next/head';
 
 interface PageTitleProps {
   title: string | (string | undefined)[];
 }
 
-const PageTitle: React.FC<PageTitleProps> = ({ title }) => {
+const PageTitle = ({ title }: PageTitleProps) => {
   const settings = useSettings();
 
+  const titleText = `${
+    Array.isArray(title) ? title.filter(Boolean).join(' - ') : title
+  } - ${settings.currentSettings.applicationTitle}`;
+
   return (
     <Head>
-      <title>
-        {Array.isArray(title) ? title.filter(Boolean).join(' - ') : title} -{' '}
-        {settings.currentSettings.applicationTitle}
-      </title>
+      <title>{titleText}</title>
     </Head>
   );
 };
diff --git a/src/components/Common/PlayButton/index.tsx b/src/components/Common/PlayButton/index.tsx
index c41935ae..01d3a012 100644
--- a/src/components/Common/PlayButton/index.tsx
+++ b/src/components/Common/PlayButton/index.tsx
@@ -1,5 +1,4 @@
-import React, { ReactNode } from 'react';
-import ButtonWithDropdown from '../ButtonWithDropdown';
+import ButtonWithDropdown from '@app/components/Common/ButtonWithDropdown';
 
 interface PlayButtonProps {
   links: PlayButtonLink[];
@@ -8,10 +7,10 @@ interface PlayButtonProps {
 export interface PlayButtonLink {
   text: string;
   url: string;
-  svg: ReactNode;
+  svg: React.ReactNode;
 }
 
-const PlayButton: React.FC<PlayButtonProps> = ({ links }) => {
+const PlayButton = ({ links }: PlayButtonProps) => {
   if (!links || !links.length) {
     return null;
   }
diff --git a/src/components/Common/ProgressCircle/index.tsx b/src/components/Common/ProgressCircle/index.tsx
index 64ca49c1..7df2b041 100644
--- a/src/components/Common/ProgressCircle/index.tsx
+++ b/src/components/Common/ProgressCircle/index.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useRef } from 'react';
+import { useEffect, useRef } from 'react';
 
 interface ProgressCircleProps {
   className?: string;
@@ -6,11 +6,11 @@ interface ProgressCircleProps {
   useHeatLevel?: boolean;
 }
 
-const ProgressCircle: React.FC<ProgressCircleProps> = ({
+const ProgressCircle = ({
   className,
   progress = 0,
   useHeatLevel,
-}) => {
+}: ProgressCircleProps) => {
   const ref = useRef<SVGCircleElement>(null);
 
   let color = '';
diff --git a/src/components/Common/SensitiveInput/index.tsx b/src/components/Common/SensitiveInput/index.tsx
index 886fd721..6652f551 100644
--- a/src/components/Common/SensitiveInput/index.tsx
+++ b/src/components/Common/SensitiveInput/index.tsx
@@ -1,6 +1,6 @@
 import { EyeIcon, EyeOffIcon } from '@heroicons/react/solid';
 import { Field } from 'formik';
-import React, { useState } from 'react';
+import { useState } from 'react';
 
 interface CustomInputProps extends React.ComponentProps<'input'> {
   as?: 'input';
@@ -12,10 +12,7 @@ interface CustomFieldProps extends React.ComponentProps<typeof Field> {
 
 type SensitiveInputProps = CustomInputProps | CustomFieldProps;
 
-const SensitiveInput: React.FC<SensitiveInputProps> = ({
-  as = 'input',
-  ...props
-}) => {
+const SensitiveInput = ({ as = 'input', ...props }: SensitiveInputProps) => {
   const [isHidden, setHidden] = useState(true);
   const Component = as === 'input' ? 'input' : Field;
   const componentProps =
diff --git a/src/components/Common/SettingsTabs/index.tsx b/src/components/Common/SettingsTabs/index.tsx
index 75158705..8ee46fea 100644
--- a/src/components/Common/SettingsTabs/index.tsx
+++ b/src/components/Common/SettingsTabs/index.tsx
@@ -1,8 +1,8 @@
+import { useUser } from '@app/hooks/useUser';
+import type { Permission } from '@server/lib/permissions';
+import { hasPermission } from '@server/lib/permissions';
 import Link from 'next/link';
 import { useRouter } from 'next/router';
-import React from 'react';
-import { hasPermission, Permission } from '../../../../server/lib/permissions';
-import { useUser } from '../../../hooks/useUser';
 
 export interface SettingsRoute {
   text: string;
@@ -14,14 +14,17 @@ export interface SettingsRoute {
   hidden?: boolean;
 }
 
-const SettingsLink: React.FC<{
+type SettingsLinkProps = {
   tabType: 'default' | 'button';
   currentPath: string;
   route: string;
   regex: RegExp;
   hidden?: boolean;
   isMobile?: boolean;
-}> = ({
+  children: React.ReactNode;
+};
+
+const SettingsLink = ({
   children,
   tabType,
   currentPath,
@@ -29,7 +32,7 @@ const SettingsLink: React.FC<{
   regex,
   hidden = false,
   isMobile = false,
-}) => {
+}: SettingsLinkProps) => {
   if (hidden) {
     return null;
   }
@@ -65,10 +68,13 @@ const SettingsLink: React.FC<{
   );
 };
 
-const SettingsTabs: React.FC<{
+const SettingsTabs = ({
+  tabType = 'default',
+  settingsRoutes,
+}: {
   tabType?: 'default' | 'button';
   settingsRoutes: SettingsRoute[];
-}> = ({ tabType = 'default', settingsRoutes }) => {
+}) => {
   const router = useRouter();
   const { user: currentUser } = useUser();
 
@@ -137,7 +143,7 @@ const SettingsTabs: React.FC<{
         </div>
       ) : (
         <div className="hide-scrollbar hidden overflow-x-scroll border-b border-gray-600 sm:block">
-          <nav className="flex">
+          <nav className="flex" data-testid="settings-nav-desktop">
             {settingsRoutes
               .filter(
                 (route) =>
diff --git a/src/components/Common/SlideOver/index.tsx b/src/components/Common/SlideOver/index.tsx
index 6fadb706..e7ccf706 100644
--- a/src/components/Common/SlideOver/index.tsx
+++ b/src/components/Common/SlideOver/index.tsx
@@ -1,24 +1,25 @@
 /* eslint-disable jsx-a11y/click-events-have-key-events */
+import { useLockBodyScroll } from '@app/hooks/useLockBodyScroll';
+import { Transition } from '@headlessui/react';
 import { XIcon } from '@heroicons/react/outline';
-import React, { useEffect, useRef, useState } from 'react';
+import { Fragment, useEffect, useRef, useState } from 'react';
 import ReactDOM from 'react-dom';
-import { useLockBodyScroll } from '../../../hooks/useLockBodyScroll';
-import Transition from '../../Transition';
 
 interface SlideOverProps {
   show?: boolean;
   title: React.ReactNode;
   subText?: string;
   onClose: () => void;
+  children: React.ReactNode;
 }
 
-const SlideOver: React.FC<SlideOverProps> = ({
+const SlideOver = ({
   show = false,
   title,
   subText,
   onClose,
   children,
-}) => {
+}: SlideOverProps) => {
   const [isMounted, setIsMounted] = useState(false);
   const slideoverRef = useRef(null);
   useLockBodyScroll(show);
@@ -33,6 +34,7 @@ const SlideOver: React.FC<SlideOverProps> = ({
 
   return ReactDOM.createPortal(
     <Transition
+      as={Fragment}
       show={show}
       appear
       enter="opacity-0 transition ease-in-out duration-300"
@@ -53,9 +55,8 @@ const SlideOver: React.FC<SlideOverProps> = ({
         }}
       >
         <div className="absolute inset-0 overflow-hidden">
-          <section className="absolute inset-y-0 right-0 flex max-w-full pl-10">
-            <Transition
-              show={show}
+          <section className="absolute inset-y-0 right-0 flex max-w-full">
+            <Transition.Child
               appear
               enter="transform transition ease-in-out duration-500 sm:duration-700"
               enterFrom="translate-x-full"
@@ -66,20 +67,20 @@ const SlideOver: React.FC<SlideOverProps> = ({
             >
               {/* eslint-disable-next-line jsx-a11y/no-static-element-interactions */}
               <div
-                className="w-screen max-w-md"
+                className="slideover h-full w-screen max-w-md p-2 sm:p-4"
                 ref={slideoverRef}
                 onClick={(e) => e.stopPropagation()}
               >
-                <div className="flex h-full flex-col overflow-y-scroll bg-gray-700 shadow-xl">
-                  <header className="slideover space-y-1 bg-indigo-600 px-4">
+                <div className="hide-scrollbar flex h-full flex-col overflow-y-scroll rounded-lg bg-gray-800 bg-opacity-80 shadow-xl ring-1 ring-gray-700 backdrop-blur">
+                  <header className="space-y-1 border-b border-gray-700 py-4 px-4">
                     <div className="flex items-center justify-between space-x-3">
-                      <h2 className="text-lg font-bold leading-7 text-white">
+                      <h2 className="text-overseerr text-2xl font-bold leading-7">
                         {title}
                       </h2>
                       <div className="flex h-7 items-center">
                         <button
                           aria-label="Close panel"
-                          className="text-indigo-200 transition duration-150 ease-in-out hover:text-white"
+                          className="text-gray-200 transition duration-150 ease-in-out hover:text-white"
                           onClick={() => onClose()}
                         >
                           <XIcon className="h-6 w-6" />
@@ -88,7 +89,7 @@ const SlideOver: React.FC<SlideOverProps> = ({
                     </div>
                     {subText && (
                       <div>
-                        <p className="text-sm leading-5 text-indigo-300">
+                        <p className="font-semibold leading-5 text-gray-300">
                           {subText}
                         </p>
                       </div>
@@ -99,7 +100,7 @@ const SlideOver: React.FC<SlideOverProps> = ({
                   </div>
                 </div>
               </div>
-            </Transition>
+            </Transition.Child>
           </section>
         </div>
       </div>
diff --git a/src/components/Common/StatusBadgeMini/index.tsx b/src/components/Common/StatusBadgeMini/index.tsx
new file mode 100644
index 00000000..0653c7d8
--- /dev/null
+++ b/src/components/Common/StatusBadgeMini/index.tsx
@@ -0,0 +1,45 @@
+import {
+  BellIcon,
+  CheckIcon,
+  ClockIcon,
+  MinusSmIcon,
+} from '@heroicons/react/solid';
+import { MediaStatus } from '@server/constants/media';
+
+interface StatusBadgeMiniProps {
+  status: MediaStatus;
+  is4k?: boolean;
+}
+
+const StatusBadgeMini = ({ status, is4k = false }: StatusBadgeMiniProps) => {
+  const badgeStyle = ['w-5 rounded-full p-0.5 text-white ring-1'];
+  let indicatorIcon: React.ReactNode;
+
+  switch (status) {
+    case MediaStatus.PROCESSING:
+      badgeStyle.push('bg-indigo-500 ring-indigo-400');
+      indicatorIcon = <ClockIcon />;
+      break;
+    case MediaStatus.AVAILABLE:
+      badgeStyle.push('bg-green-500 ring-green-400');
+      indicatorIcon = <CheckIcon />;
+      break;
+    case MediaStatus.PENDING:
+      badgeStyle.push('bg-yellow-500 ring-yellow-400');
+      indicatorIcon = <BellIcon />;
+      break;
+    case MediaStatus.PARTIALLY_AVAILABLE:
+      badgeStyle.push('bg-green-500 ring-green-400');
+      indicatorIcon = <MinusSmIcon />;
+      break;
+  }
+
+  return (
+    <div className="inline-flex whitespace-nowrap rounded-full text-xs font-semibold leading-5 ring-1 ring-gray-700">
+      <div className={badgeStyle.join(' ')}>{indicatorIcon}</div>
+      {is4k && <span className="pl-1 pr-2 text-gray-200">4K</span>}
+    </div>
+  );
+};
+
+export default StatusBadgeMini;
diff --git a/src/components/Common/Table/index.tsx b/src/components/Common/Table/index.tsx
index 9e0cb0ca..a286de69 100644
--- a/src/components/Common/Table/index.tsx
+++ b/src/components/Common/Table/index.tsx
@@ -1,17 +1,20 @@
-import React, { AllHTMLAttributes } from 'react';
-import { withProperties } from '../../../utils/typeHelpers';
+import { withProperties } from '@app/utils/typeHelpers';
 
-const TBody: React.FC = ({ children }) => {
+type TBodyProps = {
+  children: React.ReactNode;
+};
+
+const TBody = ({ children }: TBodyProps) => {
   return (
     <tbody className="divide-y divide-gray-700 bg-gray-800">{children}</tbody>
   );
 };
 
-const TH: React.FC<AllHTMLAttributes<HTMLTableHeaderCellElement>> = ({
+const TH = ({
   children,
   className,
   ...props
-}) => {
+}: React.ComponentPropsWithoutRef<'th'>) => {
   const style = [
     'px-4 py-3 bg-gray-500 text-left text-xs leading-4 font-medium text-gray-200 uppercase tracking-wider truncate',
   ];
@@ -27,18 +30,18 @@ const TH: React.FC<AllHTMLAttributes<HTMLTableHeaderCellElement>> = ({
   );
 };
 
-interface TDProps extends AllHTMLAttributes<HTMLTableCellElement> {
+type TDProps = {
   alignText?: 'left' | 'center' | 'right';
   noPadding?: boolean;
-}
+};
 
-const TD: React.FC<TDProps> = ({
+const TD = ({
   children,
   alignText = 'left',
   noPadding,
   className,
   ...props
-}) => {
+}: TDProps & React.ComponentPropsWithoutRef<'td'>) => {
   const style = ['text-sm leading-5 text-white'];
 
   switch (alignText) {
@@ -68,7 +71,11 @@ const TD: React.FC<TDProps> = ({
   );
 };
 
-const Table: React.FC = ({ children }) => {
+type TableProps = {
+  children: React.ReactNode;
+};
+
+const Table = ({ children }: TableProps) => {
   return (
     <div className="flex flex-col">
       <div className="my-2 -mx-4 overflow-x-auto md:mx-0 lg:mx-0">
diff --git a/src/components/Common/Tooltip/index.tsx b/src/components/Common/Tooltip/index.tsx
new file mode 100644
index 00000000..b0c4fb2e
--- /dev/null
+++ b/src/components/Common/Tooltip/index.tsx
@@ -0,0 +1,38 @@
+import React from 'react';
+import type { Config } from 'react-popper-tooltip';
+import { usePopperTooltip } from 'react-popper-tooltip';
+
+type TooltipProps = {
+  content: React.ReactNode;
+  children: React.ReactElement;
+  tooltipConfig?: Partial<Config>;
+};
+
+const Tooltip = ({ children, content, tooltipConfig }: TooltipProps) => {
+  const { getTooltipProps, setTooltipRef, setTriggerRef, visible } =
+    usePopperTooltip({
+      followCursor: true,
+      offset: [-28, 6],
+      placement: 'auto-end',
+      ...tooltipConfig,
+    });
+
+  return (
+    <>
+      {React.cloneElement(children, { ref: setTriggerRef })}
+      {visible && (
+        <div
+          ref={setTooltipRef}
+          {...getTooltipProps({
+            className:
+              'z-50 text-sm font-normal bg-gray-800 px-2 py-1 rounded border border-gray-600 shadow text-gray-100',
+          })}
+        >
+          {content}
+        </div>
+      )}
+    </>
+  );
+};
+
+export default Tooltip;
diff --git a/src/components/CompanyCard/index.tsx b/src/components/CompanyCard/index.tsx
index b6383a77..762d1a08 100644
--- a/src/components/CompanyCard/index.tsx
+++ b/src/components/CompanyCard/index.tsx
@@ -1,5 +1,5 @@
 import Link from 'next/link';
-import React, { useState } from 'react';
+import { useState } from 'react';
 
 interface CompanyCardProps {
   name: string;
@@ -7,7 +7,7 @@ interface CompanyCardProps {
   url: string;
 }
 
-const CompanyCard: React.FC<CompanyCardProps> = ({ image, url, name }) => {
+const CompanyCard = ({ image, url, name }: CompanyCardProps) => {
   const [isHovered, setHovered] = useState(false);
 
   return (
diff --git a/src/components/Discover/DiscoverMovieGenre/index.tsx b/src/components/Discover/DiscoverMovieGenre/index.tsx
index e340f4eb..d31921da 100644
--- a/src/components/Discover/DiscoverMovieGenre/index.tsx
+++ b/src/components/Discover/DiscoverMovieGenre/index.tsx
@@ -1,19 +1,18 @@
-import React from 'react';
-import type { MovieResult } from '../../../../server/models/Search';
-import ListView from '../../Common/ListView';
-import { defineMessages, useIntl } from 'react-intl';
-import Header from '../../Common/Header';
-import PageTitle from '../../Common/PageTitle';
+import Header from '@app/components/Common/Header';
+import ListView from '@app/components/Common/ListView';
+import PageTitle from '@app/components/Common/PageTitle';
+import useDiscover from '@app/hooks/useDiscover';
+import globalMessages from '@app/i18n/globalMessages';
+import Error from '@app/pages/_error';
+import type { MovieResult } from '@server/models/Search';
 import { useRouter } from 'next/router';
-import globalMessages from '../../../i18n/globalMessages';
-import useDiscover from '../../../hooks/useDiscover';
-import Error from '../../../pages/_error';
+import { defineMessages, useIntl } from 'react-intl';
 
 const messages = defineMessages({
   genreMovies: '{genre} Movies',
 });
 
-const DiscoverMovieGenre: React.FC = () => {
+const DiscoverMovieGenre = () => {
   const router = useRouter();
   const intl = useIntl();
 
diff --git a/src/components/Discover/DiscoverMovieLanguage/index.tsx b/src/components/Discover/DiscoverMovieLanguage/index.tsx
index b1e19d05..e9a274fa 100644
--- a/src/components/Discover/DiscoverMovieLanguage/index.tsx
+++ b/src/components/Discover/DiscoverMovieLanguage/index.tsx
@@ -1,19 +1,18 @@
-import React from 'react';
-import type { MovieResult } from '../../../../server/models/Search';
-import ListView from '../../Common/ListView';
-import { defineMessages, useIntl } from 'react-intl';
-import Header from '../../Common/Header';
-import PageTitle from '../../Common/PageTitle';
+import Header from '@app/components/Common/Header';
+import ListView from '@app/components/Common/ListView';
+import PageTitle from '@app/components/Common/PageTitle';
+import useDiscover from '@app/hooks/useDiscover';
+import globalMessages from '@app/i18n/globalMessages';
+import Error from '@app/pages/_error';
+import type { MovieResult } from '@server/models/Search';
 import { useRouter } from 'next/router';
-import globalMessages from '../../../i18n/globalMessages';
-import useDiscover from '../../../hooks/useDiscover';
-import Error from '../../../pages/_error';
+import { defineMessages, useIntl } from 'react-intl';
 
 const messages = defineMessages({
   languageMovies: '{language} Movies',
 });
 
-const DiscoverMovieLanguage: React.FC = () => {
+const DiscoverMovieLanguage = () => {
   const router = useRouter();
   const intl = useIntl();
 
diff --git a/src/components/Discover/DiscoverMovies.tsx b/src/components/Discover/DiscoverMovies.tsx
index cef4c623..b9ec8dea 100644
--- a/src/components/Discover/DiscoverMovies.tsx
+++ b/src/components/Discover/DiscoverMovies.tsx
@@ -1,17 +1,16 @@
-import React from 'react';
-import type { MovieResult } from '../../../server/models/Search';
-import ListView from '../Common/ListView';
+import Header from '@app/components/Common/Header';
+import ListView from '@app/components/Common/ListView';
+import PageTitle from '@app/components/Common/PageTitle';
+import useDiscover from '@app/hooks/useDiscover';
+import Error from '@app/pages/_error';
+import type { MovieResult } from '@server/models/Search';
 import { defineMessages, useIntl } from 'react-intl';
-import Header from '../Common/Header';
-import PageTitle from '../Common/PageTitle';
-import useDiscover from '../../hooks/useDiscover';
-import Error from '../../pages/_error';
 
 const messages = defineMessages({
   discovermovies: 'Popular Movies',
 });
 
-const DiscoverMovies: React.FC = () => {
+const DiscoverMovies = () => {
   const intl = useIntl();
 
   const {
diff --git a/src/components/Discover/DiscoverNetwork/index.tsx b/src/components/Discover/DiscoverNetwork/index.tsx
index 247c5ece..f09fef37 100644
--- a/src/components/Discover/DiscoverNetwork/index.tsx
+++ b/src/components/Discover/DiscoverNetwork/index.tsx
@@ -1,20 +1,19 @@
-import React from 'react';
-import type { TvResult } from '../../../../server/models/Search';
-import ListView from '../../Common/ListView';
-import { defineMessages, useIntl } from 'react-intl';
-import Header from '../../Common/Header';
-import PageTitle from '../../Common/PageTitle';
+import Header from '@app/components/Common/Header';
+import ListView from '@app/components/Common/ListView';
+import PageTitle from '@app/components/Common/PageTitle';
+import useDiscover from '@app/hooks/useDiscover';
+import globalMessages from '@app/i18n/globalMessages';
+import Error from '@app/pages/_error';
+import type { TvNetwork } from '@server/models/common';
+import type { TvResult } from '@server/models/Search';
 import { useRouter } from 'next/router';
-import globalMessages from '../../../i18n/globalMessages';
-import useDiscover from '../../../hooks/useDiscover';
-import Error from '../../../pages/_error';
-import { TvNetwork } from '../../../../server/models/common';
+import { defineMessages, useIntl } from 'react-intl';
 
 const messages = defineMessages({
   networkSeries: '{network} Series',
 });
 
-const DiscoverTvNetwork: React.FC = () => {
+const DiscoverTvNetwork = () => {
   const router = useRouter();
   const intl = useIntl();
 
diff --git a/src/components/Discover/DiscoverStudio/index.tsx b/src/components/Discover/DiscoverStudio/index.tsx
index b1f3b066..1d78748b 100644
--- a/src/components/Discover/DiscoverStudio/index.tsx
+++ b/src/components/Discover/DiscoverStudio/index.tsx
@@ -1,20 +1,19 @@
-import React from 'react';
-import type { MovieResult } from '../../../../server/models/Search';
-import ListView from '../../Common/ListView';
-import { defineMessages, useIntl } from 'react-intl';
-import Header from '../../Common/Header';
-import PageTitle from '../../Common/PageTitle';
+import Header from '@app/components/Common/Header';
+import ListView from '@app/components/Common/ListView';
+import PageTitle from '@app/components/Common/PageTitle';
+import useDiscover from '@app/hooks/useDiscover';
+import globalMessages from '@app/i18n/globalMessages';
+import Error from '@app/pages/_error';
+import type { ProductionCompany } from '@server/models/common';
+import type { MovieResult } from '@server/models/Search';
 import { useRouter } from 'next/router';
-import globalMessages from '../../../i18n/globalMessages';
-import useDiscover from '../../../hooks/useDiscover';
-import Error from '../../../pages/_error';
-import { ProductionCompany } from '../../../../server/models/common';
+import { defineMessages, useIntl } from 'react-intl';
 
 const messages = defineMessages({
   studioMovies: '{studio} Movies',
 });
 
-const DiscoverMovieStudio: React.FC = () => {
+const DiscoverMovieStudio = () => {
   const router = useRouter();
   const intl = useIntl();
 
diff --git a/src/components/Discover/DiscoverTv.tsx b/src/components/Discover/DiscoverTv.tsx
index 60c29225..404b1aa5 100644
--- a/src/components/Discover/DiscoverTv.tsx
+++ b/src/components/Discover/DiscoverTv.tsx
@@ -1,17 +1,16 @@
-import React from 'react';
-import type { TvResult } from '../../../server/models/Search';
-import ListView from '../Common/ListView';
+import Header from '@app/components/Common/Header';
+import ListView from '@app/components/Common/ListView';
+import PageTitle from '@app/components/Common/PageTitle';
+import useDiscover from '@app/hooks/useDiscover';
+import Error from '@app/pages/_error';
+import type { TvResult } from '@server/models/Search';
 import { defineMessages, useIntl } from 'react-intl';
-import Header from '../Common/Header';
-import PageTitle from '../Common/PageTitle';
-import useDiscover from '../../hooks/useDiscover';
-import Error from '../../pages/_error';
 
 const messages = defineMessages({
   discovertv: 'Popular Series',
 });
 
-const DiscoverTv: React.FC = () => {
+const DiscoverTv = () => {
   const intl = useIntl();
 
   const {
diff --git a/src/components/Discover/DiscoverTvGenre/index.tsx b/src/components/Discover/DiscoverTvGenre/index.tsx
index d4b672a5..9602fbb8 100644
--- a/src/components/Discover/DiscoverTvGenre/index.tsx
+++ b/src/components/Discover/DiscoverTvGenre/index.tsx
@@ -1,19 +1,18 @@
-import React from 'react';
-import type { TvResult } from '../../../../server/models/Search';
-import ListView from '../../Common/ListView';
-import { defineMessages, useIntl } from 'react-intl';
-import Header from '../../Common/Header';
-import PageTitle from '../../Common/PageTitle';
+import Header from '@app/components/Common/Header';
+import ListView from '@app/components/Common/ListView';
+import PageTitle from '@app/components/Common/PageTitle';
+import useDiscover from '@app/hooks/useDiscover';
+import globalMessages from '@app/i18n/globalMessages';
+import Error from '@app/pages/_error';
+import type { TvResult } from '@server/models/Search';
 import { useRouter } from 'next/router';
-import globalMessages from '../../../i18n/globalMessages';
-import useDiscover from '../../../hooks/useDiscover';
-import Error from '../../../pages/_error';
+import { defineMessages, useIntl } from 'react-intl';
 
 const messages = defineMessages({
   genreSeries: '{genre} Series',
 });
 
-const DiscoverTvGenre: React.FC = () => {
+const DiscoverTvGenre = () => {
   const router = useRouter();
   const intl = useIntl();
 
diff --git a/src/components/Discover/DiscoverTvLanguage/index.tsx b/src/components/Discover/DiscoverTvLanguage/index.tsx
index ed0873f9..b6c710e9 100644
--- a/src/components/Discover/DiscoverTvLanguage/index.tsx
+++ b/src/components/Discover/DiscoverTvLanguage/index.tsx
@@ -1,19 +1,18 @@
-import React from 'react';
-import type { TvResult } from '../../../../server/models/Search';
-import ListView from '../../Common/ListView';
-import { defineMessages, useIntl } from 'react-intl';
-import Header from '../../Common/Header';
-import PageTitle from '../../Common/PageTitle';
+import Header from '@app/components/Common/Header';
+import ListView from '@app/components/Common/ListView';
+import PageTitle from '@app/components/Common/PageTitle';
+import useDiscover from '@app/hooks/useDiscover';
+import globalMessages from '@app/i18n/globalMessages';
+import Error from '@app/pages/_error';
+import type { TvResult } from '@server/models/Search';
 import { useRouter } from 'next/router';
-import globalMessages from '../../../i18n/globalMessages';
-import useDiscover from '../../../hooks/useDiscover';
-import Error from '../../../pages/_error';
+import { defineMessages, useIntl } from 'react-intl';
 
 const messages = defineMessages({
   languageSeries: '{language} Series',
 });
 
-const DiscoverTvLanguage: React.FC = () => {
+const DiscoverTvLanguage = () => {
   const router = useRouter();
   const intl = useIntl();
 
diff --git a/src/components/Discover/DiscoverTvUpcoming.tsx b/src/components/Discover/DiscoverTvUpcoming.tsx
index 5b59f26a..2a693964 100644
--- a/src/components/Discover/DiscoverTvUpcoming.tsx
+++ b/src/components/Discover/DiscoverTvUpcoming.tsx
@@ -1,17 +1,16 @@
-import React from 'react';
-import type { TvResult } from '../../../server/models/Search';
-import ListView from '../Common/ListView';
+import Header from '@app/components/Common/Header';
+import ListView from '@app/components/Common/ListView';
+import PageTitle from '@app/components/Common/PageTitle';
+import useDiscover from '@app/hooks/useDiscover';
+import Error from '@app/pages/_error';
+import type { TvResult } from '@server/models/Search';
 import { defineMessages, useIntl } from 'react-intl';
-import Header from '../Common/Header';
-import PageTitle from '../Common/PageTitle';
-import useDiscover from '../../hooks/useDiscover';
-import Error from '../../pages/_error';
 
 const messages = defineMessages({
   upcomingtv: 'Upcoming Series',
 });
 
-const DiscoverTvUpcoming: React.FC = () => {
+const DiscoverTvUpcoming = () => {
   const intl = useIntl();
 
   const {
diff --git a/src/components/Discover/DiscoverWatchlist/index.tsx b/src/components/Discover/DiscoverWatchlist/index.tsx
new file mode 100644
index 00000000..fbbdff01
--- /dev/null
+++ b/src/components/Discover/DiscoverWatchlist/index.tsx
@@ -0,0 +1,84 @@
+import Header from '@app/components/Common/Header';
+import ListView from '@app/components/Common/ListView';
+import PageTitle from '@app/components/Common/PageTitle';
+import useDiscover from '@app/hooks/useDiscover';
+import { useUser } from '@app/hooks/useUser';
+import Error from '@app/pages/_error';
+import type { WatchlistItem } from '@server/interfaces/api/discoverInterfaces';
+import Link from 'next/link';
+import { useRouter } from 'next/router';
+import { defineMessages, useIntl } from 'react-intl';
+
+const messages = defineMessages({
+  discoverwatchlist: 'Your Plex Watchlist',
+  watchlist: 'Plex Watchlist',
+});
+
+const DiscoverWatchlist = () => {
+  const intl = useIntl();
+  const router = useRouter();
+  const { user } = useUser({
+    id: Number(router.query.userId),
+  });
+  const { user: currentUser } = useUser();
+
+  const {
+    isLoadingInitialData,
+    isEmpty,
+    isLoadingMore,
+    isReachingEnd,
+    titles,
+    fetchMore,
+    error,
+  } = useDiscover<WatchlistItem>(
+    `/api/v1/${
+      router.pathname.startsWith('/profile')
+        ? `user/${currentUser?.id}`
+        : router.query.userId
+        ? `user/${router.query.userId}`
+        : 'discover'
+    }/watchlist`
+  );
+
+  if (error) {
+    return <Error statusCode={500} />;
+  }
+
+  const title = intl.formatMessage(
+    router.query.userId ? messages.watchlist : messages.discoverwatchlist
+  );
+
+  return (
+    <>
+      <PageTitle
+        title={[title, router.query.userId ? user?.displayName : '']}
+      />
+      <div className="mt-1 mb-5">
+        <Header
+          subtext={
+            router.query.userId ? (
+              <Link href={`/users/${user?.id}`}>
+                <a className="hover:underline">{user?.displayName}</a>
+              </Link>
+            ) : (
+              ''
+            )
+          }
+        >
+          {title}
+        </Header>
+      </div>
+      <ListView
+        plexItems={titles}
+        isEmpty={isEmpty}
+        isLoading={
+          isLoadingInitialData || (isLoadingMore && (titles?.length ?? 0) > 0)
+        }
+        isReachingEnd={isReachingEnd}
+        onScrollBottom={fetchMore}
+      />
+    </>
+  );
+};
+
+export default DiscoverWatchlist;
diff --git a/src/components/Discover/MovieGenreList/index.tsx b/src/components/Discover/MovieGenreList/index.tsx
index bc85adad..f19f5770 100644
--- a/src/components/Discover/MovieGenreList/index.tsx
+++ b/src/components/Discover/MovieGenreList/index.tsx
@@ -1,19 +1,18 @@
-import React from 'react';
+import Header from '@app/components/Common/Header';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import { genreColorMap } from '@app/components/Discover/constants';
+import GenreCard from '@app/components/GenreCard';
+import Error from '@app/pages/_error';
+import type { GenreSliderItem } from '@server/interfaces/api/discoverInterfaces';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import { GenreSliderItem } from '../../../../server/interfaces/api/discoverInterfaces';
-import Error from '../../../pages/_error';
-import Header from '../../Common/Header';
-import LoadingSpinner from '../../Common/LoadingSpinner';
-import PageTitle from '../../Common/PageTitle';
-import GenreCard from '../../GenreCard';
-import { genreColorMap } from '../constants';
 
 const messages = defineMessages({
   moviegenres: 'Movie Genres',
 });
 
-const MovieGenreList: React.FC = () => {
+const MovieGenreList = () => {
   const intl = useIntl();
   const { data, error } = useSWR<GenreSliderItem[]>(
     `/api/v1/discover/genreslider/movie`
diff --git a/src/components/Discover/MovieGenreSlider/index.tsx b/src/components/Discover/MovieGenreSlider/index.tsx
index cf1b8ce1..4899d349 100644
--- a/src/components/Discover/MovieGenreSlider/index.tsx
+++ b/src/components/Discover/MovieGenreSlider/index.tsx
@@ -1,18 +1,18 @@
+import { genreColorMap } from '@app/components/Discover/constants';
+import GenreCard from '@app/components/GenreCard';
+import Slider from '@app/components/Slider';
 import { ArrowCircleRightIcon } from '@heroicons/react/outline';
+import type { GenreSliderItem } from '@server/interfaces/api/discoverInterfaces';
 import Link from 'next/link';
 import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import { GenreSliderItem } from '../../../../server/interfaces/api/discoverInterfaces';
-import GenreCard from '../../GenreCard';
-import Slider from '../../Slider';
-import { genreColorMap } from '../constants';
 
 const messages = defineMessages({
   moviegenres: 'Movie Genres',
 });
 
-const MovieGenreSlider: React.FC = () => {
+const MovieGenreSlider = () => {
   const intl = useIntl();
   const { data, error } = useSWR<GenreSliderItem[]>(
     `/api/v1/discover/genreslider/movie`,
diff --git a/src/components/Discover/NetworkSlider/index.tsx b/src/components/Discover/NetworkSlider/index.tsx
index 44c776cf..8973cbd1 100644
--- a/src/components/Discover/NetworkSlider/index.tsx
+++ b/src/components/Discover/NetworkSlider/index.tsx
@@ -1,7 +1,6 @@
-import React from 'react';
+import CompanyCard from '@app/components/CompanyCard';
+import Slider from '@app/components/Slider';
 import { defineMessages, useIntl } from 'react-intl';
-import CompanyCard from '../../CompanyCard';
-import Slider from '../../Slider';
 
 const messages = defineMessages({
   networks: 'Networks',
@@ -110,6 +109,12 @@ const networks: Network[] = [
       'https://image.tmdb.org/t/p/w780_filter(duotone,ffffff,bababa)/nm8d7P7MJNiBLdgIzUK0gkuEA4r.png',
     url: '/discover/tv/network/16',
   },
+  {
+    name: 'Paramount+',
+    image:
+      'https://image.tmdb.org/t/p/w780_filter(duotone,ffffff,bababa)/fi83B1oztoS47xxcemFdPMhIzK.png',
+    url: '/discover/tv/network/4330',
+  },
   {
     name: 'BBC One',
     image:
@@ -136,7 +141,7 @@ const networks: Network[] = [
   },
 ];
 
-const NetworkSlider: React.FC = () => {
+const NetworkSlider = () => {
   const intl = useIntl();
 
   return (
diff --git a/src/components/Discover/StudioSlider/index.tsx b/src/components/Discover/StudioSlider/index.tsx
index 59f0e8c0..3f136142 100644
--- a/src/components/Discover/StudioSlider/index.tsx
+++ b/src/components/Discover/StudioSlider/index.tsx
@@ -1,7 +1,6 @@
-import React from 'react';
+import CompanyCard from '@app/components/CompanyCard';
+import Slider from '@app/components/Slider';
 import { defineMessages, useIntl } from 'react-intl';
-import CompanyCard from '../../CompanyCard';
-import Slider from '../../Slider';
 
 const messages = defineMessages({
   studios: 'Studios',
@@ -21,10 +20,10 @@ const studios: Studio[] = [
     url: '/discover/movies/studio/2',
   },
   {
-    name: '20th Century Fox',
+    name: '20th Century Studios',
     image:
-      'https://image.tmdb.org/t/p/w780_filter(duotone,ffffff,bababa)/qZCc1lty5FzX30aOCVRBLzaVmcp.png',
-    url: '/discover/movies/studio/25',
+      'https://image.tmdb.org/t/p/w780_filter(duotone,ffffff,bababa)/h0rjX5vjW5r8yEnUBStFarjcLT4.png',
+    url: '/discover/movies/studio/127928',
   },
   {
     name: 'Sony Pictures',
@@ -76,7 +75,7 @@ const studios: Studio[] = [
   },
 ];
 
-const StudioSlider: React.FC = () => {
+const StudioSlider = () => {
   const intl = useIntl();
 
   return (
diff --git a/src/components/Discover/Trending.tsx b/src/components/Discover/Trending.tsx
index c0f2e222..5210e7d3 100644
--- a/src/components/Discover/Trending.tsx
+++ b/src/components/Discover/Trending.tsx
@@ -1,21 +1,20 @@
-import React from 'react';
+import Header from '@app/components/Common/Header';
+import ListView from '@app/components/Common/ListView';
+import PageTitle from '@app/components/Common/PageTitle';
+import useDiscover from '@app/hooks/useDiscover';
+import Error from '@app/pages/_error';
 import type {
   MovieResult,
-  TvResult,
   PersonResult,
-} from '../../../server/models/Search';
-import ListView from '../Common/ListView';
+  TvResult,
+} from '@server/models/Search';
 import { defineMessages, useIntl } from 'react-intl';
-import Header from '../Common/Header';
-import PageTitle from '../Common/PageTitle';
-import useDiscover from '../../hooks/useDiscover';
-import Error from '../../pages/_error';
 
 const messages = defineMessages({
   trending: 'Trending',
 });
 
-const Trending: React.FC = () => {
+const Trending = () => {
   const intl = useIntl();
   const {
     isLoadingInitialData,
diff --git a/src/components/Discover/TvGenreList/index.tsx b/src/components/Discover/TvGenreList/index.tsx
index 15fe9a01..391c51f2 100644
--- a/src/components/Discover/TvGenreList/index.tsx
+++ b/src/components/Discover/TvGenreList/index.tsx
@@ -1,19 +1,18 @@
-import React from 'react';
+import Header from '@app/components/Common/Header';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import { genreColorMap } from '@app/components/Discover/constants';
+import GenreCard from '@app/components/GenreCard';
+import Error from '@app/pages/_error';
+import type { GenreSliderItem } from '@server/interfaces/api/discoverInterfaces';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import { GenreSliderItem } from '../../../../server/interfaces/api/discoverInterfaces';
-import Error from '../../../pages/_error';
-import Header from '../../Common/Header';
-import LoadingSpinner from '../../Common/LoadingSpinner';
-import PageTitle from '../../Common/PageTitle';
-import GenreCard from '../../GenreCard';
-import { genreColorMap } from '../constants';
 
 const messages = defineMessages({
   seriesgenres: 'Series Genres',
 });
 
-const TvGenreList: React.FC = () => {
+const TvGenreList = () => {
   const intl = useIntl();
   const { data, error } = useSWR<GenreSliderItem[]>(
     `/api/v1/discover/genreslider/tv`
diff --git a/src/components/Discover/TvGenreSlider/index.tsx b/src/components/Discover/TvGenreSlider/index.tsx
index 54f8daa3..820012c3 100644
--- a/src/components/Discover/TvGenreSlider/index.tsx
+++ b/src/components/Discover/TvGenreSlider/index.tsx
@@ -1,18 +1,18 @@
+import { genreColorMap } from '@app/components/Discover/constants';
+import GenreCard from '@app/components/GenreCard';
+import Slider from '@app/components/Slider';
 import { ArrowCircleRightIcon } from '@heroicons/react/outline';
+import type { GenreSliderItem } from '@server/interfaces/api/discoverInterfaces';
 import Link from 'next/link';
 import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import { GenreSliderItem } from '../../../../server/interfaces/api/discoverInterfaces';
-import GenreCard from '../../GenreCard';
-import Slider from '../../Slider';
-import { genreColorMap } from '../constants';
 
 const messages = defineMessages({
   tvgenres: 'Series Genres',
 });
 
-const TvGenreSlider: React.FC = () => {
+const TvGenreSlider = () => {
   const intl = useIntl();
   const { data, error } = useSWR<GenreSliderItem[]>(
     `/api/v1/discover/genreslider/tv`,
diff --git a/src/components/Discover/Upcoming.tsx b/src/components/Discover/Upcoming.tsx
index 1e14f73d..b556e6f9 100644
--- a/src/components/Discover/Upcoming.tsx
+++ b/src/components/Discover/Upcoming.tsx
@@ -1,17 +1,16 @@
-import React from 'react';
-import type { MovieResult } from '../../../server/models/Search';
-import ListView from '../Common/ListView';
+import Header from '@app/components/Common/Header';
+import ListView from '@app/components/Common/ListView';
+import PageTitle from '@app/components/Common/PageTitle';
+import useDiscover from '@app/hooks/useDiscover';
+import Error from '@app/pages/_error';
+import type { MovieResult } from '@server/models/Search';
 import { defineMessages, useIntl } from 'react-intl';
-import Header from '../Common/Header';
-import PageTitle from '../Common/PageTitle';
-import useDiscover from '../../hooks/useDiscover';
-import Error from '../../pages/_error';
 
 const messages = defineMessages({
   upcomingmovies: 'Upcoming Movies',
 });
 
-const UpcomingMovies: React.FC = () => {
+const UpcomingMovies = () => {
   const intl = useIntl();
 
   const {
diff --git a/src/components/Discover/index.tsx b/src/components/Discover/index.tsx
index 3ebd6226..24dc6fea 100644
--- a/src/components/Discover/index.tsx
+++ b/src/components/Discover/index.tsx
@@ -1,19 +1,20 @@
+import PageTitle from '@app/components/Common/PageTitle';
+import MovieGenreSlider from '@app/components/Discover/MovieGenreSlider';
+import NetworkSlider from '@app/components/Discover/NetworkSlider';
+import StudioSlider from '@app/components/Discover/StudioSlider';
+import TvGenreSlider from '@app/components/Discover/TvGenreSlider';
+import MediaSlider from '@app/components/MediaSlider';
+import RequestCard from '@app/components/RequestCard';
+import Slider from '@app/components/Slider';
+import TmdbTitleCard from '@app/components/TitleCard/TmdbTitleCard';
+import { Permission, UserType, useUser } from '@app/hooks/useUser';
 import { ArrowCircleRightIcon } from '@heroicons/react/outline';
+import type { WatchlistItem } from '@server/interfaces/api/discoverInterfaces';
+import type { MediaResultsResponse } from '@server/interfaces/api/mediaInterfaces';
+import type { RequestResultsResponse } from '@server/interfaces/api/requestInterfaces';
 import Link from 'next/link';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import type { MediaResultsResponse } from '../../../server/interfaces/api/mediaInterfaces';
-import type { RequestResultsResponse } from '../../../server/interfaces/api/requestInterfaces';
-import PageTitle from '../Common/PageTitle';
-import MediaSlider from '../MediaSlider';
-import RequestCard from '../RequestCard';
-import Slider from '../Slider';
-import TmdbTitleCard from '../TitleCard/TmdbTitleCard';
-import MovieGenreSlider from './MovieGenreSlider';
-import NetworkSlider from './NetworkSlider';
-import StudioSlider from './StudioSlider';
-import TvGenreSlider from './TvGenreSlider';
 
 const messages = defineMessages({
   discover: 'Discover',
@@ -22,13 +23,16 @@ const messages = defineMessages({
   populartv: 'Popular Series',
   upcomingtv: 'Upcoming Series',
   recentlyAdded: 'Recently Added',
-  noRequests: 'No requests.',
   upcoming: 'Upcoming Movies',
   trending: 'Trending',
+  plexwatchlist: 'Your Plex Watchlist',
+  emptywatchlist:
+    'Media added to your <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink> will appear here.',
 });
 
-const Discover: React.FC = () => {
+const Discover = () => {
   const intl = useIntl();
+  const { user, hasPermission } = useUser();
 
   const { data: media, error: mediaError } = useSWR<MediaResultsResponse>(
     '/api/v1/media?filter=allavailable&take=20&sort=mediaAdded',
@@ -38,50 +42,114 @@ const Discover: React.FC = () => {
   const { data: requests, error: requestError } =
     useSWR<RequestResultsResponse>(
       '/api/v1/request?filter=all&take=10&sort=modified&skip=0',
-      { revalidateOnMount: true }
+      {
+        revalidateOnMount: true,
+      }
     );
 
+  const { data: watchlistItems, error: watchlistError } = useSWR<{
+    page: number;
+    totalPages: number;
+    totalResults: number;
+    results: WatchlistItem[];
+  }>(user?.userType === UserType.PLEX ? '/api/v1/discover/watchlist' : null, {
+    revalidateOnMount: true,
+  });
+
   return (
     <>
       <PageTitle title={intl.formatMessage(messages.discover)} />
-      <div className="slider-header">
-        <div className="slider-title">
-          <span>{intl.formatMessage(messages.recentlyAdded)}</span>
-        </div>
-      </div>
-      <Slider
-        sliderKey="media"
-        isLoading={!media && !mediaError}
-        isEmpty={!!media && !mediaError && media.results.length === 0}
-        items={media?.results?.map((item) => (
-          <TmdbTitleCard
-            key={`media-slider-item-${item.id}`}
-            tmdbId={item.tmdbId}
-            type={item.mediaType}
-          />
-        ))}
-      />
-      <div className="slider-header">
-        <Link href="/requests?filter=all">
-          <a className="slider-title">
-            <span>{intl.formatMessage(messages.recentrequests)}</span>
-            <ArrowCircleRightIcon />
-          </a>
-        </Link>
-      </div>
-      <Slider
-        sliderKey="requests"
-        isLoading={!requests && !requestError}
-        isEmpty={!!requests && !requestError && requests.results.length === 0}
-        items={(requests?.results ?? []).map((request) => (
-          <RequestCard
-            key={`request-slider-item-${request.id}`}
-            request={request}
+      {(!media || !!media.results.length) &&
+        !mediaError &&
+        hasPermission([Permission.MANAGE_REQUESTS, Permission.RECENT_VIEW], {
+          type: 'or',
+        }) && (
+          <>
+            <div className="slider-header">
+              <div className="slider-title">
+                <span>{intl.formatMessage(messages.recentlyAdded)}</span>
+              </div>
+            </div>
+            <Slider
+              sliderKey="media"
+              isLoading={!media}
+              items={(media?.results ?? []).map((item) => (
+                <TmdbTitleCard
+                  key={`media-slider-item-${item.id}`}
+                  id={item.id}
+                  tmdbId={item.tmdbId}
+                  tvdbId={item.tvdbId}
+                  type={item.mediaType}
+                />
+              ))}
+            />
+          </>
+        )}
+      {(!requests || !!requests.results.length) && !requestError && (
+        <>
+          <div className="slider-header">
+            <Link href="/requests?filter=all">
+              <a className="slider-title">
+                <span>{intl.formatMessage(messages.recentrequests)}</span>
+                <ArrowCircleRightIcon />
+              </a>
+            </Link>
+          </div>
+          <Slider
+            sliderKey="requests"
+            isLoading={!requests}
+            items={(requests?.results ?? []).map((request) => (
+              <RequestCard
+                key={`request-slider-item-${request.id}`}
+                request={request}
+              />
+            ))}
+            placeholder={<RequestCard.Placeholder />}
           />
-        ))}
-        placeholder={<RequestCard.Placeholder />}
-        emptyMessage={intl.formatMessage(messages.noRequests)}
-      />
+        </>
+      )}
+      {user?.userType === UserType.PLEX &&
+        (!watchlistItems ||
+          !!watchlistItems.results.length ||
+          user.settings?.watchlistSyncMovies ||
+          user.settings?.watchlistSyncTv) &&
+        !watchlistError && (
+          <>
+            <div className="slider-header">
+              <Link href="/discover/watchlist">
+                <a className="slider-title">
+                  <span>{intl.formatMessage(messages.plexwatchlist)}</span>
+                  <ArrowCircleRightIcon />
+                </a>
+              </Link>
+            </div>
+            <Slider
+              sliderKey="watchlist"
+              isLoading={!watchlistItems}
+              isEmpty={!!watchlistItems && watchlistItems.results.length === 0}
+              emptyMessage={intl.formatMessage(messages.emptywatchlist, {
+                PlexWatchlistSupportLink: (msg: React.ReactNode) => (
+                  <a
+                    href="https://support.plex.tv/articles/universal-watchlist/"
+                    className="text-white transition duration-300 hover:underline"
+                    target="_blank"
+                    rel="noreferrer"
+                  >
+                    {msg}
+                  </a>
+                ),
+              })}
+              items={watchlistItems?.results.map((item) => (
+                <TmdbTitleCard
+                  id={item.tmdbId}
+                  key={`watchlist-slider-item-${item.ratingKey}`}
+                  tmdbId={item.tmdbId}
+                  type={item.mediaType}
+                />
+              ))}
+            />
+          </>
+        )}
       <MediaSlider
         sliderKey="trending"
         title={intl.formatMessage(messages.trending)}
diff --git a/src/components/DownloadBlock/index.tsx b/src/components/DownloadBlock/index.tsx
index d7c3922c..0597e3a6 100644
--- a/src/components/DownloadBlock/index.tsx
+++ b/src/components/DownloadBlock/index.tsx
@@ -1,7 +1,6 @@
-import React from 'react';
+import Badge from '@app/components/Common/Badge';
+import type { DownloadingItem } from '@server/lib/downloadtracker';
 import { defineMessages, FormattedRelativeTime, useIntl } from 'react-intl';
-import { DownloadingItem } from '../../../server/lib/downloadtracker';
-import Badge from '../Common/Badge';
 
 const messages = defineMessages({
   estimatedtime: 'Estimated {time}',
@@ -12,10 +11,7 @@ interface DownloadBlockProps {
   is4k?: boolean;
 }
 
-const DownloadBlock: React.FC<DownloadBlockProps> = ({
-  downloadItem,
-  is4k = false,
-}) => {
+const DownloadBlock = ({ downloadItem, is4k = false }: DownloadBlockProps) => {
   const intl = useIntl();
 
   return (
diff --git a/src/components/ExternalLinkBlock/index.tsx b/src/components/ExternalLinkBlock/index.tsx
index 05f8c3bc..c4386c38 100644
--- a/src/components/ExternalLinkBlock/index.tsx
+++ b/src/components/ExternalLinkBlock/index.tsx
@@ -1,12 +1,11 @@
-import React from 'react';
-import { MediaType } from '../../../server/constants/media';
-import ImdbLogo from '../../assets/services/imdb.svg';
-import PlexLogo from '../../assets/services/plex.svg';
-import RTLogo from '../../assets/services/rt.svg';
-import TmdbLogo from '../../assets/services/tmdb.svg';
-import TraktLogo from '../../assets/services/trakt.svg';
-import TvdbLogo from '../../assets/services/tvdb.svg';
-import useLocale from '../../hooks/useLocale';
+import ImdbLogo from '@app/assets/services/imdb.svg';
+import PlexLogo from '@app/assets/services/plex.svg';
+import RTLogo from '@app/assets/services/rt.svg';
+import TmdbLogo from '@app/assets/services/tmdb.svg';
+import TraktLogo from '@app/assets/services/trakt.svg';
+import TvdbLogo from '@app/assets/services/tvdb.svg';
+import useLocale from '@app/hooks/useLocale';
+import { MediaType } from '@server/constants/media';
 
 interface ExternalLinkBlockProps {
   mediaType: 'movie' | 'tv';
@@ -17,14 +16,14 @@ interface ExternalLinkBlockProps {
   plexUrl?: string;
 }
 
-const ExternalLinkBlock: React.FC<ExternalLinkBlockProps> = ({
+const ExternalLinkBlock = ({
   mediaType,
   tmdbId,
   tvdbId,
   imdbId,
   rtUrl,
   plexUrl,
-}) => {
+}: ExternalLinkBlockProps) => {
   const { locale } = useLocale();
 
   return (
@@ -71,7 +70,7 @@ const ExternalLinkBlock: React.FC<ExternalLinkBlockProps> = ({
       )}
       {rtUrl && (
         <a
-          href={`${rtUrl}`}
+          href={rtUrl}
           className="w-14 opacity-50 transition duration-300 hover:opacity-100"
           target="_blank"
           rel="noreferrer"
diff --git a/src/components/GenreCard/index.tsx b/src/components/GenreCard/index.tsx
index 85d888a3..5171bd81 100644
--- a/src/components/GenreCard/index.tsx
+++ b/src/components/GenreCard/index.tsx
@@ -1,7 +1,7 @@
+import CachedImage from '@app/components/Common/CachedImage';
+import { withProperties } from '@app/utils/typeHelpers';
 import Link from 'next/link';
-import React, { useState } from 'react';
-import { withProperties } from '../../utils/typeHelpers';
-import CachedImage from '../Common/CachedImage';
+import { useState } from 'react';
 
 interface GenreCardProps {
   name: string;
@@ -10,12 +10,7 @@ interface GenreCardProps {
   canExpand?: boolean;
 }
 
-const GenreCard: React.FC<GenreCardProps> = ({
-  image,
-  url,
-  name,
-  canExpand = false,
-}) => {
+const GenreCard = ({ image, url, name, canExpand = false }: GenreCardProps) => {
   const [isHovered, setHovered] = useState(false);
 
   return (
@@ -54,7 +49,7 @@ const GenreCard: React.FC<GenreCardProps> = ({
   );
 };
 
-const GenreCardPlaceholder: React.FC = () => {
+const GenreCardPlaceholder = () => {
   return (
     <div
       className={`relative h-32 w-56 animate-pulse rounded-xl bg-gray-700 sm:h-40 sm:w-72`}
diff --git a/src/components/IssueBlock/index.tsx b/src/components/IssueBlock/index.tsx
index 3367a2c2..c337c721 100644
--- a/src/components/IssueBlock/index.tsx
+++ b/src/components/IssueBlock/index.tsx
@@ -1,22 +1,21 @@
+import Button from '@app/components/Common/Button';
+import { issueOptions } from '@app/components/IssueModal/constants';
+import { useUser } from '@app/hooks/useUser';
 import {
   CalendarIcon,
   ExclamationIcon,
   EyeIcon,
   UserIcon,
 } from '@heroicons/react/solid';
+import type Issue from '@server/entity/Issue';
 import Link from 'next/link';
-import React from 'react';
 import { useIntl } from 'react-intl';
-import type Issue from '../../../server/entity/Issue';
-import { useUser } from '../../hooks/useUser';
-import Button from '../Common/Button';
-import { issueOptions } from '../IssueModal/constants';
 
 interface IssueBlockProps {
   issue: Issue;
 }
 
-const IssueBlock: React.FC<IssueBlockProps> = ({ issue }) => {
+const IssueBlock = ({ issue }: IssueBlockProps) => {
   const { user } = useUser();
   const intl = useIntl();
   const issueOption = issueOptions.find(
diff --git a/src/components/IssueDetails/IssueComment/index.tsx b/src/components/IssueDetails/IssueComment/index.tsx
index 99b26a44..b941c9f3 100644
--- a/src/components/IssueDetails/IssueComment/index.tsx
+++ b/src/components/IssueDetails/IssueComment/index.tsx
@@ -1,18 +1,16 @@
-import { Menu } from '@headlessui/react';
-import { ExclamationIcon } from '@heroicons/react/outline';
+import Button from '@app/components/Common/Button';
+import Modal from '@app/components/Common/Modal';
+import { Permission, useUser } from '@app/hooks/useUser';
+import { Menu, Transition } from '@headlessui/react';
 import { DotsVerticalIcon } from '@heroicons/react/solid';
+import type { default as IssueCommentType } from '@server/entity/IssueComment';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
 import Link from 'next/link';
-import React, { useState } from 'react';
+import { Fragment, useState } from 'react';
 import { defineMessages, FormattedRelativeTime, useIntl } from 'react-intl';
 import ReactMarkdown from 'react-markdown';
 import * as Yup from 'yup';
-import type { default as IssueCommentType } from '../../../../server/entity/IssueComment';
-import { Permission, useUser } from '../../../hooks/useUser';
-import Button from '../../Common/Button';
-import Modal from '../../Common/Modal';
-import Transition from '../../Transition';
 
 const messages = defineMessages({
   postedby: 'Posted {relativeTime} by {username}',
@@ -30,12 +28,12 @@ interface IssueCommentProps {
   onUpdate?: () => void;
 }
 
-const IssueComment: React.FC<IssueCommentProps> = ({
+const IssueComment = ({
   comment,
   isReversed = false,
   isActiveUser = false,
   onUpdate,
-}) => {
+}: IssueCommentProps) => {
   const intl = useIntl();
   const [showDeleteModal, setShowDeleteModal] = useState(false);
   const [isEditing, setIsEditing] = useState(false);
@@ -66,6 +64,7 @@ const IssueComment: React.FC<IssueCommentProps> = ({
       } mt-4 space-x-4`}
     >
       <Transition
+        as={Fragment}
         enter="transition opacity-0 duration-300"
         enterFrom="opacity-0"
         enterTo="opacity-100"
@@ -80,7 +79,6 @@ const IssueComment: React.FC<IssueCommentProps> = ({
           onOk={() => deleteComment()}
           okText={intl.formatMessage(messages.delete)}
           okButtonType="danger"
-          iconSvg={<ExclamationIcon />}
         >
           {intl.formatMessage(messages.areyousuredelete)}
         </Modal>
@@ -90,7 +88,7 @@ const IssueComment: React.FC<IssueCommentProps> = ({
           <img
             src={comment.user.avatar}
             alt=""
-            className="h-10 w-10 scale-100 transform-gpu rounded-full ring-1 ring-gray-500 transition duration-300 hover:scale-105"
+            className="h-10 w-10 scale-100 transform-gpu rounded-full object-cover ring-1 ring-gray-500 transition duration-300 hover:scale-105"
           />
         </a>
       </Link>
@@ -114,6 +112,7 @@ const IssueComment: React.FC<IssueCommentProps> = ({
                   </div>
 
                   <Transition
+                    as={Fragment}
                     show={open}
                     enter="transition ease-out duration-100"
                     enterFrom="transform opacity-0 scale-95"
@@ -195,9 +194,11 @@ const IssueComment: React.FC<IssueCommentProps> = ({
                         name="newMessage"
                         className="h-24"
                       />
-                      {errors.newMessage && touched.newMessage && (
-                        <div className="error">{errors.newMessage}</div>
-                      )}
+                      {errors.newMessage &&
+                        touched.newMessage &&
+                        typeof errors.newMessage === 'string' && (
+                          <div className="error">{errors.newMessage}</div>
+                        )}
                       <div className="mt-4 flex items-center justify-end space-x-2">
                         <Button
                           type="button"
diff --git a/src/components/IssueDetails/IssueDescription/index.tsx b/src/components/IssueDetails/IssueDescription/index.tsx
index 103626d4..2a06e5be 100644
--- a/src/components/IssueDetails/IssueDescription/index.tsx
+++ b/src/components/IssueDetails/IssueDescription/index.tsx
@@ -1,12 +1,12 @@
+import Button from '@app/components/Common/Button';
+import { Permission, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
 import { Menu, Transition } from '@headlessui/react';
 import { DotsVerticalIcon } from '@heroicons/react/solid';
 import { Field, Form, Formik } from 'formik';
-import React, { Fragment, useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import ReactMarkdown from 'react-markdown';
-import { Permission, useUser } from '../../../hooks/useUser';
-import globalMessages from '../../../i18n/globalMessages';
-import Button from '../../Common/Button';
 
 const messages = defineMessages({
   description: 'Description',
@@ -22,13 +22,13 @@ interface IssueDescriptionProps {
   onDelete: () => void;
 }
 
-const IssueDescription: React.FC<IssueDescriptionProps> = ({
+const IssueDescription = ({
   description,
   belongsToUser,
   commentCount,
   onEdit,
   onDelete,
-}) => {
+}: IssueDescriptionProps) => {
   const intl = useIntl();
   const { hasPermission } = useUser();
   const [isEditing, setIsEditing] = useState(false);
@@ -52,7 +52,7 @@ const IssueDescription: React.FC<IssueDescriptionProps> = ({
 
                 <Transition
                   show={open}
-                  as={Fragment}
+                  as="div"
                   enter="transition ease-out duration-100"
                   enterFrom="transform opacity-0 scale-95"
                   enterTo="transform opacity-100 scale-100"
diff --git a/src/components/IssueDetails/index.tsx b/src/components/IssueDetails/index.tsx
index 8939f61d..7868b626 100644
--- a/src/components/IssueDetails/index.tsx
+++ b/src/components/IssueDetails/index.tsx
@@ -1,38 +1,37 @@
+import Badge from '@app/components/Common/Badge';
+import Button from '@app/components/Common/Button';
+import CachedImage from '@app/components/Common/CachedImage';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import Modal from '@app/components/Common/Modal';
+import PageTitle from '@app/components/Common/PageTitle';
+import IssueComment from '@app/components/IssueDetails/IssueComment';
+import IssueDescription from '@app/components/IssueDetails/IssueDescription';
+import { issueOptions } from '@app/components/IssueModal/constants';
+import { Permission, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import Error from '@app/pages/_error';
+import { Transition } from '@headlessui/react';
 import {
   ChatIcon,
   CheckCircleIcon,
-  ExclamationIcon,
   PlayIcon,
   ServerIcon,
 } from '@heroicons/react/outline';
 import { RefreshIcon } from '@heroicons/react/solid';
+import { IssueStatus } from '@server/constants/issue';
+import { MediaType } from '@server/constants/media';
+import type Issue from '@server/entity/Issue';
+import type { MovieDetails } from '@server/models/Movie';
+import type { TvDetails } from '@server/models/Tv';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
 import Link from 'next/link';
 import { useRouter } from 'next/router';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, FormattedRelativeTime, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import { IssueStatus } from '../../../server/constants/issue';
-import { MediaType } from '../../../server/constants/media';
-import type Issue from '../../../server/entity/Issue';
-import type { MovieDetails } from '../../../server/models/Movie';
-import type { TvDetails } from '../../../server/models/Tv';
-import { Permission, useUser } from '../../hooks/useUser';
-import globalMessages from '../../i18n/globalMessages';
-import Error from '../../pages/_error';
-import Badge from '../Common/Badge';
-import Button from '../Common/Button';
-import CachedImage from '../Common/CachedImage';
-import LoadingSpinner from '../Common/LoadingSpinner';
-import Modal from '../Common/Modal';
-import PageTitle from '../Common/PageTitle';
-import { issueOptions } from '../IssueModal/constants';
-import Transition from '../Transition';
-import IssueComment from './IssueComment';
-import IssueDescription from './IssueDescription';
 
 const messages = defineMessages({
   openedby: '#{issueId} opened {relativeTime} by {username}',
@@ -74,7 +73,7 @@ const isMovie = (movie: MovieDetails | TvDetails): movie is MovieDetails => {
   return (movie as MovieDetails).title !== undefined;
 };
 
-const IssueDetails: React.FC = () => {
+const IssueDetails = () => {
   const { addToast } = useToasts();
   const router = useRouter();
   const intl = useIntl();
@@ -174,6 +173,7 @@ const IssueDetails: React.FC = () => {
     >
       <PageTitle title={[intl.formatMessage(messages.issuepagetitle), title]} />
       <Transition
+        as="div"
         enter="transition opacity-0 duration-300"
         enterFrom="opacity-0"
         enterTo="opacity-100"
@@ -188,7 +188,6 @@ const IssueDetails: React.FC = () => {
           onOk={() => deleteIssue()}
           okText={intl.formatMessage(messages.deleteissue)}
           okButtonType="danger"
-          iconSvg={<ExclamationIcon />}
         >
           {intl.formatMessage(messages.deleteissueconfirm)}
         </Modal>
@@ -264,7 +263,7 @@ const IssueDetails: React.FC = () => {
                 >
                   <a className="group ml-1 inline-flex h-full items-center xl:ml-1.5">
                     <img
-                      className="mr-0.5 h-5 w-5 scale-100 transform-gpu rounded-full transition duration-300 group-hover:scale-105 xl:mr-1 xl:h-6 xl:w-6"
+                      className="mr-0.5 h-5 w-5 scale-100 transform-gpu rounded-full object-cover transition duration-300 group-hover:scale-105 xl:mr-1 xl:h-6 xl:w-6"
                       src={issueData.createdBy.avatar}
                       alt=""
                     />
diff --git a/src/components/IssueList/IssueItem/index.tsx b/src/components/IssueList/IssueItem/index.tsx
index 1695215a..00e48631 100644
--- a/src/components/IssueList/IssueItem/index.tsx
+++ b/src/components/IssueList/IssueItem/index.tsx
@@ -1,20 +1,19 @@
+import Badge from '@app/components/Common/Badge';
+import Button from '@app/components/Common/Button';
+import CachedImage from '@app/components/Common/CachedImage';
+import { issueOptions } from '@app/components/IssueModal/constants';
+import { Permission, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
 import { EyeIcon } from '@heroicons/react/solid';
+import { IssueStatus } from '@server/constants/issue';
+import { MediaType } from '@server/constants/media';
+import type Issue from '@server/entity/Issue';
+import type { MovieDetails } from '@server/models/Movie';
+import type { TvDetails } from '@server/models/Tv';
 import Link from 'next/link';
-import React from 'react';
 import { useInView } from 'react-intersection-observer';
 import { defineMessages, FormattedRelativeTime, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import { IssueStatus } from '../../../../server/constants/issue';
-import { MediaType } from '../../../../server/constants/media';
-import Issue from '../../../../server/entity/Issue';
-import { MovieDetails } from '../../../../server/models/Movie';
-import { TvDetails } from '../../../../server/models/Tv';
-import { Permission, useUser } from '../../../hooks/useUser';
-import globalMessages from '../../../i18n/globalMessages';
-import Badge from '../../Common/Badge';
-import Button from '../../Common/Button';
-import CachedImage from '../../Common/CachedImage';
-import { issueOptions } from '../../IssueModal/constants';
 
 const messages = defineMessages({
   openeduserdate: '{date} by {user}',
@@ -36,7 +35,7 @@ interface IssueItemProps {
   issue: Issue;
 }
 
-const IssueItem: React.FC<IssueItemProps> = ({ issue }) => {
+const IssueItem = ({ issue }: IssueItemProps) => {
   const intl = useIntl();
   const { hasPermission } = useUser();
   const { ref, inView } = useInView({
@@ -228,7 +227,7 @@ const IssueItem: React.FC<IssueItemProps> = ({ issue }) => {
                           <img
                             src={issue.createdBy.avatar}
                             alt=""
-                            className="avatar-sm ml-1.5"
+                            className="avatar-sm ml-1.5 object-cover"
                           />
                           <span className="truncate text-sm font-semibold group-hover:text-white group-hover:underline">
                             {issue.createdBy.displayName}
diff --git a/src/components/IssueList/index.tsx b/src/components/IssueList/index.tsx
index 91e9a8eb..0c2ee3a9 100644
--- a/src/components/IssueList/index.tsx
+++ b/src/components/IssueList/index.tsx
@@ -1,21 +1,21 @@
+import Button from '@app/components/Common/Button';
+import Header from '@app/components/Common/Header';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import IssueItem from '@app/components/IssueList/IssueItem';
+import { useUpdateQueryParams } from '@app/hooks/useUpdateQueryParams';
+import globalMessages from '@app/i18n/globalMessages';
 import {
   ChevronLeftIcon,
   ChevronRightIcon,
   FilterIcon,
   SortDescendingIcon,
 } from '@heroicons/react/solid';
+import type { IssueResultsResponse } from '@server/interfaces/api/issueInterfaces';
 import { useRouter } from 'next/router';
-import React, { useEffect, useState } from 'react';
+import { useEffect, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import { IssueResultsResponse } from '../../../server/interfaces/api/issueInterfaces';
-import Button from '../../components/Common/Button';
-import { useUpdateQueryParams } from '../../hooks/useUpdateQueryParams';
-import globalMessages from '../../i18n/globalMessages';
-import Header from '../Common/Header';
-import LoadingSpinner from '../Common/LoadingSpinner';
-import PageTitle from '../Common/PageTitle';
-import IssueItem from './IssueItem';
 
 const messages = defineMessages({
   issues: 'Issues',
@@ -32,7 +32,7 @@ enum Filter {
 
 type Sort = 'added' | 'modified';
 
-const IssueList: React.FC = () => {
+const IssueList = () => {
   const intl = useIntl();
   const router = useRouter();
   const [currentFilter, setCurrentFilter] = useState<Filter>(Filter.OPEN);
@@ -194,9 +194,9 @@ const IssueList: React.FC = () => {
                       ? pageIndex * currentPageSize + data.results.length
                       : (pageIndex + 1) * currentPageSize,
                   total: data.pageInfo.results,
-                  strong: function strong(msg) {
-                    return <span className="font-medium">{msg}</span>;
-                  },
+                  strong: (msg: React.ReactNode) => (
+                    <span className="font-medium">{msg}</span>
+                  ),
                 })}
             </p>
           </div>
diff --git a/src/components/IssueModal/CreateIssueModal/index.tsx b/src/components/IssueModal/CreateIssueModal/index.tsx
index 5dbc4180..0ed4162f 100644
--- a/src/components/IssueModal/CreateIssueModal/index.tsx
+++ b/src/components/IssueModal/CreateIssueModal/index.tsx
@@ -1,28 +1,25 @@
+import Button from '@app/components/Common/Button';
+import Modal from '@app/components/Common/Modal';
+import { issueOptions } from '@app/components/IssueModal/constants';
+import useSettings from '@app/hooks/useSettings';
+import { Permission, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
 import { RadioGroup } from '@headlessui/react';
-import { ExclamationIcon } from '@heroicons/react/outline';
 import { ArrowCircleRightIcon } from '@heroicons/react/solid';
+import { MediaStatus } from '@server/constants/media';
+import type Issue from '@server/entity/Issue';
+import type { MovieDetails } from '@server/models/Movie';
+import type { TvDetails } from '@server/models/Tv';
 import axios from 'axios';
 import { Field, Formik } from 'formik';
 import Link from 'next/link';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import { MediaStatus } from '../../../../server/constants/media';
-import type Issue from '../../../../server/entity/Issue';
-import { MovieDetails } from '../../../../server/models/Movie';
-import { TvDetails } from '../../../../server/models/Tv';
-import useSettings from '../../../hooks/useSettings';
-import { Permission, useUser } from '../../../hooks/useUser';
-import globalMessages from '../../../i18n/globalMessages';
-import Button from '../../Common/Button';
-import Modal from '../../Common/Modal';
-import { issueOptions } from '../constants';
 
 const messages = defineMessages({
   validationMessageRequired: 'You must provide a description',
-  issomethingwrong: 'Is there a problem with {title}?',
   whatswrong: "What's wrong?",
   providedetail:
     'Please provide a detailed explanation of the issue you encountered.',
@@ -55,11 +52,11 @@ interface CreateIssueModalProps {
   onCancel?: () => void;
 }
 
-const CreateIssueModal: React.FC<CreateIssueModalProps> = ({
+const CreateIssueModal = ({
   onCancel,
   mediaType,
   tmdbId,
-}) => {
+}: CreateIssueModalProps) => {
   const intl = useIntl();
   const settings = useSettings();
   const { hasPermission } = useUser();
@@ -118,9 +115,7 @@ const CreateIssueModal: React.FC<CreateIssueModalProps> = ({
                 <div>
                   {intl.formatMessage(messages.toastSuccessCreate, {
                     title: isMovie(data) ? data.title : data.name,
-                    strong: function strong(msg) {
-                      return <strong>{msg}</strong>;
-                    },
+                    strong: (msg: React.ReactNode) => <strong>{msg}</strong>,
                   })}
                 </div>
                 <Link href={`/issues/${newIssue.data.id}`}>
@@ -153,23 +148,14 @@ const CreateIssueModal: React.FC<CreateIssueModalProps> = ({
           <Modal
             backgroundClickable
             onCancel={onCancel}
-            iconSvg={<ExclamationIcon />}
             title={intl.formatMessage(messages.reportissue)}
+            subTitle={data && isMovie(data) ? data?.title : data?.name}
             cancelText={intl.formatMessage(globalMessages.close)}
             onOk={() => handleSubmit()}
             okText={intl.formatMessage(messages.submitissue)}
             loading={!data && !error}
             backdrop={`https://image.tmdb.org/t/p/w1920_and_h800_multi_faces/${data?.backdropPath}`}
           >
-            {data && (
-              <div className="flex items-center">
-                <span className="mr-1 font-semibold">
-                  {intl.formatMessage(messages.issomethingwrong, {
-                    title: isMovie(data) ? data.title : data.name,
-                  })}
-                </span>
-              </div>
-            )}
             {mediaType === 'tv' && data && !isMovie(data) && (
               <>
                 <div className="form-row">
@@ -267,7 +253,7 @@ const CreateIssueModal: React.FC<CreateIssueModalProps> = ({
                           ? 'rounded-bl-md rounded-br-md'
                           : '',
                         checked
-                          ? 'z-10 border-indigo-500 bg-indigo-600'
+                          ? 'z-10 border border-indigo-500 bg-indigo-400 bg-opacity-20'
                           : 'border-gray-500',
                         'relative flex cursor-pointer border p-4 focus:outline-none'
                       )
@@ -278,7 +264,7 @@ const CreateIssueModal: React.FC<CreateIssueModalProps> = ({
                         <span
                           className={`${
                             checked
-                              ? 'border-transparent bg-indigo-800'
+                              ? 'border-transparent bg-indigo-600'
                               : 'border-gray-300 bg-white'
                           } ${
                             active ? 'ring-2 ring-indigo-300 ring-offset-2' : ''
@@ -315,9 +301,11 @@ const CreateIssueModal: React.FC<CreateIssueModalProps> = ({
                 className="h-28"
                 placeholder={intl.formatMessage(messages.providedetail)}
               />
-              {errors.message && touched.message && (
-                <div className="error">{errors.message}</div>
-              )}
+              {errors.message &&
+                touched.message &&
+                typeof errors.message === 'string' && (
+                  <div className="error">{errors.message}</div>
+                )}
             </div>
           </Modal>
         );
diff --git a/src/components/IssueModal/constants.ts b/src/components/IssueModal/constants.ts
index 92cf6bc7..7552c633 100644
--- a/src/components/IssueModal/constants.ts
+++ b/src/components/IssueModal/constants.ts
@@ -1,5 +1,6 @@
-import { defineMessages, MessageDescriptor } from 'react-intl';
-import { IssueType } from '../../../server/constants/issue';
+import { IssueType } from '@server/constants/issue';
+import type { MessageDescriptor } from 'react-intl';
+import { defineMessages } from 'react-intl';
 
 const messages = defineMessages({
   issueAudio: 'Audio',
diff --git a/src/components/IssueModal/index.tsx b/src/components/IssueModal/index.tsx
index f3f226de..6ec67c24 100644
--- a/src/components/IssueModal/index.tsx
+++ b/src/components/IssueModal/index.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import Transition from '../Transition';
-import CreateIssueModal from './CreateIssueModal';
+import CreateIssueModal from '@app/components/IssueModal/CreateIssueModal';
+import { Transition } from '@headlessui/react';
 
 interface IssueModalProps {
   show?: boolean;
@@ -10,13 +9,9 @@ interface IssueModalProps {
   issueId?: never;
 }
 
-const IssueModal: React.FC<IssueModalProps> = ({
-  show,
-  mediaType,
-  onCancel,
-  tmdbId,
-}) => (
+const IssueModal = ({ show, mediaType, onCancel, tmdbId }: IssueModalProps) => (
   <Transition
+    as="div"
     enter="transition opacity-0 duration-300"
     enterFrom="opacity-0"
     enterTo="opacity-100"
diff --git a/src/components/JSONEditor/index.tsx b/src/components/JSONEditor/index.tsx
index b1de78a7..1bb415c7 100644
--- a/src/components/JSONEditor/index.tsx
+++ b/src/components/JSONEditor/index.tsx
@@ -1,20 +1,15 @@
-import React, { HTMLAttributes } from 'react';
-import AceEditor from 'react-ace';
+import 'ace-builds/src-noconflict/ace';
 import 'ace-builds/src-noconflict/mode-json';
 import 'ace-builds/src-noconflict/theme-dracula';
-
+import type { HTMLAttributes } from 'react';
+import AceEditor from 'react-ace';
 interface JSONEditorProps extends HTMLAttributes<HTMLDivElement> {
   name: string;
   value: string;
   onUpdate: (value: string) => void;
 }
 
-const JSONEditor: React.FC<JSONEditorProps> = ({
-  name,
-  value,
-  onUpdate,
-  onBlur,
-}) => {
+const JSONEditor = ({ name, value, onUpdate, onBlur }: JSONEditorProps) => {
   return (
     <div className="w-full overflow-hidden rounded-md">
       <AceEditor
diff --git a/src/components/LanguageSelector/index.tsx b/src/components/LanguageSelector/index.tsx
index 74c84b15..d8e4cc2f 100644
--- a/src/components/LanguageSelector/index.tsx
+++ b/src/components/LanguageSelector/index.tsx
@@ -1,10 +1,11 @@
+import globalMessages from '@app/i18n/globalMessages';
+import type { Language } from '@server/lib/settings';
 import { sortBy } from 'lodash';
-import React, { useMemo } from 'react';
+import { useMemo } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
-import Select, { CSSObjectWithLabel } from 'react-select';
+import type { CSSObjectWithLabel } from 'react-select';
+import Select from 'react-select';
 import useSWR from 'swr';
-import { Language } from '../../../server/lib/settings';
-import globalMessages from '../../i18n/globalMessages';
 
 const messages = defineMessages({
   originalLanguageDefault: 'All Languages',
@@ -33,12 +34,12 @@ interface LanguageSelectorProps {
   isUserSettings?: boolean;
 }
 
-const LanguageSelector: React.FC<LanguageSelectorProps> = ({
+const LanguageSelector = ({
   value,
   setFieldValue,
   serverValue,
   isUserSettings = false,
-}) => {
+}: LanguageSelectorProps) => {
   const intl = useIntl();
   const { data: languages } = useSWR<Language[]>('/api/v1/languages');
 
diff --git a/src/components/Layout/LanguagePicker/index.tsx b/src/components/Layout/LanguagePicker/index.tsx
index 1d610604..0eec6b7d 100644
--- a/src/components/Layout/LanguagePicker/index.tsx
+++ b/src/components/Layout/LanguagePicker/index.tsx
@@ -1,19 +1,17 @@
+import type { AvailableLocale } from '@app/context/LanguageContext';
+import { availableLanguages } from '@app/context/LanguageContext';
+import useClickOutside from '@app/hooks/useClickOutside';
+import useLocale from '@app/hooks/useLocale';
+import { Transition } from '@headlessui/react';
 import { TranslateIcon } from '@heroicons/react/solid';
-import React, { useRef, useState } from 'react';
+import { useRef, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
-import {
-  availableLanguages,
-  AvailableLocale,
-} from '../../../context/LanguageContext';
-import useClickOutside from '../../../hooks/useClickOutside';
-import useLocale from '../../../hooks/useLocale';
-import Transition from '../../Transition';
 
 const messages = defineMessages({
   displaylanguage: 'Display Language',
 });
 
-const LanguagePicker: React.FC = () => {
+const LanguagePicker = () => {
   const intl = useIntl();
   const dropdownRef = useRef<HTMLDivElement>(null);
   const { locale, setLocale } = useLocale();
@@ -34,6 +32,7 @@ const LanguagePicker: React.FC = () => {
         </button>
       </div>
       <Transition
+        as="div"
         show={isDropdownOpen}
         enter="transition ease-out duration-100 opacity-0"
         enterFrom="transform opacity-0 scale-95"
diff --git a/src/components/Layout/Notifications/index.tsx b/src/components/Layout/Notifications/index.tsx
index 9376b424..eed2697e 100644
--- a/src/components/Layout/Notifications/index.tsx
+++ b/src/components/Layout/Notifications/index.tsx
@@ -1,7 +1,6 @@
 import { BellIcon } from '@heroicons/react/outline';
-import React from 'react';
 
-const Notifications: React.FC = () => {
+const Notifications = () => {
   return (
     <button
       className="rounded-full p-1 text-gray-400 hover:bg-gray-500 hover:text-white focus:text-white focus:outline-none focus:ring"
diff --git a/src/components/Layout/SearchInput/index.tsx b/src/components/Layout/SearchInput/index.tsx
index 8c48fff3..3c971e37 100644
--- a/src/components/Layout/SearchInput/index.tsx
+++ b/src/components/Layout/SearchInput/index.tsx
@@ -1,14 +1,13 @@
+import useSearchInput from '@app/hooks/useSearchInput';
 import { XCircleIcon } from '@heroicons/react/outline';
 import { SearchIcon } from '@heroicons/react/solid';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
-import useSearchInput from '../../../hooks/useSearchInput';
 
 const messages = defineMessages({
   searchPlaceholder: 'Search Movies & TV',
 });
 
-const SearchInput: React.FC = () => {
+const SearchInput = () => {
   const intl = useIntl();
   const { searchValue, setSearchValue, setIsOpen, clear } = useSearchInput();
   return (
diff --git a/src/components/Layout/Sidebar/index.tsx b/src/components/Layout/Sidebar/index.tsx
index 45716eeb..d4933951 100644
--- a/src/components/Layout/Sidebar/index.tsx
+++ b/src/components/Layout/Sidebar/index.tsx
@@ -1,3 +1,7 @@
+import VersionStatus from '@app/components/Layout/VersionStatus';
+import useClickOutside from '@app/hooks/useClickOutside';
+import { Permission, useUser } from '@app/hooks/useUser';
+import { Transition } from '@headlessui/react';
 import {
   ClockIcon,
   CogIcon,
@@ -8,12 +12,8 @@ import {
 } from '@heroicons/react/outline';
 import Link from 'next/link';
 import { useRouter } from 'next/router';
-import React, { ReactNode, useRef } from 'react';
+import { Fragment, useRef } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
-import useClickOutside from '../../../hooks/useClickOutside';
-import { Permission, useUser } from '../../../hooks/useUser';
-import Transition from '../../Transition';
-import VersionStatus from '../VersionStatus';
 
 const messages = defineMessages({
   dashboard: 'Discover',
@@ -30,12 +30,13 @@ interface SidebarProps {
 
 interface SidebarLinkProps {
   href: string;
-  svgIcon: ReactNode;
+  svgIcon: React.ReactNode;
   messagesKey: keyof typeof messages;
   activeRegExp: RegExp;
   as?: string;
   requiredPermission?: Permission | Permission[];
   permissionType?: 'and' | 'or';
+  dataTestId?: string;
 }
 
 const SidebarLinks: SidebarLinkProps[] = [
@@ -71,17 +72,19 @@ const SidebarLinks: SidebarLinkProps[] = [
     svgIcon: <UsersIcon className="mr-3 h-6 w-6" />,
     activeRegExp: /^\/users/,
     requiredPermission: Permission.MANAGE_USERS,
+    dataTestId: 'sidebar-menu-users',
   },
   {
     href: '/settings',
     messagesKey: 'settings',
     svgIcon: <CogIcon className="mr-3 h-6 w-6" />,
     activeRegExp: /^\/settings/,
-    requiredPermission: Permission.MANAGE_SETTINGS,
+    requiredPermission: Permission.ADMIN,
+    dataTestId: 'sidebar-menu-settings',
   },
 ];
 
-const Sidebar: React.FC<SidebarProps> = ({ open, setClosed }) => {
+const Sidebar = ({ open, setClosed }: SidebarProps) => {
   const navRef = useRef<HTMLDivElement>(null);
   const router = useRouter();
   const intl = useIntl();
@@ -91,9 +94,10 @@ const Sidebar: React.FC<SidebarProps> = ({ open, setClosed }) => {
   return (
     <>
       <div className="lg:hidden">
-        <Transition show={open}>
+        <Transition as={Fragment} show={open}>
           <div className="fixed inset-0 z-40 flex">
-            <Transition
+            <Transition.Child
+              as="div"
               enter="transition-opacity ease-linear duration-300"
               enterFrom="opacity-0"
               enterTo="opacity-100"
@@ -104,8 +108,9 @@ const Sidebar: React.FC<SidebarProps> = ({ open, setClosed }) => {
               <div className="fixed inset-0">
                 <div className="absolute inset-0 bg-gray-900 opacity-90"></div>
               </div>
-            </Transition>
-            <Transition
+            </Transition.Child>
+            <Transition.Child
+              as="div"
               enter="transition ease-in-out duration-300 transform"
               enterFrom="-translate-x-full"
               enterTo="translate-x-0"
@@ -114,7 +119,7 @@ const Sidebar: React.FC<SidebarProps> = ({ open, setClosed }) => {
               leaveTo="-translate-x-full"
             >
               <>
-                <div className="sidebar relative flex w-full max-w-xs flex-1 flex-col bg-gray-800">
+                <div className="sidebar relative flex h-full w-full max-w-xs flex-1 flex-col bg-gray-800">
                   <div className="sidebar-close-button absolute top-0 right-0 -mr-14 p-1">
                     <button
                       className="flex h-12 w-12 items-center justify-center rounded-full focus:bg-gray-600 focus:outline-none"
@@ -126,7 +131,7 @@ const Sidebar: React.FC<SidebarProps> = ({ open, setClosed }) => {
                   </div>
                   <div
                     ref={navRef}
-                    className="flex h-0 flex-1 flex-col overflow-y-auto pt-8 pb-8 sm:pb-4"
+                    className="flex flex-1 flex-col overflow-y-auto pt-8 pb-8 sm:pb-4"
                   >
                     <div className="flex flex-shrink-0 items-center px-2">
                       <span className="px-4 text-xl text-gray-50">
@@ -167,6 +172,7 @@ const Sidebar: React.FC<SidebarProps> = ({ open, setClosed }) => {
                                     : 'hover:bg-gray-700 focus:bg-gray-700'
                                 }
                               `}
+                              data-testid={`${sidebarLink.dataTestId}-mobile`}
                             >
                               {sidebarLink.svgIcon}
                               {intl.formatMessage(
@@ -188,7 +194,7 @@ const Sidebar: React.FC<SidebarProps> = ({ open, setClosed }) => {
                   {/* <!-- Force sidebar to shrink to fit close icon --> */}
                 </div>
               </>
-            </Transition>
+            </Transition.Child>
           </div>
         </Transition>
       </div>
@@ -228,6 +234,7 @@ const Sidebar: React.FC<SidebarProps> = ({ open, setClosed }) => {
                                     : 'hover:bg-gray-700 focus:bg-gray-700'
                                 }
                               `}
+                        data-testid={sidebarLink.dataTestId}
                       >
                         {sidebarLink.svgIcon}
                         {intl.formatMessage(messages[sidebarLink.messagesKey])}
diff --git a/src/components/Layout/UserDropdown/MiniQuotaDisplay/index.tsx b/src/components/Layout/UserDropdown/MiniQuotaDisplay/index.tsx
new file mode 100644
index 00000000..abc08dd1
--- /dev/null
+++ b/src/components/Layout/UserDropdown/MiniQuotaDisplay/index.tsx
@@ -0,0 +1,93 @@
+import Infinity from '@app/assets/infinity.svg';
+import { SmallLoadingSpinner } from '@app/components/Common/LoadingSpinner';
+import ProgressCircle from '@app/components/Common/ProgressCircle';
+import type { QuotaResponse } from '@server/interfaces/api/userInterfaces';
+import { defineMessages, useIntl } from 'react-intl';
+import useSWR from 'swr';
+
+const messages = defineMessages({
+  movierequests: 'Movie Requests',
+  seriesrequests: 'Series Requests',
+});
+
+type MiniQuotaDisplayProps = {
+  userId: number;
+};
+
+const MiniQuotaDisplay = ({ userId }: MiniQuotaDisplayProps) => {
+  const intl = useIntl();
+  const { data, error } = useSWR<QuotaResponse>(`/api/v1/user/${userId}/quota`);
+
+  if (error) {
+    return null;
+  }
+
+  if (!data && !error) {
+    return <SmallLoadingSpinner />;
+  }
+
+  return (
+    <>
+      {((data?.movie.limit ?? 0) !== 0 || (data?.tv.limit ?? 0) !== 0) && (
+        <div className="flex">
+          <div className="flex basis-1/2 flex-col space-y-2">
+            <div className="text-sm text-gray-200">
+              {intl.formatMessage(messages.movierequests)}
+            </div>
+            <div className="flex h-full items-center space-x-2 text-gray-200">
+              {data?.movie.limit ?? 0 > 0 ? (
+                <>
+                  <ProgressCircle
+                    className="h-8 w-8"
+                    progress={Math.round(
+                      ((data?.movie.remaining ?? 0) /
+                        (data?.movie.limit ?? 1)) *
+                        100
+                    )}
+                    useHeatLevel
+                  />
+                  <span className="text-lg font-bold">
+                    {data?.movie.remaining} / {data?.movie.limit}
+                  </span>
+                </>
+              ) : (
+                <>
+                  <Infinity className="w-7" />
+                  <span className="font-bold">Unlimited</span>
+                </>
+              )}
+            </div>
+          </div>
+          <div className="flex basis-1/2 flex-col space-y-2">
+            <div className="text-sm text-gray-200">
+              {intl.formatMessage(messages.seriesrequests)}
+            </div>
+            <div className="flex h-full items-center space-x-2 text-gray-200">
+              {data?.tv.limit ?? 0 > 0 ? (
+                <>
+                  <ProgressCircle
+                    className="h-8 w-8"
+                    progress={Math.round(
+                      ((data?.tv.remaining ?? 0) / (data?.tv.limit ?? 1)) * 100
+                    )}
+                    useHeatLevel
+                  />
+                  <span className="text-lg font-bold text-gray-200">
+                    {data?.tv.remaining} / {data?.tv.limit}
+                  </span>
+                </>
+              ) : (
+                <>
+                  <Infinity className="w-7" />
+                  <span className="font-bold">Unlimited</span>
+                </>
+              )}
+            </div>
+          </div>
+        </div>
+      )}
+    </>
+  );
+};
+
+export default MiniQuotaDisplay;
diff --git a/src/components/Layout/UserDropdown/index.tsx b/src/components/Layout/UserDropdown/index.tsx
index a9923117..57481b71 100644
--- a/src/components/Layout/UserDropdown/index.tsx
+++ b/src/components/Layout/UserDropdown/index.tsx
@@ -1,25 +1,39 @@
-import { LogoutIcon } from '@heroicons/react/outline';
+import MiniQuotaDisplay from '@app/components/Layout/UserDropdown/MiniQuotaDisplay';
+import { useUser } from '@app/hooks/useUser';
+import { Menu, Transition } from '@headlessui/react';
+import { ClockIcon, LogoutIcon } from '@heroicons/react/outline';
 import { CogIcon, UserIcon } from '@heroicons/react/solid';
 import axios from 'axios';
+import type { LinkProps } from 'next/link';
 import Link from 'next/link';
-import React, { useRef, useState } from 'react';
+import { forwardRef, Fragment } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
-import useClickOutside from '../../../hooks/useClickOutside';
-import { useUser } from '../../../hooks/useUser';
-import Transition from '../../Transition';
 
 const messages = defineMessages({
   myprofile: 'Profile',
   settings: 'Settings',
+  requests: 'Requests',
   signout: 'Sign Out',
 });
 
-const UserDropdown: React.FC = () => {
+const ForwardedLink = forwardRef<
+  HTMLAnchorElement,
+  LinkProps & React.ComponentPropsWithoutRef<'a'>
+>(({ href, children, ...rest }, ref) => {
+  return (
+    <Link href={href}>
+      <a ref={ref} {...rest}>
+        {children}
+      </a>
+    </Link>
+  );
+});
+
+ForwardedLink.displayName = 'ForwardedLink';
+
+const UserDropdown = () => {
   const intl = useIntl();
-  const dropdownRef = useRef<HTMLDivElement>(null);
   const { user, revalidate } = useUser();
-  const [isDropdownOpen, setDropdownOpen] = useState(false);
-  useClickOutside(dropdownRef, () => setDropdownOpen(false));
 
   const logout = async () => {
     const response = await axios.post('/api/v1/auth/logout');
@@ -30,86 +44,119 @@ const UserDropdown: React.FC = () => {
   };
 
   return (
-    <div className="relative ml-3">
+    <Menu as="div" className="relative ml-3">
       <div>
-        <button
+        <Menu.Button
           className="flex max-w-xs items-center rounded-full text-sm ring-1 ring-gray-700 hover:ring-gray-500 focus:outline-none focus:ring-gray-500"
-          id="user-menu"
-          aria-label="User menu"
-          aria-haspopup="true"
-          onClick={() => setDropdownOpen(true)}
+          data-testid="user-menu"
         >
           <img
-            className="h-8 w-8 rounded-full sm:h-10 sm:w-10"
+            className="h-8 w-8 rounded-full object-cover sm:h-10 sm:w-10"
             src={user?.avatar}
             alt=""
           />
-        </button>
+        </Menu.Button>
       </div>
       <Transition
-        show={isDropdownOpen}
+        as={Fragment}
         enter="transition ease-out duration-100"
         enterFrom="transform opacity-0 scale-95"
         enterTo="transform opacity-100 scale-100"
         leave="transition ease-in duration-75"
         leaveFrom="transform opacity-100 scale-100"
         leaveTo="transform opacity-0 scale-95"
+        appear
       >
-        <div
-          className="absolute right-0 mt-2 w-48 origin-top-right rounded-md shadow-lg"
-          ref={dropdownRef}
-        >
-          <div
-            className="rounded-md bg-gray-700 py-1 ring-1 ring-black ring-opacity-5"
-            role="menu"
-            aria-orientation="vertical"
-            aria-labelledby="user-menu"
-          >
-            <Link href={`/profile`}>
-              <a
-                className="flex items-center px-4 py-2 text-sm font-medium text-gray-200 transition duration-150 ease-in-out hover:bg-gray-600"
-                role="menuitem"
-                tabIndex={0}
-                onKeyDown={(e) => {
-                  if (e.key === 'Enter') {
-                    setDropdownOpen(false);
-                  }
-                }}
-                onClick={() => setDropdownOpen(false)}
-              >
-                <UserIcon className="mr-2 inline h-5 w-5" />
-                <span>{intl.formatMessage(messages.myprofile)}</span>
-              </a>
-            </Link>
-            <Link href={`/profile/settings`}>
-              <a
-                className="flex items-center px-4 py-2 text-sm font-medium text-gray-200 transition duration-150 ease-in-out hover:bg-gray-600"
-                role="menuitem"
-                tabIndex={0}
-                onKeyDown={(e) => {
-                  if (e.key === 'Enter') {
-                    setDropdownOpen(false);
-                  }
-                }}
-                onClick={() => setDropdownOpen(false)}
-              >
-                <CogIcon className="mr-2 inline h-5 w-5" />
-                <span>{intl.formatMessage(messages.settings)}</span>
-              </a>
-            </Link>
-            <a
-              href="#"
-              className="flex items-center px-4 py-2 text-sm font-medium text-gray-200 transition duration-150 ease-in-out hover:bg-gray-600"
-              role="menuitem"
-              onClick={() => logout()}
-            >
-              <LogoutIcon className="mr-2 inline h-5 w-5" />
-              <span>{intl.formatMessage(messages.signout)}</span>
-            </a>
+        <Menu.Items className="absolute right-0 mt-2 w-72 origin-top-right rounded-md shadow-lg">
+          <div className="divide-y divide-gray-700 rounded-md bg-gray-800 bg-opacity-80 ring-1 ring-gray-700 backdrop-blur">
+            <div className="flex flex-col space-y-4 px-4 py-4">
+              <div className="flex items-center space-x-2">
+                <img
+                  className="h-8 w-8 rounded-full object-cover sm:h-10 sm:w-10"
+                  src={user?.avatar}
+                  alt=""
+                />
+                <div className="flex min-w-0 flex-col">
+                  <span className="truncate text-xl font-semibold text-gray-200">
+                    {user?.displayName}
+                  </span>
+                  <span className="truncate text-sm text-gray-400">
+                    {user?.email}
+                  </span>
+                </div>
+              </div>
+              {user && <MiniQuotaDisplay userId={user?.id} />}
+            </div>
+            <div className="p-1">
+              <Menu.Item>
+                {({ active }) => (
+                  <ForwardedLink
+                    href={`/profile`}
+                    className={`flex items-center rounded px-4 py-2 text-sm font-medium text-gray-200 transition duration-150 ease-in-out ${
+                      active
+                        ? 'bg-gradient-to-br from-indigo-600 to-purple-600 text-white'
+                        : ''
+                    }`}
+                    data-testid="user-menu-profile"
+                  >
+                    <UserIcon className="mr-2 inline h-5 w-5" />
+                    <span>{intl.formatMessage(messages.myprofile)}</span>
+                  </ForwardedLink>
+                )}
+              </Menu.Item>
+              <Menu.Item>
+                {({ active }) => (
+                  <ForwardedLink
+                    href={`/users/${user?.id}/requests?filter=all`}
+                    className={`flex items-center rounded px-4 py-2 text-sm font-medium text-gray-200 transition duration-150 ease-in-out ${
+                      active
+                        ? 'bg-gradient-to-br from-indigo-600 to-purple-600 text-white'
+                        : ''
+                    }`}
+                    data-testid="user-menu-settings"
+                  >
+                    <ClockIcon className="mr-2 inline h-5 w-5" />
+                    <span>{intl.formatMessage(messages.requests)}</span>
+                  </ForwardedLink>
+                )}
+              </Menu.Item>
+              <Menu.Item>
+                {({ active }) => (
+                  <ForwardedLink
+                    href={`/profile/settings`}
+                    className={`flex items-center rounded px-4 py-2 text-sm font-medium text-gray-200 transition duration-150 ease-in-out ${
+                      active
+                        ? 'bg-gradient-to-br from-indigo-600 to-purple-600 text-white'
+                        : ''
+                    }`}
+                    data-testid="user-menu-settings"
+                  >
+                    <CogIcon className="mr-2 inline h-5 w-5" />
+                    <span>{intl.formatMessage(messages.settings)}</span>
+                  </ForwardedLink>
+                )}
+              </Menu.Item>
+              <Menu.Item>
+                {({ active }) => (
+                  <a
+                    href="#"
+                    className={`flex items-center rounded px-4 py-2 text-sm font-medium text-gray-200 transition duration-150 ease-in-out ${
+                      active
+                        ? 'bg-gradient-to-br from-indigo-600 to-purple-600 text-white'
+                        : ''
+                    }`}
+                    onClick={() => logout()}
+                  >
+                    <LogoutIcon className="mr-2 inline h-5 w-5" />
+                    <span>{intl.formatMessage(messages.signout)}</span>
+                  </a>
+                )}
+              </Menu.Item>
+            </div>
           </div>
-        </div>
+        </Menu.Items>
       </Transition>
-    </div>
+    </Menu>
   );
 };
 
diff --git a/src/components/Layout/VersionStatus/index.tsx b/src/components/Layout/VersionStatus/index.tsx
index d682df4c..515ff20e 100644
--- a/src/components/Layout/VersionStatus/index.tsx
+++ b/src/components/Layout/VersionStatus/index.tsx
@@ -4,11 +4,10 @@ import {
   CodeIcon,
   ServerIcon,
 } from '@heroicons/react/outline';
+import type { StatusResponse } from '@server/interfaces/api/settingsInterfaces';
 import Link from 'next/link';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import { StatusResponse } from '../../../../server/interfaces/api/settingsInterfaces';
 
 const messages = defineMessages({
   streamdevelop: 'Overseerr Develop',
@@ -22,7 +21,7 @@ interface VersionStatusProps {
   onClick?: () => void;
 }
 
-const VersionStatus: React.FC<VersionStatusProps> = ({ onClick }) => {
+const VersionStatus = ({ onClick }: VersionStatusProps) => {
   const intl = useIntl();
   const { data } = useSWR<StatusResponse>('/api/v1/status', {
     refreshInterval: 60 * 1000,
diff --git a/src/components/Layout/index.tsx b/src/components/Layout/index.tsx
index bde59277..22c131ae 100644
--- a/src/components/Layout/index.tsx
+++ b/src/components/Layout/index.tsx
@@ -1,16 +1,21 @@
+import SearchInput from '@app/components/Layout/SearchInput';
+import Sidebar from '@app/components/Layout/Sidebar';
+import UserDropdown from '@app/components/Layout/UserDropdown';
+import PullToRefresh from '@app/components/PullToRefresh';
+import type { AvailableLocale } from '@app/context/LanguageContext';
+import useLocale from '@app/hooks/useLocale';
+import useSettings from '@app/hooks/useSettings';
+import { useUser } from '@app/hooks/useUser';
 import { MenuAlt2Icon } from '@heroicons/react/outline';
 import { ArrowLeftIcon } from '@heroicons/react/solid';
 import { useRouter } from 'next/router';
-import React, { useEffect, useState } from 'react';
-import { AvailableLocale } from '../../context/LanguageContext';
-import useLocale from '../../hooks/useLocale';
-import useSettings from '../../hooks/useSettings';
-import { useUser } from '../../hooks/useUser';
-import SearchInput from './SearchInput';
-import Sidebar from './Sidebar';
-import UserDropdown from './UserDropdown';
+import { useEffect, useState } from 'react';
 
-const Layout: React.FC = ({ children }) => {
+type LayoutProps = {
+  children: React.ReactNode;
+};
+
+const Layout = ({ children }: LayoutProps) => {
   const [isSidebarOpen, setSidebarOpen] = useState(false);
   const [isScrolled, setIsScrolled] = useState(false);
   const { user } = useUser();
@@ -53,6 +58,7 @@ const Layout: React.FC = ({ children }) => {
       <Sidebar open={isSidebarOpen} setClosed={() => setSidebarOpen(false)} />
 
       <div className="relative mb-16 flex w-0 min-w-0 flex-1 flex-col lg:ml-64">
+        <PullToRefresh />
         <div
           className={`searchbar fixed left-0 right-0 top-0 z-10 flex flex-shrink-0 bg-opacity-80 transition duration-300 ${
             isScrolled ? 'bg-gray-700' : 'bg-transparent'
@@ -68,6 +74,7 @@ const Layout: React.FC = ({ children }) => {
             } transition duration-300 focus:outline-none lg:hidden`}
             aria-label="Open sidebar"
             onClick={() => setSidebarOpen(true)}
+            data-testid="sidebar-toggle"
           >
             <MenuAlt2Icon className="h-6 w-6" />
           </button>
diff --git a/src/components/LoadingBar/index.tsx b/src/components/LoadingBar/index.tsx
index 712ba4db..1e488c67 100644
--- a/src/components/LoadingBar/index.tsx
+++ b/src/components/LoadingBar/index.tsx
@@ -1,7 +1,7 @@
 import { NProgress } from '@tanem/react-nprogress';
+import { useRouter } from 'next/router';
 import React, { useEffect, useState } from 'react';
 import ReactDOM from 'react-dom';
-import { useRouter } from 'next/router';
 
 interface BarProps {
   progress: number;
diff --git a/src/components/Login/LocalLogin.tsx b/src/components/Login/LocalLogin.tsx
index 2480a8d5..5ea2a01c 100644
--- a/src/components/Login/LocalLogin.tsx
+++ b/src/components/Login/LocalLogin.tsx
@@ -1,13 +1,13 @@
+import Button from '@app/components/Common/Button';
+import SensitiveInput from '@app/components/Common/SensitiveInput';
+import useSettings from '@app/hooks/useSettings';
 import { LoginIcon, SupportIcon } from '@heroicons/react/outline';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
 import Link from 'next/link';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import * as Yup from 'yup';
-import useSettings from '../../hooks/useSettings';
-import Button from '../Common/Button';
-import SensitiveInput from '../Common/SensitiveInput';
 
 const messages = defineMessages({
   email: 'Email Address',
@@ -24,7 +24,7 @@ interface LocalLoginProps {
   revalidate: () => void;
 }
 
-const LocalLogin: React.FC<LocalLoginProps> = ({ revalidate }) => {
+const LocalLogin = ({ revalidate }: LocalLoginProps) => {
   const intl = useIntl();
   const settings = useSettings();
   const [loginError, setLoginError] = useState<string | null>(null);
@@ -77,11 +77,14 @@ const LocalLogin: React.FC<LocalLoginProps> = ({ revalidate }) => {
                       name="email"
                       type="text"
                       inputMode="email"
+                      data-testid="email"
                     />
                   </div>
-                  {errors.email && touched.email && (
-                    <div className="error">{errors.email}</div>
-                  )}
+                  {errors.email &&
+                    touched.email &&
+                    typeof errors.email === 'string' && (
+                      <div className="error">{errors.email}</div>
+                    )}
                 </div>
                 <label htmlFor="password" className="text-label">
                   {intl.formatMessage(messages.password)}
@@ -94,11 +97,14 @@ const LocalLogin: React.FC<LocalLoginProps> = ({ revalidate }) => {
                       name="password"
                       type="password"
                       autoComplete="current-password"
+                      data-testid="password"
                     />
                   </div>
-                  {errors.password && touched.password && (
-                    <div className="error">{errors.password}</div>
-                  )}
+                  {errors.password &&
+                    touched.password &&
+                    typeof errors.password === 'string' && (
+                      <div className="error">{errors.password}</div>
+                    )}
                 </div>
                 {loginError && (
                   <div className="mt-1 mb-2 sm:col-span-2 sm:mt-0">
@@ -113,6 +119,7 @@ const LocalLogin: React.FC<LocalLoginProps> = ({ revalidate }) => {
                       buttonType="primary"
                       type="submit"
                       disabled={isSubmitting || !isValid}
+                      data-testid="local-signin-button"
                     >
                       <LoginIcon />
                       <span>
diff --git a/src/components/Login/index.tsx b/src/components/Login/index.tsx
index d50e84e0..2dc177a1 100644
--- a/src/components/Login/index.tsx
+++ b/src/components/Login/index.tsx
@@ -1,18 +1,18 @@
+import Accordion from '@app/components/Common/Accordion';
+import ImageFader from '@app/components/Common/ImageFader';
+import PageTitle from '@app/components/Common/PageTitle';
+import LanguagePicker from '@app/components/Layout/LanguagePicker';
+import LocalLogin from '@app/components/Login/LocalLogin';
+import PlexLoginButton from '@app/components/PlexLoginButton';
+import useSettings from '@app/hooks/useSettings';
+import { useUser } from '@app/hooks/useUser';
+import { Transition } from '@headlessui/react';
 import { XCircleIcon } from '@heroicons/react/solid';
 import axios from 'axios';
 import { useRouter } from 'next/dist/client/router';
-import React, { useEffect, useState } from 'react';
+import { useEffect, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import useSettings from '../../hooks/useSettings';
-import { useUser } from '../../hooks/useUser';
-import Accordion from '../Common/Accordion';
-import ImageFader from '../Common/ImageFader';
-import PageTitle from '../Common/PageTitle';
-import LanguagePicker from '../Layout/LanguagePicker';
-import PlexLoginButton from '../PlexLoginButton';
-import Transition from '../Transition';
-import LocalLogin from './LocalLogin';
 
 const messages = defineMessages({
   signin: 'Sign In',
@@ -21,7 +21,7 @@ const messages = defineMessages({
   signinwithoverseerr: 'Use your {applicationTitle} account',
 });
 
-const Login: React.FC = () => {
+const Login = () => {
   const intl = useIntl();
   const [error, setError] = useState('');
   const [isProcessing, setProcessing] = useState(false);
@@ -73,7 +73,7 @@ const Login: React.FC = () => {
       <ImageFader
         backgroundImages={
           backdrops?.map(
-            (backdrop) => `https://www.themoviedb.org/t/p/original${backdrop}`
+            (backdrop) => `https://image.tmdb.org/t/p/original${backdrop}`
           ) ?? []
         }
       />
@@ -93,6 +93,7 @@ const Login: React.FC = () => {
         >
           <>
             <Transition
+              as="div"
               show={!!error}
               enter="opacity-0 transition duration-300"
               enterFrom="opacity-0"
diff --git a/src/components/ManageSlideOver/index.tsx b/src/components/ManageSlideOver/index.tsx
index 8c6f2791..ca89f08a 100644
--- a/src/components/ManageSlideOver/index.tsx
+++ b/src/components/ManageSlideOver/index.tsx
@@ -1,27 +1,23 @@
+import Button from '@app/components/Common/Button';
+import ConfirmButton from '@app/components/Common/ConfirmButton';
+import SlideOver from '@app/components/Common/SlideOver';
+import DownloadBlock from '@app/components/DownloadBlock';
+import IssueBlock from '@app/components/IssueBlock';
+import RequestBlock from '@app/components/RequestBlock';
+import useSettings from '@app/hooks/useSettings';
+import { Permission, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
 import { ServerIcon, ViewListIcon } from '@heroicons/react/outline';
 import { CheckCircleIcon, DocumentRemoveIcon } from '@heroicons/react/solid';
+import { IssueStatus } from '@server/constants/issue';
+import { MediaRequestStatus, MediaStatus } from '@server/constants/media';
+import type { MediaWatchDataResponse } from '@server/interfaces/api/mediaInterfaces';
+import type { MovieDetails } from '@server/models/Movie';
+import type { TvDetails } from '@server/models/Tv';
 import axios from 'axios';
 import Link from 'next/link';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import { IssueStatus } from '../../../server/constants/issue';
-import {
-  MediaRequestStatus,
-  MediaStatus,
-} from '../../../server/constants/media';
-import { MediaWatchDataResponse } from '../../../server/interfaces/api/mediaInterfaces';
-import { MovieDetails } from '../../../server/models/Movie';
-import { TvDetails } from '../../../server/models/Tv';
-import useSettings from '../../hooks/useSettings';
-import { Permission, useUser } from '../../hooks/useUser';
-import globalMessages from '../../i18n/globalMessages';
-import Button from '../Common/Button';
-import ConfirmButton from '../Common/ConfirmButton';
-import SlideOver from '../Common/SlideOver';
-import DownloadBlock from '../DownloadBlock';
-import IssueBlock from '../IssueBlock';
-import RequestBlock from '../RequestBlock';
 
 const messages = defineMessages({
   manageModalTitle: 'Manage {mediaType}',
@@ -72,9 +68,13 @@ interface ManageSlideOverTvProps extends ManageSlideOverProps {
   data: TvDetails;
 }
 
-const ManageSlideOver: React.FC<
-  ManageSlideOverMovieProps | ManageSlideOverTvProps
-> = ({ show, mediaType, onClose, data, revalidate }) => {
+const ManageSlideOver = ({
+  show,
+  mediaType,
+  onClose,
+  data,
+  revalidate,
+}: ManageSlideOverMovieProps | ManageSlideOverTvProps) => {
   const { user: currentUser, hasPermission } = useUser();
   const intl = useIntl();
   const settings = useSettings();
@@ -115,9 +115,9 @@ const ManageSlideOver: React.FC<
       <>
         {intl.formatMessage(messages.plays, {
           playCount,
-          strong: function strong(msg) {
-            return <strong className="text-2xl font-semibold">{msg}</strong>;
-          },
+          strong: (msg: React.ReactNode) => (
+            <strong className="text-2xl font-semibold">{msg}</strong>
+          ),
         })}
       </>
     );
@@ -141,7 +141,7 @@ const ManageSlideOver: React.FC<
             <h3 className="mb-2 text-xl font-bold">
               {intl.formatMessage(messages.downloadstatus)}
             </h3>
-            <div className="overflow-hidden rounded-md bg-gray-600 shadow">
+            <div className="overflow-hidden rounded-md border border-gray-700 shadow">
               <ul>
                 {data.mediaInfo?.downloadStatus?.map((status, index) => (
                   <li
@@ -167,11 +167,11 @@ const ManageSlideOver: React.FC<
           type: 'or',
         }) &&
           openIssues.length > 0 && (
-            <>
+            <div>
               <h3 className="mb-2 text-xl font-bold">
                 {intl.formatMessage(messages.manageModalIssues)}
               </h3>
-              <div className="overflow-hidden rounded-md bg-gray-600 shadow">
+              <div className="overflow-hidden rounded-md border border-gray-700 shadow">
                 <ul>
                   {openIssues.map((issue) => (
                     <li
@@ -183,14 +183,14 @@ const ManageSlideOver: React.FC<
                   ))}
                 </ul>
               </div>
-            </>
+            </div>
           )}
         {requests.length > 0 && (
           <div>
             <h3 className="mb-2 text-xl font-bold">
               {intl.formatMessage(messages.manageModalRequests)}
             </h3>
-            <div className="overflow-hidden rounded-md bg-gray-600 shadow">
+            <div className="overflow-hidden rounded-md border border-gray-700 shadow">
               <ul>
                 {requests.map((request) => (
                   <li
@@ -210,77 +210,81 @@ const ManageSlideOver: React.FC<
         {hasPermission(Permission.ADMIN) &&
           (data.mediaInfo?.serviceUrl ||
             data.mediaInfo?.tautulliUrl ||
-            watchData?.data?.playCount) && (
+            watchData?.data) && (
             <div>
               <h3 className="mb-2 text-xl font-bold">
                 {intl.formatMessage(messages.manageModalMedia)}
               </h3>
               <div className="space-y-2">
-                {!!watchData?.data && (
+                {(watchData?.data || data.mediaInfo?.tautulliUrl) && (
                   <div>
-                    <div
-                      className={`grid grid-cols-1 divide-y divide-gray-500 overflow-hidden bg-gray-600 text-sm text-gray-300 shadow ${
-                        data.mediaInfo?.tautulliUrl
-                          ? 'rounded-t-md'
-                          : 'rounded-md'
-                      }`}
-                    >
-                      <div className="grid grid-cols-3 divide-x divide-gray-500">
-                        <div className="px-4 py-3">
-                          <div className="font-bold">
-                            {intl.formatMessage(messages.pastdays, { days: 7 })}
-                          </div>
-                          <div className="text-white">
-                            {styledPlayCount(watchData.data.playCount7Days)}
+                    {!!watchData?.data && (
+                      <div
+                        className={`grid grid-cols-1 divide-y divide-gray-700 overflow-hidden border-gray-700 text-sm text-gray-300 shadow ${
+                          data.mediaInfo?.tautulliUrl
+                            ? 'rounded-t-md border-x border-t'
+                            : 'rounded-md border'
+                        }`}
+                      >
+                        <div className="grid grid-cols-3 divide-x divide-gray-700">
+                          <div className="px-4 py-3">
+                            <div className="font-bold">
+                              {intl.formatMessage(messages.pastdays, {
+                                days: 7,
+                              })}
+                            </div>
+                            <div className="text-white">
+                              {styledPlayCount(watchData.data.playCount7Days)}
+                            </div>
                           </div>
-                        </div>
-                        <div className="px-4 py-3">
-                          <div className="font-bold">
-                            {intl.formatMessage(messages.pastdays, {
-                              days: 30,
-                            })}
+                          <div className="px-4 py-3">
+                            <div className="font-bold">
+                              {intl.formatMessage(messages.pastdays, {
+                                days: 30,
+                              })}
+                            </div>
+                            <div className="text-white">
+                              {styledPlayCount(watchData.data.playCount30Days)}
+                            </div>
                           </div>
-                          <div className="text-white">
-                            {styledPlayCount(watchData.data.playCount30Days)}
+                          <div className="px-4 py-3">
+                            <div className="font-bold">
+                              {intl.formatMessage(messages.alltime)}
+                            </div>
+                            <div className="text-white">
+                              {styledPlayCount(watchData.data.playCount)}
+                            </div>
                           </div>
                         </div>
-                        <div className="px-4 py-3">
-                          <div className="font-bold">
-                            {intl.formatMessage(messages.alltime)}
+                        {!!watchData.data.users.length && (
+                          <div className="flex flex-row space-x-2 px-4 pt-3 pb-2">
+                            <span className="shrink-0 font-bold leading-8">
+                              {intl.formatMessage(messages.playedby)}
+                            </span>
+                            <span className="flex flex-row flex-wrap">
+                              {watchData.data.users.map((user) => (
+                                <Link
+                                  href={
+                                    currentUser?.id === user.id
+                                      ? '/profile'
+                                      : `/users/${user.id}`
+                                  }
+                                  key={`watch-user-${user.id}`}
+                                >
+                                  <a className="z-0 mb-1 -mr-2 shrink-0 hover:z-50">
+                                    <img
+                                      src={user.avatar}
+                                      alt={user.displayName}
+                                      className="h-8 w-8 scale-100 transform-gpu rounded-full object-cover ring-1 ring-gray-500 transition duration-300 hover:scale-105"
+                                    />
+                                  </a>
+                                </Link>
+                              ))}
+                            </span>
                           </div>
-                          <div className="text-white">
-                            {styledPlayCount(watchData.data.playCount)}
-                          </div>
-                        </div>
+                        )}
                       </div>
-                      {!!watchData.data.users.length && (
-                        <div className="flex flex-row space-x-2 px-4 pt-3 pb-2">
-                          <span className="shrink-0 font-bold leading-8">
-                            {intl.formatMessage(messages.playedby)}
-                          </span>
-                          <span className="flex flex-row flex-wrap">
-                            {watchData.data.users.map((user) => (
-                              <Link
-                                href={
-                                  currentUser?.id === user.id
-                                    ? '/profile'
-                                    : `/users/${user.id}`
-                                }
-                                key={`watch-user-${user.id}`}
-                              >
-                                <a className="z-0 mb-1 -mr-2 shrink-0 hover:z-50">
-                                  <img
-                                    src={user.avatar}
-                                    alt={user.displayName}
-                                    className="h-8 w-8 scale-100 transform-gpu rounded-full ring-1 ring-gray-500 transition duration-300 hover:scale-105"
-                                  />
-                                </a>
-                              </Link>
-                            ))}
-                          </span>
-                        </div>
-                      )}
-                    </div>
+                    )}
                     {data.mediaInfo?.tautulliUrl && (
                       <a
                         href={data.mediaInfo.tautulliUrl}
@@ -290,7 +294,7 @@ const ManageSlideOver: React.FC<
                         <Button
                           buttonType="ghost"
                           className={`w-full ${
-                            watchData.data.playCount ? 'rounded-t-none' : ''
+                            watchData?.data ? 'rounded-t-none' : ''
                           }`}
                         >
                           <ViewListIcon />
@@ -302,7 +306,7 @@ const ManageSlideOver: React.FC<
                     )}
                   </div>
                 )}
-                {data?.mediaInfo?.serviceUrl && (
+                {data.mediaInfo?.serviceUrl && (
                   <a
                     href={data?.mediaInfo?.serviceUrl}
                     target="_blank"
@@ -325,77 +329,83 @@ const ManageSlideOver: React.FC<
         {hasPermission(Permission.ADMIN) &&
           (data.mediaInfo?.serviceUrl4k ||
             data.mediaInfo?.tautulliUrl4k ||
-            watchData?.data4k?.playCount) && (
+            watchData?.data4k) && (
             <div>
               <h3 className="mb-2 text-xl font-bold">
                 {intl.formatMessage(messages.manageModalMedia4k)}
               </h3>
               <div className="space-y-2">
-                {!!watchData?.data4k && (
+                {(watchData?.data4k || data.mediaInfo?.tautulliUrl4k) && (
                   <div>
-                    <div
-                      className={`grid grid-cols-1 divide-y divide-gray-500 overflow-hidden bg-gray-600 text-sm text-gray-300 shadow ${
-                        data.mediaInfo?.tautulliUrl4k
-                          ? 'rounded-t-md'
-                          : 'rounded-md'
-                      }`}
-                    >
-                      <div className="grid grid-cols-3 divide-x divide-gray-500">
-                        <div className="px-4 py-3">
-                          <div className="font-bold">
-                            {intl.formatMessage(messages.pastdays, { days: 7 })}
-                          </div>
-                          <div className="text-white">
-                            {styledPlayCount(watchData.data4k.playCount7Days)}
+                    {watchData?.data4k && (
+                      <div
+                        className={`grid grid-cols-1 divide-y divide-gray-700 overflow-hidden border-gray-700 text-sm text-gray-300 shadow ${
+                          data.mediaInfo?.tautulliUrl4k
+                            ? 'rounded-t-md border-x border-t'
+                            : 'rounded-md border'
+                        }`}
+                      >
+                        <div className="grid grid-cols-3 divide-x divide-gray-700">
+                          <div className="px-4 py-3">
+                            <div className="font-bold">
+                              {intl.formatMessage(messages.pastdays, {
+                                days: 7,
+                              })}
+                            </div>
+                            <div className="text-white">
+                              {styledPlayCount(watchData.data4k.playCount7Days)}
+                            </div>
                           </div>
-                        </div>
-                        <div className="px-4 py-3">
-                          <div className="font-bold">
-                            {intl.formatMessage(messages.pastdays, {
-                              days: 30,
-                            })}
+                          <div className="px-4 py-3">
+                            <div className="font-bold">
+                              {intl.formatMessage(messages.pastdays, {
+                                days: 30,
+                              })}
+                            </div>
+                            <div className="text-white">
+                              {styledPlayCount(
+                                watchData.data4k.playCount30Days
+                              )}
+                            </div>
                           </div>
-                          <div className="text-white">
-                            {styledPlayCount(watchData.data4k.playCount30Days)}
+                          <div className="px-4 py-3">
+                            <div className="font-bold">
+                              {intl.formatMessage(messages.alltime)}
+                            </div>
+                            <div className="text-white">
+                              {styledPlayCount(watchData.data4k.playCount)}
+                            </div>
                           </div>
                         </div>
-                        <div className="px-4 py-3">
-                          <div className="font-bold">
-                            {intl.formatMessage(messages.alltime)}
-                          </div>
-                          <div className="text-white">
-                            {styledPlayCount(watchData.data4k.playCount)}
+                        {!!watchData.data4k.users.length && (
+                          <div className="flex flex-row space-x-2 px-4 pt-3 pb-2">
+                            <span className="shrink-0 font-bold leading-8">
+                              {intl.formatMessage(messages.playedby)}
+                            </span>
+                            <span className="flex flex-row flex-wrap">
+                              {watchData.data4k.users.map((user) => (
+                                <Link
+                                  href={
+                                    currentUser?.id === user.id
+                                      ? '/profile'
+                                      : `/users/${user.id}`
+                                  }
+                                  key={`watch-user-${user.id}`}
+                                >
+                                  <a className="z-0 mb-1 -mr-2 shrink-0 hover:z-50">
+                                    <img
+                                      src={user.avatar}
+                                      alt={user.displayName}
+                                      className="h-8 w-8 scale-100 transform-gpu rounded-full object-cover ring-1 ring-gray-500 transition duration-300 hover:scale-105"
+                                    />
+                                  </a>
+                                </Link>
+                              ))}
+                            </span>
                           </div>
-                        </div>
+                        )}
                       </div>
-                      {!!watchData.data4k.users.length && (
-                        <div className="flex flex-row space-x-2 px-4 pt-3 pb-2">
-                          <span className="shrink-0 font-bold leading-8">
-                            {intl.formatMessage(messages.playedby)}
-                          </span>
-                          <span className="flex flex-row flex-wrap">
-                            {watchData.data4k.users.map((user) => (
-                              <Link
-                                href={
-                                  currentUser?.id === user.id
-                                    ? '/profile'
-                                    : `/users/${user.id}`
-                                }
-                                key={`watch-user-${user.id}`}
-                              >
-                                <a className="z-0 mb-1 -mr-2 shrink-0 hover:z-50">
-                                  <img
-                                    src={user.avatar}
-                                    alt={user.displayName}
-                                    className="h-8 w-8 scale-100 transform-gpu rounded-full ring-1 ring-gray-500 transition duration-300 hover:scale-105"
-                                  />
-                                </a>
-                              </Link>
-                            ))}
-                          </span>
-                        </div>
-                      )}
-                    </div>
+                    )}
                     {data.mediaInfo?.tautulliUrl4k && (
                       <a
                         href={data.mediaInfo.tautulliUrl4k}
@@ -405,7 +415,7 @@ const ManageSlideOver: React.FC<
                         <Button
                           buttonType="ghost"
                           className={`w-full ${
-                            watchData.data4k.playCount ? 'rounded-t-none' : ''
+                            watchData?.data4k ? 'rounded-t-none' : ''
                           }`}
                         >
                           <ViewListIcon />
@@ -487,7 +497,7 @@ const ManageSlideOver: React.FC<
                     {intl.formatMessage(messages.manageModalClearMedia)}
                   </span>
                 </ConfirmButton>
-                <div className="mt-1 text-xs text-gray-400">
+                <div className="mt-2 text-xs text-gray-400">
                   {intl.formatMessage(messages.manageModalClearMediaWarning, {
                     mediaType: intl.formatMessage(
                       mediaType === 'movie' ? messages.movie : messages.tvshow
diff --git a/src/components/MediaSlider/ShowMoreCard/index.tsx b/src/components/MediaSlider/ShowMoreCard/index.tsx
index f6bc2ccb..99900ac9 100644
--- a/src/components/MediaSlider/ShowMoreCard/index.tsx
+++ b/src/components/MediaSlider/ShowMoreCard/index.tsx
@@ -1,6 +1,6 @@
 import { ArrowCircleRightIcon } from '@heroicons/react/solid';
 import Link from 'next/link';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 
 const messages = defineMessages({
@@ -12,7 +12,7 @@ interface ShowMoreCardProps {
   posters: (string | undefined)[];
 }
 
-const ShowMoreCard: React.FC<ShowMoreCardProps> = ({ url, posters }) => {
+const ShowMoreCard = ({ url, posters }: ShowMoreCardProps) => {
   const intl = useIntl();
   const [isHovered, setHovered] = useState(false);
   return (
diff --git a/src/components/MediaSlider/index.tsx b/src/components/MediaSlider/index.tsx
index 84c72822..9a9bc054 100644
--- a/src/components/MediaSlider/index.tsx
+++ b/src/components/MediaSlider/index.tsx
@@ -1,18 +1,18 @@
+import ShowMoreCard from '@app/components/MediaSlider/ShowMoreCard';
+import PersonCard from '@app/components/PersonCard';
+import Slider from '@app/components/Slider';
+import TitleCard from '@app/components/TitleCard';
+import useSettings from '@app/hooks/useSettings';
 import { ArrowCircleRightIcon } from '@heroicons/react/outline';
-import Link from 'next/link';
-import React, { useEffect } from 'react';
-import useSWRInfinite from 'swr/infinite';
-import { MediaStatus } from '../../../server/constants/media';
+import { MediaStatus } from '@server/constants/media';
 import type {
   MovieResult,
   PersonResult,
   TvResult,
-} from '../../../server/models/Search';
-import useSettings from '../../hooks/useSettings';
-import PersonCard from '../PersonCard';
-import Slider from '../Slider';
-import TitleCard from '../TitleCard';
-import ShowMoreCard from './ShowMoreCard';
+} from '@server/models/Search';
+import Link from 'next/link';
+import { useEffect } from 'react';
+import useSWRInfinite from 'swr/infinite';
 
 interface MixedResult {
   page: number;
@@ -29,13 +29,13 @@ interface MediaSliderProps {
   hideWhenEmpty?: boolean;
 }
 
-const MediaSlider: React.FC<MediaSliderProps> = ({
+const MediaSlider = ({
   title,
   url,
   linkUrl,
   sliderKey,
   hideWhenEmpty = false,
-}) => {
+}: MediaSliderProps) => {
   const settings = useSettings();
   const { data, error, setSize, size } = useSWRInfinite<MixedResult>(
     (pageIndex: number, previousPageData: MixedResult | null) => {
diff --git a/src/components/MovieDetails/MovieCast/index.tsx b/src/components/MovieDetails/MovieCast/index.tsx
index 0cc9c2e0..2006e9df 100644
--- a/src/components/MovieDetails/MovieCast/index.tsx
+++ b/src/components/MovieDetails/MovieCast/index.tsx
@@ -1,20 +1,19 @@
+import Header from '@app/components/Common/Header';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import PersonCard from '@app/components/PersonCard';
+import Error from '@app/pages/_error';
+import type { MovieDetails } from '@server/models/Movie';
 import Link from 'next/link';
 import { useRouter } from 'next/router';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import { MovieDetails } from '../../../../server/models/Movie';
-import Error from '../../../pages/_error';
-import Header from '../../Common/Header';
-import LoadingSpinner from '../../Common/LoadingSpinner';
-import PageTitle from '../../Common/PageTitle';
-import PersonCard from '../../PersonCard';
 
 const messages = defineMessages({
   fullcast: 'Full Cast',
 });
 
-const MovieCast: React.FC = () => {
+const MovieCast = () => {
   const router = useRouter();
   const intl = useIntl();
   const { data, error } = useSWR<MovieDetails>(
diff --git a/src/components/MovieDetails/MovieCrew/index.tsx b/src/components/MovieDetails/MovieCrew/index.tsx
index 14268e42..1cc43b05 100644
--- a/src/components/MovieDetails/MovieCrew/index.tsx
+++ b/src/components/MovieDetails/MovieCrew/index.tsx
@@ -1,20 +1,19 @@
+import Header from '@app/components/Common/Header';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import PersonCard from '@app/components/PersonCard';
+import Error from '@app/pages/_error';
+import type { MovieDetails } from '@server/models/Movie';
 import Link from 'next/link';
 import { useRouter } from 'next/router';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import { MovieDetails } from '../../../../server/models/Movie';
-import Error from '../../../pages/_error';
-import Header from '../../Common/Header';
-import LoadingSpinner from '../../Common/LoadingSpinner';
-import PageTitle from '../../Common/PageTitle';
-import PersonCard from '../../PersonCard';
 
 const messages = defineMessages({
   fullcrew: 'Full Crew',
 });
 
-const MovieCrew: React.FC = () => {
+const MovieCrew = () => {
   const router = useRouter();
   const intl = useIntl();
   const { data, error } = useSWR<MovieDetails>(
diff --git a/src/components/MovieDetails/MovieRecommendations.tsx b/src/components/MovieDetails/MovieRecommendations.tsx
index fc9c2bf2..a7635a25 100644
--- a/src/components/MovieDetails/MovieRecommendations.tsx
+++ b/src/components/MovieDetails/MovieRecommendations.tsx
@@ -1,21 +1,20 @@
+import Header from '@app/components/Common/Header';
+import ListView from '@app/components/Common/ListView';
+import PageTitle from '@app/components/Common/PageTitle';
+import useDiscover from '@app/hooks/useDiscover';
+import Error from '@app/pages/_error';
+import type { MovieDetails } from '@server/models/Movie';
+import type { MovieResult } from '@server/models/Search';
 import Link from 'next/link';
 import { useRouter } from 'next/router';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import type { MovieDetails } from '../../../server/models/Movie';
-import type { MovieResult } from '../../../server/models/Search';
-import useDiscover from '../../hooks/useDiscover';
-import Error from '../../pages/_error';
-import Header from '../Common/Header';
-import ListView from '../Common/ListView';
-import PageTitle from '../Common/PageTitle';
 
 const messages = defineMessages({
   recommendations: 'Recommendations',
 });
 
-const MovieRecommendations: React.FC = () => {
+const MovieRecommendations = () => {
   const intl = useIntl();
   const router = useRouter();
   const { data: movieData } = useSWR<MovieDetails>(
diff --git a/src/components/MovieDetails/MovieSimilar.tsx b/src/components/MovieDetails/MovieSimilar.tsx
index 8103f966..5ce5ef1a 100644
--- a/src/components/MovieDetails/MovieSimilar.tsx
+++ b/src/components/MovieDetails/MovieSimilar.tsx
@@ -1,21 +1,20 @@
+import Header from '@app/components/Common/Header';
+import ListView from '@app/components/Common/ListView';
+import PageTitle from '@app/components/Common/PageTitle';
+import useDiscover from '@app/hooks/useDiscover';
+import Error from '@app/pages/_error';
+import type { MovieDetails } from '@server/models/Movie';
+import type { MovieResult } from '@server/models/Search';
 import Link from 'next/link';
 import { useRouter } from 'next/router';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import type { MovieDetails } from '../../../server/models/Movie';
-import type { MovieResult } from '../../../server/models/Search';
-import useDiscover from '../../hooks/useDiscover';
-import Error from '../../pages/_error';
-import Header from '../Common/Header';
-import ListView from '../Common/ListView';
-import PageTitle from '../Common/PageTitle';
 
 const messages = defineMessages({
   similar: 'Similar Titles',
 });
 
-const MovieSimilar: React.FC = () => {
+const MovieSimilar = () => {
   const router = useRouter();
   const intl = useIntl();
   const { data: movieData } = useSWR<MovieDetails>(
diff --git a/src/components/MovieDetails/index.tsx b/src/components/MovieDetails/index.tsx
index 8dd00159..88cffb21 100644
--- a/src/components/MovieDetails/index.tsx
+++ b/src/components/MovieDetails/index.tsx
@@ -1,3 +1,29 @@
+import RTAudFresh from '@app/assets/rt_aud_fresh.svg';
+import RTAudRotten from '@app/assets/rt_aud_rotten.svg';
+import RTFresh from '@app/assets/rt_fresh.svg';
+import RTRotten from '@app/assets/rt_rotten.svg';
+import TmdbLogo from '@app/assets/tmdb_logo.svg';
+import Button from '@app/components/Common/Button';
+import CachedImage from '@app/components/Common/CachedImage';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import type { PlayButtonLink } from '@app/components/Common/PlayButton';
+import PlayButton from '@app/components/Common/PlayButton';
+import Tooltip from '@app/components/Common/Tooltip';
+import ExternalLinkBlock from '@app/components/ExternalLinkBlock';
+import IssueModal from '@app/components/IssueModal';
+import ManageSlideOver from '@app/components/ManageSlideOver';
+import MediaSlider from '@app/components/MediaSlider';
+import PersonCard from '@app/components/PersonCard';
+import RequestButton from '@app/components/RequestButton';
+import Slider from '@app/components/Slider';
+import StatusBadge from '@app/components/StatusBadge';
+import useLocale from '@app/hooks/useLocale';
+import useSettings from '@app/hooks/useSettings';
+import { Permission, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import Error from '@app/pages/_error';
+import { sortCrewPriority } from '@app/utils/creditHelpers';
 import {
   ArrowCircleRightIcon,
   CloudIcon,
@@ -11,42 +37,18 @@ import {
   ChevronDoubleDownIcon,
   ChevronDoubleUpIcon,
 } from '@heroicons/react/solid';
+import type { RTRating } from '@server/api/rottentomatoes';
+import { IssueStatus } from '@server/constants/issue';
+import { MediaStatus } from '@server/constants/media';
+import type { MovieDetails as MovieDetailsType } from '@server/models/Movie';
 import { hasFlag } from 'country-flag-icons';
 import 'country-flag-icons/3x2/flags.css';
 import { uniqBy } from 'lodash';
 import Link from 'next/link';
 import { useRouter } from 'next/router';
-import React, { useEffect, useMemo, useState } from 'react';
+import { useEffect, useMemo, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import type { RTRating } from '../../../server/api/rottentomatoes';
-import { IssueStatus } from '../../../server/constants/issue';
-import { MediaStatus } from '../../../server/constants/media';
-import type { MovieDetails as MovieDetailsType } from '../../../server/models/Movie';
-import RTAudFresh from '../../assets/rt_aud_fresh.svg';
-import RTAudRotten from '../../assets/rt_aud_rotten.svg';
-import RTFresh from '../../assets/rt_fresh.svg';
-import RTRotten from '../../assets/rt_rotten.svg';
-import TmdbLogo from '../../assets/tmdb_logo.svg';
-import useLocale from '../../hooks/useLocale';
-import useSettings from '../../hooks/useSettings';
-import { Permission, useUser } from '../../hooks/useUser';
-import globalMessages from '../../i18n/globalMessages';
-import Error from '../../pages/_error';
-import { sortCrewPriority } from '../../utils/creditHelpers';
-import Button from '../Common/Button';
-import CachedImage from '../Common/CachedImage';
-import LoadingSpinner from '../Common/LoadingSpinner';
-import PageTitle from '../Common/PageTitle';
-import PlayButton, { PlayButtonLink } from '../Common/PlayButton';
-import ExternalLinkBlock from '../ExternalLinkBlock';
-import IssueModal from '../IssueModal';
-import ManageSlideOver from '../ManageSlideOver';
-import MediaSlider from '../MediaSlider';
-import PersonCard from '../PersonCard';
-import RequestButton from '../RequestButton';
-import Slider from '../Slider';
-import StatusBadge from '../StatusBadge';
 
 const messages = defineMessages({
   originaltitle: 'Original Title',
@@ -73,13 +75,21 @@ const messages = defineMessages({
   streamingproviders: 'Currently Streaming On',
   productioncountries:
     'Production {countryCount, plural, one {Country} other {Countries}}',
+  theatricalrelease: 'Theatrical Release',
+  digitalrelease: 'Digital Release',
+  physicalrelease: 'Physical Release',
+  reportissue: 'Report an Issue',
+  managemovie: 'Manage Movie',
+  rtcriticsscore: 'Rotten Tomatoes Tomatometer',
+  rtaudiencescore: 'Rotten Tomatoes Audience Score',
+  tmdbuserscore: 'TMDB User Score',
 });
 
 interface MovieDetailsProps {
   movie?: MovieDetailsType;
 }
 
-const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
+const MovieDetails = ({ movie }: MovieDetailsProps) => {
   const settings = useSettings();
   const { user, hasPermission } = useUser();
   const router = useRouter();
@@ -113,6 +123,30 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
     setShowManager(router.query.manage == '1' ? true : false);
   }, [router.query.manage]);
 
+  const [plexUrl, setPlexUrl] = useState(data?.mediaInfo?.plexUrl);
+  const [plexUrl4k, setPlexUrl4k] = useState(data?.mediaInfo?.plexUrl4k);
+
+  useEffect(() => {
+    if (data) {
+      if (
+        /iPad|iPhone|iPod/.test(navigator.userAgent) ||
+        (navigator.userAgent === 'MacIntel' && navigator.maxTouchPoints > 1)
+      ) {
+        setPlexUrl(data.mediaInfo?.iOSPlexUrl);
+        setPlexUrl4k(data.mediaInfo?.iOSPlexUrl4k);
+      } else {
+        setPlexUrl(data.mediaInfo?.plexUrl);
+        setPlexUrl4k(data.mediaInfo?.plexUrl4k);
+      }
+    }
+  }, [
+    data,
+    data?.mediaInfo?.iOSPlexUrl,
+    data?.mediaInfo?.iOSPlexUrl4k,
+    data?.mediaInfo?.plexUrl,
+    data?.mediaInfo?.plexUrl4k,
+  ]);
+
   if (!data && !error) {
     return <LoadingSpinner />;
   }
@@ -125,32 +159,31 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
   const mediaLinks: PlayButtonLink[] = [];
 
   if (
-    data.mediaInfo?.plexUrl &&
+    plexUrl &&
     hasPermission([Permission.REQUEST, Permission.REQUEST_MOVIE], {
       type: 'or',
     })
   ) {
     mediaLinks.push({
       text: intl.formatMessage(messages.playonplex),
-      url: data.mediaInfo?.plexUrl,
+      url: plexUrl,
       svg: <PlayIcon />,
     });
   }
 
   if (
     settings.currentSettings.movie4kEnabled &&
-    data.mediaInfo?.plexUrl4k &&
+    plexUrl4k &&
     hasPermission([Permission.REQUEST_4K, Permission.REQUEST_4K_MOVIE], {
       type: 'or',
     })
   ) {
     mediaLinks.push({
       text: intl.formatMessage(messages.play4konplex),
-      url: data.mediaInfo?.plexUrl4k,
+      url: plexUrl4k,
       svg: <PlayIcon />,
     });
   }
-
   const trailerUrl = data.relatedVideos
     ?.filter((r) => r.type === 'Trailer')
     .sort((a, b) => a.size - b.size)
@@ -292,6 +325,7 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
               tmdbId={data.mediaInfo?.tmdbId}
               mediaType="movie"
               plexUrl={data.mediaInfo?.plexUrl}
+              serviceUrl={data.mediaInfo?.serviceUrl}
             />
             {settings.currentSettings.movie4kEnabled &&
               hasPermission(
@@ -313,10 +347,11 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
                   tmdbId={data.mediaInfo?.tmdbId}
                   mediaType="movie"
                   plexUrl={data.mediaInfo?.plexUrl4k}
+                  serviceUrl={data.mediaInfo?.serviceUrl4k}
                 />
               )}
           </div>
-          <h1>
+          <h1 data-testid="media-title">
             {data.title}{' '}
             {data.releaseDate && (
               <span className="media-year">
@@ -360,38 +395,42 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
                 type: 'or',
               }
             ) && (
+              <Tooltip content={intl.formatMessage(messages.reportissue)}>
+                <Button
+                  buttonType="warning"
+                  onClick={() => setShowIssueModal(true)}
+                  className="ml-2 first:ml-0"
+                >
+                  <ExclamationIcon />
+                </Button>
+              </Tooltip>
+            )}
+          {hasPermission(Permission.MANAGE_REQUESTS) && data.mediaInfo && (
+            <Tooltip content={intl.formatMessage(messages.managemovie)}>
               <Button
-                buttonType="warning"
-                className="ml-2 first:ml-0"
-                onClick={() => setShowIssueModal(true)}
+                buttonType="ghost"
+                onClick={() => setShowManager(true)}
+                className="relative ml-2 first:ml-0"
               >
-                <ExclamationIcon />
+                <CogIcon className="!mr-0" />
+                {hasPermission(
+                  [Permission.MANAGE_ISSUES, Permission.VIEW_ISSUES],
+                  {
+                    type: 'or',
+                  }
+                ) &&
+                  (
+                    data.mediaInfo?.issues.filter(
+                      (issue) => issue.status === IssueStatus.OPEN
+                    ) ?? []
+                  ).length > 0 && (
+                    <>
+                      <div className="absolute -right-1 -top-1 h-3 w-3 rounded-full bg-red-600" />
+                      <div className="absolute -right-1 -top-1 h-3 w-3 animate-ping rounded-full bg-red-600" />
+                    </>
+                  )}
               </Button>
-            )}
-          {hasPermission(Permission.MANAGE_REQUESTS) && data.mediaInfo && (
-            <Button
-              buttonType="default"
-              className="relative ml-2 first:ml-0"
-              onClick={() => setShowManager(true)}
-            >
-              <CogIcon className="!mr-0" />
-              {hasPermission(
-                [Permission.MANAGE_ISSUES, Permission.VIEW_ISSUES],
-                {
-                  type: 'or',
-                }
-              ) &&
-                (
-                  data.mediaInfo?.issues.filter(
-                    (issue) => issue.status === IssueStatus.OPEN
-                  ) ?? []
-                ).length > 0 && (
-                  <>
-                    <div className="absolute -right-1 -top-1 h-3 w-3 rounded-full bg-red-600" />
-                    <div className="absolute -right-1 -top-1 h-3 w-3 animate-ping rounded-full bg-red-600" />
-                  </>
-                )}
-            </Button>
+            </Tooltip>
           )}
         </div>
       </div>
@@ -465,36 +504,55 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
               (ratingData?.audienceRating && !!ratingData?.audienceScore)) && (
               <div className="media-ratings">
                 {ratingData?.criticsRating && !!ratingData?.criticsScore && (
-                  <>
-                    <span className="media-rating">
+                  <Tooltip
+                    content={intl.formatMessage(messages.rtcriticsscore)}
+                  >
+                    <a
+                      href={ratingData.url}
+                      className="media-rating"
+                      target="_blank"
+                      rel="noreferrer"
+                    >
                       {ratingData.criticsRating === 'Rotten' ? (
-                        <RTRotten className="mr-1 w-6" />
+                        <RTRotten className="w-6" />
                       ) : (
-                        <RTFresh className="mr-1 w-6" />
+                        <RTFresh className="w-6" />
                       )}
-                      {ratingData.criticsScore}%
-                    </span>
-                  </>
+                      <span>{ratingData.criticsScore}%</span>
+                    </a>
+                  </Tooltip>
                 )}
                 {ratingData?.audienceRating && !!ratingData?.audienceScore && (
-                  <>
-                    <span className="media-rating">
+                  <Tooltip
+                    content={intl.formatMessage(messages.rtaudiencescore)}
+                  >
+                    <a
+                      href={ratingData.url}
+                      className="media-rating"
+                      target="_blank"
+                      rel="noreferrer"
+                    >
                       {ratingData.audienceRating === 'Spilled' ? (
-                        <RTAudRotten className="mr-1 w-6" />
+                        <RTAudRotten className="w-6" />
                       ) : (
-                        <RTAudFresh className="mr-1 w-6" />
+                        <RTAudFresh className="w-6" />
                       )}
-                      {ratingData.audienceScore}%
-                    </span>
-                  </>
+                      <span>{ratingData.audienceScore}%</span>
+                    </a>
+                  </Tooltip>
                 )}
                 {!!data.voteCount && (
-                  <>
-                    <span className="media-rating">
-                      <TmdbLogo className="mr-2 w-6" />
-                      {data.voteAverage}/10
-                    </span>
-                  </>
+                  <Tooltip content={intl.formatMessage(messages.tmdbuserscore)}>
+                    <a
+                      href={`https://www.themoviedb.org/movie/${data.id}?language=${locale}`}
+                      className="media-rating"
+                      target="_blank"
+                      rel="noreferrer"
+                    >
+                      <TmdbLogo className="mr-1 w-6" />
+                      <span>{Math.round(data.voteAverage * 10)}%</span>
+                    </a>
+                  </Tooltip>
                 )}
               </div>
             )}
@@ -524,22 +582,36 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
                     >
                       {r.type === 3 ? (
                         // Theatrical
-                        <TicketIcon className="h-4 w-4" />
+                        <Tooltip
+                          content={intl.formatMessage(
+                            messages.theatricalrelease
+                          )}
+                        >
+                          <TicketIcon className="h-4 w-4" />
+                        </Tooltip>
                       ) : r.type === 4 ? (
                         // Digital
-                        <CloudIcon className="h-4 w-4" />
+                        <Tooltip
+                          content={intl.formatMessage(messages.digitalrelease)}
+                        >
+                          <CloudIcon className="h-4 w-4" />
+                        </Tooltip>
                       ) : (
                         // Physical
-                        <svg
-                          className="h-4 w-4"
-                          viewBox="0 0 24 24"
-                          xmlns="http://www.w3.org/2000/svg"
+                        <Tooltip
+                          content={intl.formatMessage(messages.physicalrelease)}
                         >
-                          <path
-                            d="m12 2c-5.5242 0-10 4.4758-10 10 0 5.5242 4.4758 10 10 10 5.5242 0 10-4.4758 10-10 0-5.5242-4.4758-10-10-10zm0 18.065c-4.4476 0-8.0645-3.6169-8.0645-8.0645 0-4.4476 3.6169-8.0645 8.0645-8.0645 4.4476 0 8.0645 3.6169 8.0645 8.0645 0 4.4476-3.6169 8.0645-8.0645 8.0645zm0-14.516c-3.5565 0-6.4516 2.8952-6.4516 6.4516h1.2903c0-2.8468 2.3145-5.1613 5.1613-5.1613zm0 2.9032c-1.9597 0-3.5484 1.5887-3.5484 3.5484s1.5887 3.5484 3.5484 3.5484 3.5484-1.5887 3.5484-3.5484-1.5887-3.5484-3.5484-3.5484zm0 4.8387c-0.71371 0-1.2903-0.57661-1.2903-1.2903s0.57661-1.2903 1.2903-1.2903 1.2903 0.57661 1.2903 1.2903-0.57661 1.2903-1.2903 1.2903z"
-                            fill="currentColor"
-                          />
-                        </svg>
+                          <svg
+                            className="h-4 w-4"
+                            viewBox="0 0 24 24"
+                            xmlns="http://www.w3.org/2000/svg"
+                          >
+                            <path
+                              d="m12 2c-5.5242 0-10 4.4758-10 10 0 5.5242 4.4758 10 10 10 5.5242 0 10-4.4758 10-10 0-5.5242-4.4758-10-10-10zm0 18.065c-4.4476 0-8.0645-3.6169-8.0645-8.0645 0-4.4476 3.6169-8.0645 8.0645-8.0645 4.4476 0 8.0645 3.6169 8.0645 8.0645 0 4.4476-3.6169 8.0645-8.0645 8.0645zm0-14.516c-3.5565 0-6.4516 2.8952-6.4516 6.4516h1.2903c0-2.8468 2.3145-5.1613 5.1613-5.1613zm0 2.9032c-1.9597 0-3.5484 1.5887-3.5484 3.5484s1.5887 3.5484 3.5484 3.5484 3.5484-1.5887 3.5484-3.5484-1.5887-3.5484-3.5484-3.5484zm0 4.8387c-0.71371 0-1.2903-0.57661-1.2903-1.2903s0.57661-1.2903 1.2903-1.2903 1.2903 0.57661 1.2903 1.2903-0.57661 1.2903-1.2903 1.2903z"
+                              fill="currentColor"
+                            />
+                          </svg>
+                        </Tooltip>
                       )}
                       <span className="ml-1.5">
                         {intl.formatDate(r.release_date, {
diff --git a/src/components/NotificationTypeSelector/NotificationType/index.tsx b/src/components/NotificationTypeSelector/NotificationType/index.tsx
index 9662ebd3..f0e6cb05 100644
--- a/src/components/NotificationTypeSelector/NotificationType/index.tsx
+++ b/src/components/NotificationTypeSelector/NotificationType/index.tsx
@@ -1,5 +1,5 @@
-import React from 'react';
-import { hasNotificationType, NotificationItem } from '..';
+import type { NotificationItem } from '@app/components/NotificationTypeSelector';
+import { hasNotificationType } from '@app/components/NotificationTypeSelector';
 
 interface NotificationTypeProps {
   option: NotificationItem;
@@ -8,12 +8,12 @@ interface NotificationTypeProps {
   onUpdate: (newTypes: number) => void;
 }
 
-const NotificationType: React.FC<NotificationTypeProps> = ({
+const NotificationType = ({
   option,
   currentTypes,
   onUpdate,
   parent,
-}) => {
+}: NotificationTypeProps) => {
   return (
     <>
       <div
diff --git a/src/components/NotificationTypeSelector/index.tsx b/src/components/NotificationTypeSelector/index.tsx
index 70b003ae..149c2757 100644
--- a/src/components/NotificationTypeSelector/index.tsx
+++ b/src/components/NotificationTypeSelector/index.tsx
@@ -1,9 +1,10 @@
+import NotificationType from '@app/components/NotificationTypeSelector/NotificationType';
+import useSettings from '@app/hooks/useSettings';
+import type { User } from '@app/hooks/useUser';
+import { Permission, useUser } from '@app/hooks/useUser';
 import { sortBy } from 'lodash';
-import React, { useMemo, useState } from 'react';
+import { useMemo, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
-import useSettings from '../../hooks/useSettings';
-import { Permission, User, useUser } from '../../hooks/useUser';
-import NotificationType from './NotificationType';
 
 const messages = defineMessages({
   notificationTypes: 'Notification Types',
@@ -59,6 +60,9 @@ const messages = defineMessages({
     'Get notified when issues you reported are reopened.',
   adminissuereopenedDescription:
     'Get notified when issues are reopened by other users.',
+  mediaautorequested: 'Request Automatically Submitted',
+  mediaautorequestedDescription:
+    'Get notified when new media requests are automatically submitted for items on your Plex Watchlist.',
 });
 
 export const hasNotificationType = (
@@ -100,6 +104,7 @@ export enum Notification {
   ISSUE_COMMENT = 512,
   ISSUE_RESOLVED = 1024,
   ISSUE_REOPENED = 2048,
+  MEDIA_AUTO_REQUESTED = 4096,
 }
 
 export const ALL_NOTIFICATIONS = Object.values(Notification)
@@ -124,13 +129,13 @@ interface NotificationTypeSelectorProps {
   error?: string;
 }
 
-const NotificationTypeSelector: React.FC<NotificationTypeSelectorProps> = ({
+const NotificationTypeSelector = ({
   user,
   enabledTypes = ALL_NOTIFICATIONS,
   currentTypes,
   onUpdate,
   error,
-}) => {
+}: NotificationTypeSelectorProps) => {
   const intl = useIntl();
   const settings = useSettings();
   const { hasPermission } = useUser({ id: user?.id });
@@ -190,6 +195,25 @@ const NotificationTypeSelector: React.FC<NotificationTypeSelectorProps> = ({
             ))));
 
     const types: NotificationItem[] = [
+      {
+        id: 'media-auto-requested',
+        name: intl.formatMessage(messages.mediaautorequested),
+        description: intl.formatMessage(messages.mediaautorequestedDescription),
+        value: Notification.MEDIA_AUTO_REQUESTED,
+        hidden:
+          !user ||
+          (!user.settings?.watchlistSyncMovies &&
+            !user.settings?.watchlistSyncTv) ||
+          !hasPermission(
+            [
+              Permission.AUTO_REQUEST,
+              Permission.AUTO_REQUEST_MOVIE,
+              Permission.AUTO_REQUEST_TV,
+            ],
+            { type: 'or' }
+          ),
+        hasNotifyUser: true,
+      },
       {
         id: 'media-requested',
         name: intl.formatMessage(messages.mediarequested),
diff --git a/src/components/PWAHeader/index.tsx b/src/components/PWAHeader/index.tsx
index 1c53abfb..0dde7e42 100644
--- a/src/components/PWAHeader/index.tsx
+++ b/src/components/PWAHeader/index.tsx
@@ -1,12 +1,8 @@
-import React from 'react';
-
 interface PWAHeaderProps {
   applicationTitle?: string;
 }
 
-const PWAHeader: React.FC<PWAHeaderProps> = ({
-  applicationTitle = 'Overseerr',
-}) => {
+const PWAHeader = ({ applicationTitle = 'Overseerr' }: PWAHeaderProps) => {
   return (
     <>
       <link
diff --git a/src/components/PermissionEdit/index.tsx b/src/components/PermissionEdit/index.tsx
index 504e615d..768b9281 100644
--- a/src/components/PermissionEdit/index.tsx
+++ b/src/components/PermissionEdit/index.tsx
@@ -1,7 +1,8 @@
-import React from 'react';
+import type { PermissionItem } from '@app/components/PermissionOption';
+import PermissionOption from '@app/components/PermissionOption';
+import type { User } from '@app/hooks/useUser';
+import { Permission } from '@app/hooks/useUser';
 import { defineMessages, useIntl } from 'react-intl';
-import { Permission, User } from '../../hooks/useUser';
-import PermissionOption, { PermissionItem } from '../PermissionOption';
 
 export const messages = defineMessages({
   admin: 'Admin',
@@ -10,9 +11,6 @@ export const messages = defineMessages({
   users: 'Manage Users',
   usersDescription:
     'Grant permission to manage users. Users with this permission cannot modify users with or grant the Admin privilege.',
-  settings: 'Manage Settings',
-  settingsDescription:
-    'Grant permission to modify global settings. A user must have this permission to grant it to others.',
   managerequests: 'Manage Requests',
   managerequestsDescription:
     'Grant permission to manage media requests. All requests made by a user with this permission will be automatically approved.',
@@ -52,6 +50,15 @@ export const messages = defineMessages({
   advancedrequest: 'Advanced Requests',
   advancedrequestDescription:
     'Grant permission to modify advanced media request options.',
+  autorequest: 'Auto-Request',
+  autorequestDescription:
+    'Grant permission to automatically submit requests for non-4K media via Plex Watchlist.',
+  autorequestMovies: 'Auto-Request Movies',
+  autorequestMoviesDescription:
+    'Grant permission to automatically submit requests for non-4K movies via Plex Watchlist.',
+  autorequestSeries: 'Auto-Request Series',
+  autorequestSeriesDescription:
+    'Grant permission to automatically submit requests for non-4K series via Plex Watchlist.',
   viewrequests: 'View Requests',
   viewrequestsDescription:
     'Grant permission to view media requests submitted by other users.',
@@ -62,6 +69,12 @@ export const messages = defineMessages({
   viewissues: 'View Issues',
   viewissuesDescription:
     'Grant permission to view media issues reported by other users.',
+  viewrecent: 'View Recently Added',
+  viewrecentDescription:
+    'Grant permission to view the list of recently added media.',
+  viewwatchlists: 'View Plex Watchlists',
+  viewwatchlistsDescription:
+    "Grant permission to view other users' Plex Watchlists.",
 });
 
 interface PermissionEditProps {
@@ -71,12 +84,12 @@ interface PermissionEditProps {
   onUpdate: (newPermissions: number) => void;
 }
 
-export const PermissionEdit: React.FC<PermissionEditProps> = ({
+export const PermissionEdit = ({
   actingUser,
   currentUser,
   currentPermission,
   onUpdate,
-}) => {
+}: PermissionEditProps) => {
   const intl = useIntl();
 
   const permissionList: PermissionItem[] = [
@@ -86,12 +99,6 @@ export const PermissionEdit: React.FC<PermissionEditProps> = ({
       description: intl.formatMessage(messages.adminDescription),
       permission: Permission.ADMIN,
     },
-    {
-      id: 'settings',
-      name: intl.formatMessage(messages.settings),
-      description: intl.formatMessage(messages.settingsDescription),
-      permission: Permission.MANAGE_SETTINGS,
-    },
     {
       id: 'users',
       name: intl.formatMessage(messages.users),
@@ -116,6 +123,18 @@ export const PermissionEdit: React.FC<PermissionEditProps> = ({
           description: intl.formatMessage(messages.viewrequestsDescription),
           permission: Permission.REQUEST_VIEW,
         },
+        {
+          id: 'viewrecent',
+          name: intl.formatMessage(messages.viewrecent),
+          description: intl.formatMessage(messages.viewrecentDescription),
+          permission: Permission.RECENT_VIEW,
+        },
+        {
+          id: 'viewwatchlists',
+          name: intl.formatMessage(messages.viewwatchlists),
+          description: intl.formatMessage(messages.viewwatchlistsDescription),
+          permission: Permission.WATCHLIST_VIEW,
+        },
       ],
     },
     {
@@ -175,6 +194,43 @@ export const PermissionEdit: React.FC<PermissionEditProps> = ({
         },
       ],
     },
+    {
+      id: 'autorequest',
+      name: intl.formatMessage(messages.autorequest),
+      description: intl.formatMessage(messages.autorequestDescription),
+      permission: Permission.AUTO_REQUEST,
+      requires: [{ permissions: [Permission.REQUEST] }],
+      children: [
+        {
+          id: 'autorequestmovies',
+          name: intl.formatMessage(messages.autorequestMovies),
+          description: intl.formatMessage(
+            messages.autorequestMoviesDescription
+          ),
+          permission: Permission.AUTO_REQUEST_MOVIE,
+          requires: [
+            {
+              permissions: [Permission.REQUEST, Permission.REQUEST_MOVIE],
+              type: 'or',
+            },
+          ],
+        },
+        {
+          id: 'autorequesttv',
+          name: intl.formatMessage(messages.autorequestSeries),
+          description: intl.formatMessage(
+            messages.autorequestSeriesDescription
+          ),
+          permission: Permission.AUTO_REQUEST_TV,
+          requires: [
+            {
+              permissions: [Permission.REQUEST, Permission.REQUEST_TV],
+              type: 'or',
+            },
+          ],
+        },
+      ],
+    },
     {
       id: 'request4k',
       name: intl.formatMessage(messages.request4k),
diff --git a/src/components/PermissionOption/index.tsx b/src/components/PermissionOption/index.tsx
index 73923475..43d5128d 100644
--- a/src/components/PermissionOption/index.tsx
+++ b/src/components/PermissionOption/index.tsx
@@ -1,7 +1,7 @@
-import React from 'react';
-import { hasPermission } from '../../../server/lib/permissions';
-import useSettings from '../../hooks/useSettings';
-import { Permission, User } from '../../hooks/useUser';
+import useSettings from '@app/hooks/useSettings';
+import type { User } from '@app/hooks/useUser';
+import { Permission } from '@app/hooks/useUser';
+import { hasPermission } from '@server/lib/permissions';
 
 export interface PermissionItem {
   id: string;
@@ -26,14 +26,14 @@ interface PermissionOptionProps {
   onUpdate: (newPermissions: number) => void;
 }
 
-const PermissionOption: React.FC<PermissionOptionProps> = ({
+const PermissionOption = ({
   option,
   actingUser,
   currentUser,
   currentPermission,
   onUpdate,
   parent,
-}) => {
+}: PermissionOptionProps) => {
   const settings = useSettings();
 
   const autoApprovePermissions = [
@@ -66,14 +66,9 @@ const PermissionOption: React.FC<PermissionOptionProps> = ({
   }
 
   if (
-    // Non-Admin users cannot modify the Admin permission
-    (actingUser &&
-      !hasPermission(Permission.ADMIN, actingUser.permissions) &&
-      option.permission === Permission.ADMIN) ||
-    // Users without the Manage Settings permission cannot modify/grant that permission
-    (actingUser &&
-      !hasPermission(Permission.MANAGE_SETTINGS, actingUser.permissions) &&
-      option.permission === Permission.MANAGE_SETTINGS)
+    // Only the owner can modify the Admin permission
+    actingUser?.id !== 1 &&
+    option.permission === Permission.ADMIN
   ) {
     disabled = true;
   }
diff --git a/src/components/PersonCard/index.tsx b/src/components/PersonCard/index.tsx
index 47fe56ef..c2b7b642 100644
--- a/src/components/PersonCard/index.tsx
+++ b/src/components/PersonCard/index.tsx
@@ -1,7 +1,7 @@
+import CachedImage from '@app/components/Common/CachedImage';
 import { UserCircleIcon } from '@heroicons/react/solid';
 import Link from 'next/link';
-import React, { useState } from 'react';
-import CachedImage from '../Common/CachedImage';
+import { useState } from 'react';
 
 interface PersonCardProps {
   personId: number;
@@ -11,13 +11,13 @@ interface PersonCardProps {
   canExpand?: boolean;
 }
 
-const PersonCard: React.FC<PersonCardProps> = ({
+const PersonCard = ({
   personId,
   name,
   subName,
   profilePath,
   canExpand = false,
-}) => {
+}: PersonCardProps) => {
   const [isHovered, setHovered] = useState(false);
 
   return (
diff --git a/src/components/PersonDetails/index.tsx b/src/components/PersonDetails/index.tsx
index 173fc5da..9c8173ad 100644
--- a/src/components/PersonDetails/index.tsx
+++ b/src/components/PersonDetails/index.tsx
@@ -1,19 +1,19 @@
+import Ellipsis from '@app/assets/ellipsis.svg';
+import CachedImage from '@app/components/Common/CachedImage';
+import ImageFader from '@app/components/Common/ImageFader';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import TitleCard from '@app/components/TitleCard';
+import globalMessages from '@app/i18n/globalMessages';
+import Error from '@app/pages/_error';
+import type { PersonCombinedCreditsResponse } from '@server/interfaces/api/personInterfaces';
+import type { PersonDetails as PersonDetailsType } from '@server/models/Person';
 import { groupBy } from 'lodash';
 import { useRouter } from 'next/router';
-import React, { useMemo, useState } from 'react';
+import { useMemo, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import TruncateMarkup from 'react-truncate-markup';
 import useSWR from 'swr';
-import type { PersonCombinedCreditsResponse } from '../../../server/interfaces/api/personInterfaces';
-import type { PersonDetails as PersonDetailsType } from '../../../server/models/Person';
-import Ellipsis from '../../assets/ellipsis.svg';
-import globalMessages from '../../i18n/globalMessages';
-import Error from '../../pages/_error';
-import CachedImage from '../Common/CachedImage';
-import ImageFader from '../Common/ImageFader';
-import LoadingSpinner from '../Common/LoadingSpinner';
-import PageTitle from '../Common/PageTitle';
-import TitleCard from '../TitleCard';
 
 const messages = defineMessages({
   birthdate: 'Born {birthdate}',
@@ -24,7 +24,7 @@ const messages = defineMessages({
   ascharacter: 'as {character}',
 });
 
-const PersonDetails: React.FC = () => {
+const PersonDetails = () => {
   const intl = useIntl();
   const router = useRouter();
   const { data, error } = useSWR<PersonDetailsType>(
diff --git a/src/components/PlexLoginButton/index.tsx b/src/components/PlexLoginButton/index.tsx
index 55093871..c89f1021 100644
--- a/src/components/PlexLoginButton/index.tsx
+++ b/src/components/PlexLoginButton/index.tsx
@@ -1,8 +1,8 @@
+import globalMessages from '@app/i18n/globalMessages';
+import PlexOAuth from '@app/utils/plex';
 import { LoginIcon } from '@heroicons/react/outline';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
-import globalMessages from '../../i18n/globalMessages';
-import PlexOAuth from '../../utils/plex';
 
 const messages = defineMessages({
   signinwithplex: 'Sign In',
@@ -17,11 +17,11 @@ interface PlexLoginButtonProps {
   onError?: (message: string) => void;
 }
 
-const PlexLoginButton: React.FC<PlexLoginButtonProps> = ({
+const PlexLoginButton = ({
   onAuthToken,
   onError,
   isProcessing,
-}) => {
+}: PlexLoginButtonProps) => {
   const intl = useIntl();
   const [loading, setLoading] = useState(false);
 
diff --git a/src/components/PullToRefresh/index.tsx b/src/components/PullToRefresh/index.tsx
new file mode 100644
index 00000000..ce92ea60
--- /dev/null
+++ b/src/components/PullToRefresh/index.tsx
@@ -0,0 +1,40 @@
+import { RefreshIcon } from '@heroicons/react/outline';
+import Router from 'next/router';
+import PR from 'pulltorefreshjs';
+import { useEffect } from 'react';
+import ReactDOMServer from 'react-dom/server';
+
+const PullToRefresh: React.FC = () => {
+  useEffect(() => {
+    PR.init({
+      mainElement: '#pull-to-refresh',
+      onRefresh() {
+        Router.reload();
+      },
+      iconArrow: ReactDOMServer.renderToString(
+        <div className="p-2">
+          <RefreshIcon className="z-50 m-auto h-9 w-9 rounded-full border-4 border-gray-800 bg-gray-800 text-indigo-500 ring-1 ring-gray-700" />
+        </div>
+      ),
+      iconRefreshing: ReactDOMServer.renderToString(
+        <div
+          className="animate-spin p-2"
+          style={{ animationDirection: 'reverse' }}
+        >
+          <RefreshIcon className="z-50 m-auto h-9 w-9 rounded-full border-4 border-gray-800 bg-gray-800 text-indigo-500 ring-1 ring-gray-700" />
+        </div>
+      ),
+      instructionsPullToRefresh: ReactDOMServer.renderToString(<div />),
+      instructionsReleaseToRefresh: ReactDOMServer.renderToString(<div />),
+      instructionsRefreshing: ReactDOMServer.renderToString(<div />),
+      distReload: 60,
+    });
+    return () => {
+      PR.destroyAll();
+    };
+  }, []);
+
+  return <div id="pull-to-refresh"></div>;
+};
+
+export default PullToRefresh;
diff --git a/src/components/QuotaSelector/index.tsx b/src/components/QuotaSelector/index.tsx
index 9ad39e22..7240dbc2 100644
--- a/src/components/QuotaSelector/index.tsx
+++ b/src/components/QuotaSelector/index.tsx
@@ -24,7 +24,7 @@ interface QuotaSelectorProps {
   onChange: (fieldName: string, value: number) => void;
 }
 
-const QuotaSelector: React.FC<QuotaSelectorProps> = ({
+const QuotaSelector = ({
   mediaType,
   dayFieldName,
   limitFieldName,
@@ -34,7 +34,7 @@ const QuotaSelector: React.FC<QuotaSelectorProps> = ({
   limitOverride,
   isDisabled = false,
   onChange,
-}) => {
+}: QuotaSelectorProps) => {
   const initialDays = defaultDays ?? 7;
   const initialLimit = defaultLimit ?? 0;
   const [quotaDays, setQuotaDays] = useState(initialDays);
diff --git a/src/components/RegionSelector/index.tsx b/src/components/RegionSelector/index.tsx
index 0c4bb2c6..5a714c74 100644
--- a/src/components/RegionSelector/index.tsx
+++ b/src/components/RegionSelector/index.tsx
@@ -1,13 +1,13 @@
+import useSettings from '@app/hooks/useSettings';
 import { Listbox, Transition } from '@headlessui/react';
 import { CheckIcon, ChevronDownIcon } from '@heroicons/react/solid';
+import type { Region } from '@server/lib/settings';
 import { hasFlag } from 'country-flag-icons';
 import 'country-flag-icons/3x2/flags.css';
 import { sortBy } from 'lodash';
-import React, { useEffect, useMemo, useState } from 'react';
+import { useEffect, useMemo, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import type { Region } from '../../../server/lib/settings';
-import useSettings from '../../hooks/useSettings';
 
 const messages = defineMessages({
   regionDefault: 'All Regions',
@@ -21,12 +21,12 @@ interface RegionSelectorProps {
   onChange?: (fieldName: string, region: string) => void;
 }
 
-const RegionSelector: React.FC<RegionSelectorProps> = ({
+const RegionSelector = ({
   name,
   value,
   isUserSetting = false,
   onChange,
-}) => {
+}: RegionSelectorProps) => {
   const { currentSettings } = useSettings();
   const intl = useIntl();
   const { data: regions } = useSWR<Region[]>('/api/v1/regions');
diff --git a/src/components/RequestBlock/index.tsx b/src/components/RequestBlock/index.tsx
index 073ffaeb..e6a0c02b 100644
--- a/src/components/RequestBlock/index.tsx
+++ b/src/components/RequestBlock/index.tsx
@@ -1,3 +1,10 @@
+import Badge from '@app/components/Common/Badge';
+import Button from '@app/components/Common/Button';
+import Tooltip from '@app/components/Common/Tooltip';
+import RequestModal from '@app/components/RequestModal';
+import useRequestOverride from '@app/hooks/useRequestOverride';
+import { useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
 import {
   CalendarIcon,
   CheckIcon,
@@ -7,18 +14,12 @@ import {
   UserIcon,
   XIcon,
 } from '@heroicons/react/solid';
+import { MediaRequestStatus } from '@server/constants/media';
+import type { MediaRequest } from '@server/entity/MediaRequest';
 import axios from 'axios';
 import Link from 'next/link';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
-import { MediaRequestStatus } from '../../../server/constants/media';
-import type { MediaRequest } from '../../../server/entity/MediaRequest';
-import useRequestOverride from '../../hooks/useRequestOverride';
-import { useUser } from '../../hooks/useUser';
-import globalMessages from '../../i18n/globalMessages';
-import Badge from '../Common/Badge';
-import Button from '../Common/Button';
-import RequestModal from '../RequestModal';
 
 const messages = defineMessages({
   seasons: '{seasonCount, plural, one {Season} other {Seasons}}',
@@ -26,6 +27,14 @@ const messages = defineMessages({
   server: 'Destination Server',
   profilechanged: 'Quality Profile',
   rootfolder: 'Root Folder',
+  languageprofile: 'Language Profile',
+  requestdate: 'Request Date',
+  requestedby: 'Requested By',
+  lastmodifiedby: 'Last Modified By',
+  approve: 'Approve Request',
+  decline: 'Decline Request',
+  edit: 'Edit Request',
+  delete: 'Delete Request',
 });
 
 interface RequestBlockProps {
@@ -33,12 +42,13 @@ interface RequestBlockProps {
   onUpdate?: () => void;
 }
 
-const RequestBlock: React.FC<RequestBlockProps> = ({ request, onUpdate }) => {
+const RequestBlock = ({ request, onUpdate }: RequestBlockProps) => {
   const { user } = useUser();
   const intl = useIntl();
   const [isUpdating, setIsUpdating] = useState(false);
   const [showEditModal, setShowEditModal] = useState(false);
-  const { profile, rootFolder, server } = useRequestOverride(request);
+  const { profile, rootFolder, server, languageProfile } =
+    useRequestOverride(request);
 
   const updateRequest = async (type: 'approve' | 'decline'): Promise<void> => {
     setIsUpdating(true);
@@ -81,7 +91,9 @@ const RequestBlock: React.FC<RequestBlockProps> = ({ request, onUpdate }) => {
         <div className="flex items-center justify-between">
           <div className="mr-6 min-w-0 flex-1 flex-col items-center text-sm leading-5">
             <div className="white mb-1 flex flex-nowrap">
-              <UserIcon className="mr-1.5 h-5 w-5 min-w-0 flex-shrink-0" />
+              <Tooltip content={intl.formatMessage(messages.requestedby)}>
+                <UserIcon className="mr-1.5 h-5 w-5 min-w-0 flex-shrink-0" />
+              </Tooltip>
               <span className="w-40 truncate md:w-auto">
                 <Link
                   href={
@@ -98,7 +110,9 @@ const RequestBlock: React.FC<RequestBlockProps> = ({ request, onUpdate }) => {
             </div>
             {request.modifiedBy && (
               <div className="flex flex-nowrap">
-                <EyeIcon className="mr-1.5 h-5 w-5 flex-shrink-0" />
+                <Tooltip content={intl.formatMessage(messages.lastmodifiedby)}>
+                  <EyeIcon className="mr-1.5 h-5 w-5 flex-shrink-0" />
+                </Tooltip>
                 <span className="w-40 truncate md:w-auto">
                   <Link
                     href={
@@ -118,39 +132,47 @@ const RequestBlock: React.FC<RequestBlockProps> = ({ request, onUpdate }) => {
           <div className="ml-2 flex flex-shrink-0 flex-wrap">
             {request.status === MediaRequestStatus.PENDING && (
               <>
-                <Button
-                  buttonType="success"
-                  className="mr-1"
-                  onClick={() => updateRequest('approve')}
-                  disabled={isUpdating}
-                >
-                  <CheckIcon className="icon-sm" />
-                </Button>
+                <Tooltip content={intl.formatMessage(messages.approve)}>
+                  <Button
+                    buttonType="success"
+                    className="mr-1"
+                    onClick={() => updateRequest('approve')}
+                    disabled={isUpdating}
+                  >
+                    <CheckIcon className="icon-sm" />
+                  </Button>
+                </Tooltip>
+                <Tooltip content={intl.formatMessage(messages.decline)}>
+                  <Button
+                    buttonType="danger"
+                    className="mr-1"
+                    onClick={() => updateRequest('decline')}
+                    disabled={isUpdating}
+                  >
+                    <XIcon />
+                  </Button>
+                </Tooltip>
+                <Tooltip content={intl.formatMessage(messages.edit)}>
+                  <Button
+                    buttonType="warning"
+                    onClick={() => setShowEditModal(true)}
+                    disabled={isUpdating}
+                  >
+                    <PencilIcon className="icon-sm" />
+                  </Button>
+                </Tooltip>
+              </>
+            )}
+            {request.status !== MediaRequestStatus.PENDING && (
+              <Tooltip content={intl.formatMessage(messages.delete)}>
                 <Button
                   buttonType="danger"
-                  className="mr-1"
-                  onClick={() => updateRequest('decline')}
+                  onClick={() => deleteRequest()}
                   disabled={isUpdating}
                 >
-                  <XIcon />
+                  <TrashIcon className="icon-sm" />
                 </Button>
-                <Button
-                  buttonType="primary"
-                  onClick={() => setShowEditModal(true)}
-                  disabled={isUpdating}
-                >
-                  <PencilIcon className="icon-sm" />
-                </Button>
-              </>
-            )}
-            {request.status !== MediaRequestStatus.PENDING && (
-              <Button
-                buttonType="danger"
-                onClick={() => deleteRequest()}
-                disabled={isUpdating}
-              >
-                <TrashIcon className="icon-sm" />
-              </Button>
+              </Tooltip>
             )}
           </div>
         </div>
@@ -177,10 +199,17 @@ const RequestBlock: React.FC<RequestBlockProps> = ({ request, onUpdate }) => {
                   {intl.formatMessage(globalMessages.pending)}
                 </Badge>
               )}
+              {request.status === MediaRequestStatus.FAILED && (
+                <Badge badgeType="danger">
+                  {intl.formatMessage(globalMessages.failed)}
+                </Badge>
+              )}
             </div>
           </div>
           <div className="mt-2 flex items-center text-sm leading-5 sm:mt-0">
-            <CalendarIcon className="mr-1.5 h-5 w-5 flex-shrink-0" />
+            <Tooltip content={intl.formatMessage(messages.requestdate)}>
+              <CalendarIcon className="mr-1.5 h-5 w-5 flex-shrink-0" />
+            </Tooltip>
             <span>
               {intl.formatDate(request.createdAt, {
                 year: 'numeric',
@@ -209,7 +238,7 @@ const RequestBlock: React.FC<RequestBlockProps> = ({ request, onUpdate }) => {
             </div>
           </div>
         )}
-        {(server || profile !== null || rootFolder) && (
+        {(server || profile || rootFolder || languageProfile) && (
           <>
             <div className="mt-4 mb-1 text-sm">
               {intl.formatMessage(messages.requestoverrides)}
@@ -223,12 +252,12 @@ const RequestBlock: React.FC<RequestBlockProps> = ({ request, onUpdate }) => {
                   <span>{server}</span>
                 </li>
               )}
-              {profile !== null && (
+              {profile && (
                 <li className="flex justify-between px-1 py-2">
                   <span className="font-bold">
                     {intl.formatMessage(messages.profilechanged)}
                   </span>
-                  <span>ID {profile}</span>
+                  <span>{profile}</span>
                 </li>
               )}
               {rootFolder && (
@@ -239,6 +268,14 @@ const RequestBlock: React.FC<RequestBlockProps> = ({ request, onUpdate }) => {
                   <span>{rootFolder}</span>
                 </li>
               )}
+              {languageProfile && (
+                <li className="flex justify-between px-1 py-2">
+                  <span className="mr-2 font-bold">
+                    {intl.formatMessage(messages.languageprofile)}
+                  </span>
+                  <span>{languageProfile}</span>
+                </li>
+              )}
             </ul>
           </>
         )}
diff --git a/src/components/RequestButton/index.tsx b/src/components/RequestButton/index.tsx
index 5ba5bf5d..f7158944 100644
--- a/src/components/RequestButton/index.tsx
+++ b/src/components/RequestButton/index.tsx
@@ -1,23 +1,20 @@
+import ButtonWithDropdown from '@app/components/Common/ButtonWithDropdown';
+import RequestModal from '@app/components/RequestModal';
+import useSettings from '@app/hooks/useSettings';
+import { Permission, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
 import { DownloadIcon } from '@heroicons/react/outline';
 import {
   CheckIcon,
   InformationCircleIcon,
   XIcon,
 } from '@heroicons/react/solid';
+import { MediaRequestStatus, MediaStatus } from '@server/constants/media';
+import type Media from '@server/entity/Media';
+import type { MediaRequest } from '@server/entity/MediaRequest';
 import axios from 'axios';
-import React, { useMemo, useState } from 'react';
+import { useMemo, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
-import {
-  MediaRequestStatus,
-  MediaStatus,
-} from '../../../server/constants/media';
-import Media from '../../../server/entity/Media';
-import { MediaRequest } from '../../../server/entity/MediaRequest';
-import useSettings from '../../hooks/useSettings';
-import { Permission, useUser } from '../../hooks/useUser';
-import globalMessages from '../../i18n/globalMessages';
-import ButtonWithDropdown from '../Common/ButtonWithDropdown';
-import RequestModal from '../RequestModal';
 
 const messages = defineMessages({
   viewrequest: 'View Request',
@@ -54,14 +51,14 @@ interface RequestButtonProps {
   is4kShowComplete?: boolean;
 }
 
-const RequestButton: React.FC<RequestButtonProps> = ({
+const RequestButton = ({
   tmdbId,
   onUpdate,
   media,
   mediaType,
   isShowComplete = false,
   is4kShowComplete = false,
-}) => {
+}: RequestButtonProps) => {
   const intl = useIntl();
   const settings = useSettings();
   const { user, hasPermission } = useUser();
@@ -77,13 +74,13 @@ const RequestButton: React.FC<RequestButtonProps> = ({
     (request) => request.status === MediaRequestStatus.PENDING && request.is4k
   );
 
+  // Current user's pending request, or the first pending request
   const activeRequest = useMemo(() => {
     return activeRequests && activeRequests.length > 0
       ? activeRequests.find((request) => request.requestedBy.id === user?.id) ??
           activeRequests[0]
       : undefined;
   }, [activeRequests, user]);
-
   const active4kRequest = useMemo(() => {
     return active4kRequests && active4kRequests.length > 0
       ? active4kRequests.find(
@@ -121,6 +118,151 @@ const RequestButton: React.FC<RequestButtonProps> = ({
   };
 
   const buttons: ButtonOption[] = [];
+
+  // If there are pending requests, show request management options first
+  if (activeRequest || active4kRequest) {
+    if (
+      activeRequest &&
+      (activeRequest.requestedBy.id === user?.id ||
+        (activeRequests?.length === 1 &&
+          hasPermission(Permission.MANAGE_REQUESTS)))
+    ) {
+      buttons.push({
+        id: 'active-request',
+        text: intl.formatMessage(messages.viewrequest),
+        action: () => {
+          setEditRequest(true);
+          setShowRequestModal(true);
+        },
+        svg: <InformationCircleIcon />,
+      });
+    }
+
+    if (
+      activeRequest &&
+      hasPermission(Permission.MANAGE_REQUESTS) &&
+      mediaType === 'movie'
+    ) {
+      buttons.push(
+        {
+          id: 'approve-request',
+          text: intl.formatMessage(messages.approverequest),
+          action: () => {
+            modifyRequest(activeRequest, 'approve');
+          },
+          svg: <CheckIcon />,
+        },
+        {
+          id: 'decline-request',
+          text: intl.formatMessage(messages.declinerequest),
+          action: () => {
+            modifyRequest(activeRequest, 'decline');
+          },
+          svg: <XIcon />,
+        }
+      );
+    } else if (
+      activeRequests &&
+      activeRequests.length > 0 &&
+      hasPermission(Permission.MANAGE_REQUESTS) &&
+      mediaType === 'tv'
+    ) {
+      buttons.push(
+        {
+          id: 'approve-request-batch',
+          text: intl.formatMessage(messages.approverequests, {
+            requestCount: activeRequests.length,
+          }),
+          action: () => {
+            modifyRequests(activeRequests, 'approve');
+          },
+          svg: <CheckIcon />,
+        },
+        {
+          id: 'decline-request-batch',
+          text: intl.formatMessage(messages.declinerequests, {
+            requestCount: activeRequests.length,
+          }),
+          action: () => {
+            modifyRequests(activeRequests, 'decline');
+          },
+          svg: <XIcon />,
+        }
+      );
+    }
+
+    if (
+      active4kRequest &&
+      (active4kRequest.requestedBy.id === user?.id ||
+        (active4kRequests?.length === 1 &&
+          hasPermission(Permission.MANAGE_REQUESTS)))
+    ) {
+      buttons.push({
+        id: 'active-4k-request',
+        text: intl.formatMessage(messages.viewrequest4k),
+        action: () => {
+          setEditRequest(true);
+          setShowRequest4kModal(true);
+        },
+        svg: <InformationCircleIcon />,
+      });
+    }
+
+    if (
+      active4kRequest &&
+      hasPermission(Permission.MANAGE_REQUESTS) &&
+      mediaType === 'movie'
+    ) {
+      buttons.push(
+        {
+          id: 'approve-4k-request',
+          text: intl.formatMessage(messages.approverequest4k),
+          action: () => {
+            modifyRequest(active4kRequest, 'approve');
+          },
+          svg: <CheckIcon />,
+        },
+        {
+          id: 'decline-4k-request',
+          text: intl.formatMessage(messages.declinerequest4k),
+          action: () => {
+            modifyRequest(active4kRequest, 'decline');
+          },
+          svg: <XIcon />,
+        }
+      );
+    } else if (
+      active4kRequests &&
+      active4kRequests.length > 0 &&
+      hasPermission(Permission.MANAGE_REQUESTS) &&
+      mediaType === 'tv'
+    ) {
+      buttons.push(
+        {
+          id: 'approve-4k-request-batch',
+          text: intl.formatMessage(messages.approve4krequests, {
+            requestCount: active4kRequests.length,
+          }),
+          action: () => {
+            modifyRequests(active4kRequests, 'approve');
+          },
+          svg: <CheckIcon />,
+        },
+        {
+          id: 'decline-4k-request-batch',
+          text: intl.formatMessage(messages.decline4krequests, {
+            requestCount: active4kRequests.length,
+          }),
+          action: () => {
+            modifyRequests(active4kRequests, 'decline');
+          },
+          svg: <XIcon />,
+        }
+      );
+    }
+  }
+
+  // Standard request button
   if (
     (!media || media.status === MediaStatus.UNKNOWN) &&
     hasPermission(
@@ -142,8 +284,28 @@ const RequestButton: React.FC<RequestButtonProps> = ({
       },
       svg: <DownloadIcon />,
     });
+  } else if (
+    mediaType === 'tv' &&
+    (!activeRequest || activeRequest.requestedBy.id !== user?.id) &&
+    hasPermission([Permission.REQUEST, Permission.REQUEST_TV], {
+      type: 'or',
+    }) &&
+    media &&
+    media.status !== MediaStatus.AVAILABLE &&
+    !isShowComplete
+  ) {
+    buttons.push({
+      id: 'request-more',
+      text: intl.formatMessage(messages.requestmore),
+      action: () => {
+        setEditRequest(false);
+        setShowRequestModal(true);
+      },
+      svg: <DownloadIcon />,
+    });
   }
 
+  // 4K request button
   if (
     (!media || media.status4k === MediaStatus.UNKNOWN) &&
     hasPermission(
@@ -167,175 +329,7 @@ const RequestButton: React.FC<RequestButtonProps> = ({
       },
       svg: <DownloadIcon />,
     });
-  }
-
-  if (
-    activeRequest &&
-    (activeRequest.requestedBy.id === user?.id ||
-      (activeRequests?.length === 1 &&
-        hasPermission(Permission.MANAGE_REQUESTS)))
-  ) {
-    buttons.push({
-      id: 'active-request',
-      text: intl.formatMessage(messages.viewrequest),
-      action: () => {
-        setEditRequest(true);
-        setShowRequestModal(true);
-      },
-      svg: <InformationCircleIcon />,
-    });
-  }
-
-  if (
-    active4kRequest &&
-    (active4kRequest.requestedBy.id === user?.id ||
-      (active4kRequests?.length === 1 &&
-        hasPermission(Permission.MANAGE_REQUESTS)))
-  ) {
-    buttons.push({
-      id: 'active-4k-request',
-      text: intl.formatMessage(messages.viewrequest4k),
-      action: () => {
-        setEditRequest(true);
-        setShowRequest4kModal(true);
-      },
-      svg: <InformationCircleIcon />,
-    });
-  }
-
-  if (
-    activeRequest &&
-    hasPermission(Permission.MANAGE_REQUESTS) &&
-    mediaType === 'movie'
-  ) {
-    buttons.push(
-      {
-        id: 'approve-request',
-        text: intl.formatMessage(messages.approverequest),
-        action: () => {
-          modifyRequest(activeRequest, 'approve');
-        },
-        svg: <CheckIcon />,
-      },
-      {
-        id: 'decline-request',
-        text: intl.formatMessage(messages.declinerequest),
-        action: () => {
-          modifyRequest(activeRequest, 'decline');
-        },
-        svg: <XIcon />,
-      }
-    );
-  }
-
-  if (
-    activeRequests &&
-    activeRequests.length > 0 &&
-    hasPermission(Permission.MANAGE_REQUESTS) &&
-    mediaType === 'tv'
-  ) {
-    buttons.push(
-      {
-        id: 'approve-request-batch',
-        text: intl.formatMessage(messages.approverequests, {
-          requestCount: activeRequests.length,
-        }),
-        action: () => {
-          modifyRequests(activeRequests, 'approve');
-        },
-        svg: <CheckIcon />,
-      },
-      {
-        id: 'decline-request-batch',
-        text: intl.formatMessage(messages.declinerequests, {
-          requestCount: activeRequests.length,
-        }),
-        action: () => {
-          modifyRequests(activeRequests, 'decline');
-        },
-        svg: <XIcon />,
-      }
-    );
-  }
-
-  if (
-    active4kRequest &&
-    hasPermission(Permission.MANAGE_REQUESTS) &&
-    mediaType === 'movie'
-  ) {
-    buttons.push(
-      {
-        id: 'approve-4k-request',
-        text: intl.formatMessage(messages.approverequest4k),
-        action: () => {
-          modifyRequest(active4kRequest, 'approve');
-        },
-        svg: <CheckIcon />,
-      },
-      {
-        id: 'decline-4k-request',
-        text: intl.formatMessage(messages.declinerequest4k),
-        action: () => {
-          modifyRequest(active4kRequest, 'decline');
-        },
-        svg: <XIcon />,
-      }
-    );
-  }
-
-  if (
-    active4kRequests &&
-    active4kRequests.length > 0 &&
-    hasPermission(Permission.MANAGE_REQUESTS) &&
-    mediaType === 'tv'
-  ) {
-    buttons.push(
-      {
-        id: 'approve-4k-request-batch',
-        text: intl.formatMessage(messages.approve4krequests, {
-          requestCount: active4kRequests.length,
-        }),
-        action: () => {
-          modifyRequests(active4kRequests, 'approve');
-        },
-        svg: <CheckIcon />,
-      },
-      {
-        id: 'decline-4k-request-batch',
-        text: intl.formatMessage(messages.decline4krequests, {
-          requestCount: active4kRequests.length,
-        }),
-        action: () => {
-          modifyRequests(active4kRequests, 'decline');
-        },
-        svg: <XIcon />,
-      }
-    );
-  }
-
-  if (
-    mediaType === 'tv' &&
-    (!activeRequest || activeRequest.requestedBy.id !== user?.id) &&
-    hasPermission([Permission.REQUEST, Permission.REQUEST_TV], {
-      type: 'or',
-    }) &&
-    media &&
-    media.status !== MediaStatus.AVAILABLE &&
-    media.status !== MediaStatus.UNKNOWN &&
-    !isShowComplete
-  ) {
-    buttons.push({
-      id: 'request-more',
-      text: intl.formatMessage(messages.requestmore),
-      action: () => {
-        setEditRequest(false);
-        setShowRequestModal(true);
-      },
-      svg: <DownloadIcon />,
-    });
-  }
-
-  if (
+  } else if (
     mediaType === 'tv' &&
     (!active4kRequest || active4kRequest.requestedBy.id !== user?.id) &&
     hasPermission([Permission.REQUEST_4K, Permission.REQUEST_4K_TV], {
@@ -343,7 +337,6 @@ const RequestButton: React.FC<RequestButtonProps> = ({
     }) &&
     media &&
     media.status4k !== MediaStatus.AVAILABLE &&
-    media.status4k !== MediaStatus.UNKNOWN &&
     !is4kShowComplete &&
     settings.currentSettings.series4kEnabled
   ) {
diff --git a/src/components/RequestCard/index.tsx b/src/components/RequestCard/index.tsx
index 38cf541f..0a44421d 100644
--- a/src/components/RequestCard/index.tsx
+++ b/src/components/RequestCard/index.tsx
@@ -1,3 +1,12 @@
+import Badge from '@app/components/Common/Badge';
+import Button from '@app/components/Common/Button';
+import CachedImage from '@app/components/Common/CachedImage';
+import Tooltip from '@app/components/Common/Tooltip';
+import RequestModal from '@app/components/RequestModal';
+import StatusBadge from '@app/components/StatusBadge';
+import { Permission, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import { withProperties } from '@app/utils/typeHelpers';
 import {
   CheckIcon,
   PencilIcon,
@@ -5,33 +14,28 @@ import {
   TrashIcon,
   XIcon,
 } from '@heroicons/react/solid';
+import { MediaRequestStatus } from '@server/constants/media';
+import type { MediaRequest } from '@server/entity/MediaRequest';
+import type { MovieDetails } from '@server/models/Movie';
+import type { TvDetails } from '@server/models/Tv';
 import axios from 'axios';
 import Link from 'next/link';
-import React, { useEffect, useState } from 'react';
+import { useEffect, useState } from 'react';
 import { useInView } from 'react-intersection-observer';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR, { mutate } from 'swr';
-import {
-  MediaRequestStatus,
-  MediaStatus,
-} from '../../../server/constants/media';
-import type { MediaRequest } from '../../../server/entity/MediaRequest';
-import type { MovieDetails } from '../../../server/models/Movie';
-import type { TvDetails } from '../../../server/models/Tv';
-import { Permission, useUser } from '../../hooks/useUser';
-import globalMessages from '../../i18n/globalMessages';
-import { withProperties } from '../../utils/typeHelpers';
-import Badge from '../Common/Badge';
-import Button from '../Common/Button';
-import CachedImage from '../Common/CachedImage';
-import RequestModal from '../RequestModal';
-import StatusBadge from '../StatusBadge';
 
 const messages = defineMessages({
   seasons: '{seasonCount, plural, one {Season} other {Seasons}}',
   failedretry: 'Something went wrong while retrying the request.',
-  mediaerror: 'The associated title for this request is no longer available.',
+  mediaerror: '{mediaType} Not Found',
+  tmdbid: 'TMDB ID',
+  tvdbid: 'TheTVDB ID',
+  approverequest: 'Approve Request',
+  declinerequest: 'Decline Request',
+  editrequest: 'Edit Request',
+  cancelrequest: 'Cancel Request',
   deleterequest: 'Delete Request',
 });
 
@@ -39,7 +43,7 @@ const isMovie = (movie: MovieDetails | TvDetails): movie is MovieDetails => {
   return (movie as MovieDetails).title !== undefined;
 };
 
-const RequestCardPlaceholder: React.FC = () => {
+const RequestCardPlaceholder = () => {
   return (
     <div className="relative w-72 animate-pulse rounded-xl bg-gray-700 p-4 sm:w-96">
       <div className="w-20 sm:w-28">
@@ -50,37 +54,133 @@ const RequestCardPlaceholder: React.FC = () => {
 };
 
 interface RequestCardErrorProps {
-  mediaId?: number;
+  requestData?: MediaRequest;
 }
 
-const RequestCardError: React.FC<RequestCardErrorProps> = ({ mediaId }) => {
+const RequestCardError = ({ requestData }: RequestCardErrorProps) => {
   const { hasPermission } = useUser();
   const intl = useIntl();
 
   const deleteRequest = async () => {
-    await axios.delete(`/api/v1/media/${mediaId}`);
+    await axios.delete(`/api/v1/media/${requestData?.media.id}`);
+    mutate('/api/v1/media?filter=allavailable&take=20&sort=mediaAdded');
     mutate('/api/v1/request?filter=all&take=10&sort=modified&skip=0');
   };
 
   return (
-    <div className="relative w-72 rounded-xl bg-gray-800 p-4 ring-1 ring-red-500 sm:w-96">
+    <div
+      className="relative flex w-72 overflow-hidden rounded-xl bg-gray-800 p-4 text-gray-400 shadow ring-1 ring-red-500 sm:w-96"
+      data-testid="request-card"
+    >
       <div className="w-20 sm:w-28">
         <div className="w-full" style={{ paddingBottom: '150%' }}>
-          <div className="absolute inset-0 flex h-full w-full flex-col items-center justify-center px-10">
-            <div className="w-full whitespace-normal text-center text-xs text-gray-300 sm:text-sm">
-              {intl.formatMessage(messages.mediaerror)}
+          <div className="absolute inset-0 z-10 flex min-w-0 flex-1 flex-col p-4">
+            <div
+              className="whitespace-normal text-base font-bold text-white sm:text-lg"
+              data-testid="request-card-title"
+            >
+              {intl.formatMessage(messages.mediaerror, {
+                mediaType: intl.formatMessage(
+                  requestData?.type
+                    ? requestData?.type === 'movie'
+                      ? globalMessages.movie
+                      : globalMessages.tvshow
+                    : globalMessages.request
+                ),
+              })}
             </div>
-            {hasPermission(Permission.MANAGE_REQUESTS) && mediaId && (
-              <Button
-                buttonType="danger"
-                buttonSize="sm"
-                className="mt-4"
-                onClick={() => deleteRequest()}
-              >
-                <TrashIcon />
-                <span>{intl.formatMessage(messages.deleterequest)}</span>
-              </Button>
+            {requestData && (
+              <>
+                {hasPermission(
+                  [Permission.MANAGE_REQUESTS, Permission.REQUEST_VIEW],
+                  { type: 'or' }
+                ) && (
+                  <div className="card-field !hidden sm:!block">
+                    <Link href={`/users/${requestData.requestedBy.id}`}>
+                      <a className="group flex items-center">
+                        <img
+                          src={requestData.requestedBy.avatar}
+                          alt=""
+                          className="avatar-sm"
+                        />
+                        <span className="truncate group-hover:underline">
+                          {requestData.requestedBy.displayName}
+                        </span>
+                      </a>
+                    </Link>
+                  </div>
+                )}
+                <div className="mt-2 flex items-center text-sm sm:mt-1">
+                  <span className="mr-2 hidden font-bold sm:block">
+                    {intl.formatMessage(globalMessages.status)}
+                  </span>
+                  {requestData.status === MediaRequestStatus.DECLINED ||
+                  requestData.status === MediaRequestStatus.FAILED ? (
+                    <Badge badgeType="danger">
+                      {requestData.status === MediaRequestStatus.DECLINED
+                        ? intl.formatMessage(globalMessages.declined)
+                        : intl.formatMessage(globalMessages.failed)}
+                    </Badge>
+                  ) : (
+                    <StatusBadge
+                      status={
+                        requestData.media[
+                          requestData.is4k ? 'status4k' : 'status'
+                        ]
+                      }
+                      inProgress={
+                        (
+                          requestData.media[
+                            requestData.is4k
+                              ? 'downloadStatus4k'
+                              : 'downloadStatus'
+                          ] ?? []
+                        ).length > 0
+                      }
+                      is4k={requestData.is4k}
+                      plexUrl={
+                        requestData.is4k
+                          ? requestData.media.plexUrl4k
+                          : requestData.media.plexUrl
+                      }
+                      serviceUrl={
+                        requestData.is4k
+                          ? requestData.media.serviceUrl4k
+                          : requestData.media.serviceUrl
+                      }
+                    />
+                  )}
+                </div>
+              </>
             )}
+            <div className="flex flex-1 items-end space-x-2">
+              {hasPermission(Permission.MANAGE_REQUESTS) &&
+                requestData?.media.id && (
+                  <>
+                    <Button
+                      buttonType="danger"
+                      buttonSize="sm"
+                      className="mt-4 hidden sm:block"
+                      onClick={() => deleteRequest()}
+                    >
+                      <TrashIcon />
+                      <span>{intl.formatMessage(globalMessages.delete)}</span>
+                    </Button>
+                    <Tooltip
+                      content={intl.formatMessage(messages.deleterequest)}
+                    >
+                      <Button
+                        buttonType="danger"
+                        buttonSize="sm"
+                        className="mt-4 sm:hidden"
+                        onClick={() => deleteRequest()}
+                      >
+                        <TrashIcon />
+                      </Button>
+                    </Tooltip>
+                  </>
+                )}
+            </div>
           </div>
         </div>
       </div>
@@ -93,7 +193,7 @@ interface RequestCardProps {
   onTitleData?: (requestId: number, title: MovieDetails | TvDetails) => void;
 }
 
-const RequestCard: React.FC<RequestCardProps> = ({ request, onTitleData }) => {
+const RequestCard = ({ request, onTitleData }: RequestCardProps) => {
   const { ref, inView } = useInView({
     triggerOnce: true,
   });
@@ -168,7 +268,7 @@ const RequestCard: React.FC<RequestCardProps> = ({ request, onTitleData }) => {
   }
 
   if (!title || !requestData) {
-    return <RequestCardError mediaId={requestData?.media.id} />;
+    return <RequestCardError requestData={requestData} />;
   }
 
   return (
@@ -185,7 +285,10 @@ const RequestCard: React.FC<RequestCardProps> = ({ request, onTitleData }) => {
           setShowEditModal(false);
         }}
       />
-      <div className="relative flex w-72 overflow-hidden rounded-xl bg-gray-800 bg-cover bg-center p-4 text-gray-400 shadow ring-1 ring-gray-700 sm:w-96">
+      <div
+        className="relative flex w-72 overflow-hidden rounded-xl bg-gray-800 bg-cover bg-center p-4 text-gray-400 shadow ring-1 ring-gray-700 sm:w-96"
+        data-testid="request-card"
+      >
         {title.backdropPath && (
           <div className="absolute inset-0 z-0">
             <CachedImage
@@ -203,7 +306,10 @@ const RequestCard: React.FC<RequestCardProps> = ({ request, onTitleData }) => {
             />
           </div>
         )}
-        <div className="relative z-10 flex min-w-0 flex-1 flex-col pr-4">
+        <div
+          className="relative z-10 flex min-w-0 flex-1 flex-col pr-4"
+          data-testid="request-card-title"
+        >
           <div className="hidden text-xs font-medium text-white sm:flex">
             {(isMovie(title) ? title.releaseDate : title.firstAirDate)?.slice(
               0,
@@ -231,7 +337,7 @@ const RequestCard: React.FC<RequestCardProps> = ({ request, onTitleData }) => {
                   <img
                     src={requestData.requestedBy.avatar}
                     alt=""
-                    className="avatar-sm"
+                    className="avatar-sm object-cover"
                   />
                   <span className="truncate font-semibold group-hover:text-white group-hover:underline">
                     {requestData.requestedBy.displayName}
@@ -251,20 +357,13 @@ const RequestCard: React.FC<RequestCardProps> = ({ request, onTitleData }) => {
                       : request.seasons.length,
                 })}
               </span>
-              {title.seasons.filter((season) => season.seasonNumber !== 0)
-                .length === request.seasons.length ? (
-                <span className="mr-2 uppercase">
-                  <Badge>{intl.formatMessage(globalMessages.all)}</Badge>
-                </span>
-              ) : (
-                <div className="hide-scrollbar overflow-x-scroll">
-                  {request.seasons.map((season) => (
-                    <span key={`season-${season.id}`} className="mr-2">
-                      <Badge>{season.seasonNumber}</Badge>
-                    </span>
-                  ))}
-                </div>
-              )}
+              <div className="hide-scrollbar overflow-x-scroll">
+                {request.seasons.map((season) => (
+                  <span key={`season-${season.id}`} className="mr-2">
+                    <Badge>{season.seasonNumber}</Badge>
+                  </span>
+                ))}
+              </div>
             </div>
           )}
           <div className="mt-2 flex items-center text-sm sm:mt-1">
@@ -275,8 +374,7 @@ const RequestCard: React.FC<RequestCardProps> = ({ request, onTitleData }) => {
               <Badge badgeType="danger">
                 {intl.formatMessage(globalMessages.declined)}
               </Badge>
-            ) : requestData.media[requestData.is4k ? 'status4k' : 'status'] ===
-              MediaStatus.UNKNOWN ? (
+            ) : requestData.status === MediaRequestStatus.FAILED ? (
               <Badge
                 badgeType="danger"
                 href={`/${requestData.type}/${requestData.media.tmdbId}?manage=1`}
@@ -299,15 +397,20 @@ const RequestCard: React.FC<RequestCardProps> = ({ request, onTitleData }) => {
                 tmdbId={requestData.media.tmdbId}
                 mediaType={requestData.type}
                 plexUrl={
-                  requestData.media[requestData.is4k ? 'plexUrl4k' : 'plexUrl']
+                  requestData.is4k
+                    ? requestData.media.plexUrl4k
+                    : requestData.media.plexUrl
+                }
+                serviceUrl={
+                  requestData.is4k
+                    ? requestData.media.serviceUrl4k
+                    : requestData.media.serviceUrl
                 }
               />
             )}
           </div>
           <div className="flex flex-1 items-end space-x-2">
-            {requestData.media[requestData.is4k ? 'status4k' : 'status'] ===
-              MediaStatus.UNKNOWN &&
-              requestData.status !== MediaRequestStatus.DECLINED &&
+            {requestData.status === MediaRequestStatus.FAILED &&
               hasPermission(Permission.MANAGE_REQUESTS) && (
                 <Button
                   buttonType="primary"
@@ -327,26 +430,52 @@ const RequestCard: React.FC<RequestCardProps> = ({ request, onTitleData }) => {
             {requestData.status === MediaRequestStatus.PENDING &&
               hasPermission(Permission.MANAGE_REQUESTS) && (
                 <>
-                  <Button
-                    buttonType="success"
-                    buttonSize="sm"
-                    onClick={() => modifyRequest('approve')}
-                  >
-                    <CheckIcon style={{ marginRight: '0' }} />
-                    <span className="ml-1.5 hidden sm:block">
-                      {intl.formatMessage(globalMessages.approve)}
-                    </span>
-                  </Button>
-                  <Button
-                    buttonType="danger"
-                    buttonSize="sm"
-                    onClick={() => modifyRequest('decline')}
-                  >
-                    <XIcon style={{ marginRight: '0' }} />
-                    <span className="ml-1.5 hidden sm:block">
-                      {intl.formatMessage(globalMessages.decline)}
-                    </span>
-                  </Button>
+                  <div>
+                    <Button
+                      buttonType="success"
+                      buttonSize="sm"
+                      className="hidden sm:block"
+                      onClick={() => modifyRequest('approve')}
+                    >
+                      <CheckIcon />
+                      <span>{intl.formatMessage(globalMessages.approve)}</span>
+                    </Button>
+                    <Tooltip
+                      content={intl.formatMessage(messages.approverequest)}
+                    >
+                      <Button
+                        buttonType="success"
+                        buttonSize="sm"
+                        className="sm:hidden"
+                        onClick={() => modifyRequest('approve')}
+                      >
+                        <CheckIcon />
+                      </Button>
+                    </Tooltip>
+                  </div>
+                  <div>
+                    <Button
+                      buttonType="danger"
+                      buttonSize="sm"
+                      className="hidden sm:block"
+                      onClick={() => modifyRequest('decline')}
+                    >
+                      <XIcon />
+                      <span>{intl.formatMessage(globalMessages.decline)}</span>
+                    </Button>
+                    <Tooltip
+                      content={intl.formatMessage(messages.declinerequest)}
+                    >
+                      <Button
+                        buttonType="danger"
+                        buttonSize="sm"
+                        className="sm:hidden"
+                        onClick={() => modifyRequest('decline')}
+                      >
+                        <XIcon />
+                      </Button>
+                    </Tooltip>
+                  </div>
                 </>
               )}
             {requestData.status === MediaRequestStatus.PENDING &&
@@ -354,33 +483,54 @@ const RequestCard: React.FC<RequestCardProps> = ({ request, onTitleData }) => {
               requestData.requestedBy.id === user?.id &&
               (requestData.type === 'tv' ||
                 hasPermission(Permission.REQUEST_ADVANCED)) && (
-                <Button
-                  buttonType="primary"
-                  buttonSize="sm"
-                  onClick={() => setShowEditModal(true)}
-                  className={`${
-                    hasPermission(Permission.MANAGE_REQUESTS) ? 'sm:hidden' : ''
-                  }`}
-                >
-                  <PencilIcon style={{ marginRight: '0' }} />
-                  <span className="ml-1.5 hidden sm:block">
-                    {intl.formatMessage(globalMessages.edit)}
-                  </span>
-                </Button>
+                <div>
+                  {!hasPermission(Permission.MANAGE_REQUESTS) && (
+                    <Button
+                      buttonType="primary"
+                      buttonSize="sm"
+                      className="hidden sm:block"
+                      onClick={() => setShowEditModal(true)}
+                    >
+                      <PencilIcon />
+                      <span>{intl.formatMessage(globalMessages.edit)}</span>
+                    </Button>
+                  )}
+                  <Tooltip content={intl.formatMessage(messages.editrequest)}>
+                    <Button
+                      buttonType="primary"
+                      buttonSize="sm"
+                      className="sm:hidden"
+                      onClick={() => setShowEditModal(true)}
+                    >
+                      <PencilIcon />
+                    </Button>
+                  </Tooltip>
+                </div>
               )}
             {requestData.status === MediaRequestStatus.PENDING &&
               !hasPermission(Permission.MANAGE_REQUESTS) &&
               requestData.requestedBy.id === user?.id && (
-                <Button
-                  buttonType="danger"
-                  buttonSize="sm"
-                  onClick={() => deleteRequest()}
-                >
-                  <XIcon style={{ marginRight: '0' }} />
-                  <span className="ml-1.5 hidden sm:block">
-                    {intl.formatMessage(globalMessages.cancel)}
-                  </span>
-                </Button>
+                <div>
+                  <Button
+                    buttonType="danger"
+                    buttonSize="sm"
+                    className="hidden sm:block"
+                    onClick={() => deleteRequest()}
+                  >
+                    <XIcon />
+                    <span>{intl.formatMessage(globalMessages.cancel)}</span>
+                  </Button>
+                  <Tooltip content={intl.formatMessage(messages.cancelrequest)}>
+                    <Button
+                      buttonType="danger"
+                      buttonSize="sm"
+                      className="sm:hidden"
+                      onClick={() => deleteRequest()}
+                    >
+                      <XIcon />
+                    </Button>
+                  </Tooltip>
+                </div>
               )}
           </div>
         </div>
diff --git a/src/components/RequestList/RequestItem/index.tsx b/src/components/RequestList/RequestItem/index.tsx
index 54a5a59c..b3ca3781 100644
--- a/src/components/RequestList/RequestItem/index.tsx
+++ b/src/components/RequestList/RequestItem/index.tsx
@@ -1,3 +1,11 @@
+import Badge from '@app/components/Common/Badge';
+import Button from '@app/components/Common/Button';
+import CachedImage from '@app/components/Common/CachedImage';
+import ConfirmButton from '@app/components/Common/ConfirmButton';
+import RequestModal from '@app/components/RequestModal';
+import StatusBadge from '@app/components/StatusBadge';
+import { Permission, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
 import {
   CheckIcon,
   PencilIcon,
@@ -5,28 +13,17 @@ import {
   TrashIcon,
   XIcon,
 } from '@heroicons/react/solid';
+import { MediaRequestStatus } from '@server/constants/media';
+import type { MediaRequest } from '@server/entity/MediaRequest';
+import type { MovieDetails } from '@server/models/Movie';
+import type { TvDetails } from '@server/models/Tv';
 import axios from 'axios';
 import Link from 'next/link';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { useInView } from 'react-intersection-observer';
 import { defineMessages, FormattedRelativeTime, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
-import {
-  MediaRequestStatus,
-  MediaStatus,
-} from '../../../../server/constants/media';
-import type { MediaRequest } from '../../../../server/entity/MediaRequest';
-import type { MovieDetails } from '../../../../server/models/Movie';
-import type { TvDetails } from '../../../../server/models/Tv';
-import { Permission, useUser } from '../../../hooks/useUser';
-import globalMessages from '../../../i18n/globalMessages';
-import Badge from '../../Common/Badge';
-import Button from '../../Common/Button';
-import CachedImage from '../../Common/CachedImage';
-import ConfirmButton from '../../Common/ConfirmButton';
-import RequestModal from '../../RequestModal';
-import StatusBadge from '../../StatusBadge';
 
 const messages = defineMessages({
   seasons: '{seasonCount, plural, one {Season} other {Seasons}}',
@@ -35,50 +32,227 @@ const messages = defineMessages({
   requesteddate: 'Requested',
   modified: 'Modified',
   modifieduserdate: '{date} by {user}',
-  mediaerror: 'The associated title for this request is no longer available.',
+  mediaerror: '{mediaType} Not Found',
   editrequest: 'Edit Request',
   deleterequest: 'Delete Request',
   cancelRequest: 'Cancel Request',
+  tmdbid: 'TMDB ID',
+  tvdbid: 'TheTVDB ID',
 });
 
 const isMovie = (movie: MovieDetails | TvDetails): movie is MovieDetails => {
   return (movie as MovieDetails).title !== undefined;
 };
 
-interface RequestItemErroProps {
-  mediaId?: number;
+interface RequestItemErrorProps {
+  requestData?: MediaRequest;
   revalidateList: () => void;
 }
 
-const RequestItemError: React.FC<RequestItemErroProps> = ({
-  mediaId,
+const RequestItemError = ({
+  requestData,
   revalidateList,
-}) => {
+}: RequestItemErrorProps) => {
   const intl = useIntl();
   const { hasPermission } = useUser();
 
   const deleteRequest = async () => {
-    await axios.delete(`/api/v1/media/${mediaId}`);
+    await axios.delete(`/api/v1/media/${requestData?.media.id}`);
     revalidateList();
   };
 
   return (
-    <div className="flex h-64 w-full flex-col items-center justify-center rounded-xl bg-gray-800 px-10 ring-1 ring-red-500 lg:flex-row xl:h-28">
-      <span className="text-center text-sm text-gray-300 lg:text-left">
-        {intl.formatMessage(messages.mediaerror)}
-      </span>
-      {hasPermission(Permission.MANAGE_REQUESTS) && mediaId && (
-        <div className="mt-4 lg:ml-4 lg:mt-0">
+    <div className="flex h-64 w-full flex-col justify-center rounded-xl bg-gray-800 py-4 text-gray-400 shadow-md ring-1 ring-red-500 xl:h-28 xl:flex-row">
+      <div className="flex w-full flex-col justify-between overflow-hidden sm:flex-row">
+        <div className="flex w-full flex-col justify-center overflow-hidden pl-4 pr-4 sm:pr-0 xl:w-7/12 2xl:w-2/3">
+          <div className="flex text-lg font-bold text-white xl:text-xl">
+            {intl.formatMessage(messages.mediaerror, {
+              mediaType: intl.formatMessage(
+                requestData?.type
+                  ? requestData?.type === 'movie'
+                    ? globalMessages.movie
+                    : globalMessages.tvshow
+                  : globalMessages.request
+              ),
+            })}
+          </div>
+          {requestData && hasPermission(Permission.MANAGE_REQUESTS) && (
+            <>
+              <div className="card-field">
+                <span className="card-field-name">
+                  {intl.formatMessage(messages.tmdbid)}
+                </span>
+                <span className="flex truncate text-sm text-gray-300">
+                  {requestData.media.tmdbId}
+                </span>
+              </div>
+              {requestData.media.tvdbId && (
+                <div className="card-field">
+                  <span className="card-field-name">
+                    {intl.formatMessage(messages.tvdbid)}
+                  </span>
+                  <span className="flex truncate text-sm text-gray-300">
+                    {requestData?.media.tvdbId}
+                  </span>
+                </div>
+              )}
+            </>
+          )}
+        </div>
+        <div className="mt-4 ml-4 flex w-full flex-col justify-center overflow-hidden pr-4 text-sm sm:ml-2 sm:mt-0 xl:flex-1 xl:pr-0">
+          {requestData && (
+            <>
+              <div className="card-field">
+                <span className="card-field-name">
+                  {intl.formatMessage(globalMessages.status)}
+                </span>
+                {requestData.status === MediaRequestStatus.DECLINED ||
+                requestData.status === MediaRequestStatus.FAILED ? (
+                  <Badge badgeType="danger">
+                    {requestData.status === MediaRequestStatus.DECLINED
+                      ? intl.formatMessage(globalMessages.declined)
+                      : intl.formatMessage(globalMessages.failed)}
+                  </Badge>
+                ) : (
+                  <StatusBadge
+                    status={
+                      requestData.media[
+                        requestData.is4k ? 'status4k' : 'status'
+                      ]
+                    }
+                    inProgress={
+                      (
+                        requestData.media[
+                          requestData.is4k
+                            ? 'downloadStatus4k'
+                            : 'downloadStatus'
+                        ] ?? []
+                      ).length > 0
+                    }
+                    is4k={requestData.is4k}
+                    plexUrl={
+                      requestData.is4k
+                        ? requestData.media.plexUrl4k
+                        : requestData.media.plexUrl
+                    }
+                    serviceUrl={
+                      requestData.is4k
+                        ? requestData.media.serviceUrl4k
+                        : requestData.media.serviceUrl
+                    }
+                  />
+                )}
+              </div>
+              <div className="card-field">
+                {hasPermission(
+                  [Permission.MANAGE_REQUESTS, Permission.REQUEST_VIEW],
+                  { type: 'or' }
+                ) ? (
+                  <>
+                    <span className="card-field-name">
+                      {intl.formatMessage(messages.requested)}
+                    </span>
+                    <span className="flex truncate text-sm text-gray-300">
+                      {intl.formatMessage(messages.modifieduserdate, {
+                        date: (
+                          <FormattedRelativeTime
+                            value={Math.floor(
+                              (new Date(requestData.createdAt).getTime() -
+                                Date.now()) /
+                                1000
+                            )}
+                            updateIntervalInSeconds={1}
+                            numeric="auto"
+                          />
+                        ),
+                        user: (
+                          <Link href={`/users/${requestData.requestedBy.id}`}>
+                            <a className="group flex items-center truncate">
+                              <img
+                                src={requestData.requestedBy.avatar}
+                                alt=""
+                                className="avatar-sm ml-1.5"
+                              />
+                              <span className="truncate text-sm group-hover:underline">
+                                {requestData.requestedBy.displayName}
+                              </span>
+                            </a>
+                          </Link>
+                        ),
+                      })}
+                    </span>
+                  </>
+                ) : (
+                  <>
+                    <span className="card-field-name">
+                      {intl.formatMessage(messages.requesteddate)}
+                    </span>
+                    <span className="flex truncate text-sm text-gray-300">
+                      <FormattedRelativeTime
+                        value={Math.floor(
+                          (new Date(requestData.createdAt).getTime() -
+                            Date.now()) /
+                            1000
+                        )}
+                        updateIntervalInSeconds={1}
+                        numeric="auto"
+                      />
+                    </span>
+                  </>
+                )}
+              </div>
+              {requestData.modifiedBy && (
+                <div className="card-field">
+                  <span className="card-field-name">
+                    {intl.formatMessage(messages.modified)}
+                  </span>
+                  <span className="flex truncate text-sm text-gray-300">
+                    {intl.formatMessage(messages.modifieduserdate, {
+                      date: (
+                        <FormattedRelativeTime
+                          value={Math.floor(
+                            (new Date(requestData.updatedAt).getTime() -
+                              Date.now()) /
+                              1000
+                          )}
+                          updateIntervalInSeconds={1}
+                          numeric="auto"
+                        />
+                      ),
+                      user: (
+                        <Link href={`/users/${requestData.modifiedBy.id}`}>
+                          <a className="group flex items-center truncate">
+                            <img
+                              src={requestData.modifiedBy.avatar}
+                              alt=""
+                              className="avatar-sm ml-1.5"
+                            />
+                            <span className="truncate text-sm group-hover:underline">
+                              {requestData.modifiedBy.displayName}
+                            </span>
+                          </a>
+                        </Link>
+                      ),
+                    })}
+                  </span>
+                </div>
+              )}
+            </>
+          )}
+        </div>
+      </div>
+      <div className="z-10 mt-4 flex w-full flex-col justify-center pl-4 pr-4 xl:mt-0 xl:w-96 xl:items-end xl:pl-0">
+        {hasPermission(Permission.MANAGE_REQUESTS) && requestData?.media.id && (
           <Button
+            className="w-full"
             buttonType="danger"
-            buttonSize="sm"
             onClick={() => deleteRequest()}
           >
             <TrashIcon />
             <span>{intl.formatMessage(messages.deleterequest)}</span>
           </Button>
-        </div>
-      )}
+        )}
+      </div>
     </div>
   );
 };
@@ -88,10 +262,7 @@ interface RequestItemProps {
   revalidateList: () => void;
 }
 
-const RequestItem: React.FC<RequestItemProps> = ({
-  request,
-  revalidateList,
-}) => {
+const RequestItem = ({ request, revalidateList }: RequestItemProps) => {
   const { ref, inView } = useInView({
     triggerOnce: true,
   });
@@ -157,7 +328,7 @@ const RequestItem: React.FC<RequestItemProps> = ({
   if (!title || !requestData) {
     return (
       <RequestItemError
-        mediaId={requestData?.media.id}
+        requestData={requestData}
         revalidateList={revalidateList}
       />
     );
@@ -249,20 +420,13 @@ const RequestItem: React.FC<RequestItemProps> = ({
                           : request.seasons.length,
                     })}
                   </span>
-                  {title.seasons.filter((season) => season.seasonNumber !== 0)
-                    .length === request.seasons.length ? (
-                    <span className="mr-2 uppercase">
-                      <Badge>{intl.formatMessage(globalMessages.all)}</Badge>
-                    </span>
-                  ) : (
-                    <div className="hide-scrollbar flex flex-nowrap overflow-x-scroll">
-                      {request.seasons.map((season) => (
-                        <span key={`season-${season.id}`} className="mr-2">
-                          <Badge>{season.seasonNumber}</Badge>
-                        </span>
-                      ))}
-                    </div>
-                  )}
+                  <div className="hide-scrollbar flex flex-nowrap overflow-x-scroll">
+                    {request.seasons.map((season) => (
+                      <span key={`season-${season.id}`} className="mr-2">
+                        <Badge>{season.seasonNumber}</Badge>
+                      </span>
+                    ))}
+                  </div>
                 </div>
               )}
             </div>
@@ -276,9 +440,7 @@ const RequestItem: React.FC<RequestItemProps> = ({
                 <Badge badgeType="danger">
                   {intl.formatMessage(globalMessages.declined)}
                 </Badge>
-              ) : requestData.media[
-                  requestData.is4k ? 'status4k' : 'status'
-                ] === MediaStatus.UNKNOWN ? (
+              ) : requestData.status === MediaRequestStatus.FAILED ? (
                 <Badge
                   badgeType="danger"
                   href={`/${requestData.type}/${requestData.media.tmdbId}?manage=1`}
@@ -301,9 +463,14 @@ const RequestItem: React.FC<RequestItemProps> = ({
                   tmdbId={requestData.media.tmdbId}
                   mediaType={requestData.type}
                   plexUrl={
-                    requestData.media[
-                      requestData.is4k ? 'plexUrl4k' : 'plexUrl'
-                    ]
+                    requestData.is4k
+                      ? requestData.media.plexUrl4k
+                      : requestData.media.plexUrl
+                  }
+                  serviceUrl={
+                    requestData.is4k
+                      ? requestData.media.serviceUrl4k
+                      : requestData.media.serviceUrl
                   }
                 />
               )}
@@ -336,7 +503,7 @@ const RequestItem: React.FC<RequestItemProps> = ({
                             <img
                               src={requestData.requestedBy.avatar}
                               alt=""
-                              className="avatar-sm ml-1.5"
+                              className="avatar-sm ml-1.5 object-cover"
                             />
                             <span className="truncate text-sm font-semibold group-hover:text-white group-hover:underline">
                               {requestData.requestedBy.displayName}
@@ -390,7 +557,7 @@ const RequestItem: React.FC<RequestItemProps> = ({
                           <img
                             src={requestData.modifiedBy.avatar}
                             alt=""
-                            className="avatar-sm ml-1.5"
+                            className="avatar-sm ml-1.5 object-cover"
                           />
                           <span className="truncate text-sm font-semibold group-hover:text-white group-hover:underline">
                             {requestData.modifiedBy.displayName}
@@ -405,9 +572,7 @@ const RequestItem: React.FC<RequestItemProps> = ({
           </div>
         </div>
         <div className="z-10 mt-4 flex w-full flex-col justify-center space-y-2 pl-4 pr-4 xl:mt-0 xl:w-96 xl:items-end xl:pl-0">
-          {requestData.media[requestData.is4k ? 'status4k' : 'status'] ===
-            MediaStatus.UNKNOWN &&
-            requestData.status !== MediaRequestStatus.DECLINED &&
+          {requestData.status === MediaRequestStatus.FAILED &&
             hasPermission(Permission.MANAGE_REQUESTS) && (
               <Button
                 className="w-full"
diff --git a/src/components/RequestList/index.tsx b/src/components/RequestList/index.tsx
index a21cbfdf..0fa94d05 100644
--- a/src/components/RequestList/index.tsx
+++ b/src/components/RequestList/index.tsx
@@ -1,23 +1,23 @@
+import Button from '@app/components/Common/Button';
+import Header from '@app/components/Common/Header';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import RequestItem from '@app/components/RequestList/RequestItem';
+import { useUpdateQueryParams } from '@app/hooks/useUpdateQueryParams';
+import { useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
 import {
   ChevronLeftIcon,
   ChevronRightIcon,
   FilterIcon,
   SortDescendingIcon,
 } from '@heroicons/react/solid';
+import type { RequestResultsResponse } from '@server/interfaces/api/requestInterfaces';
 import Link from 'next/link';
 import { useRouter } from 'next/router';
-import React, { useEffect, useState } from 'react';
+import { useEffect, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import type { RequestResultsResponse } from '../../../server/interfaces/api/requestInterfaces';
-import { useUpdateQueryParams } from '../../hooks/useUpdateQueryParams';
-import { useUser } from '../../hooks/useUser';
-import globalMessages from '../../i18n/globalMessages';
-import Button from '../Common/Button';
-import Header from '../Common/Header';
-import LoadingSpinner from '../Common/LoadingSpinner';
-import PageTitle from '../Common/PageTitle';
-import RequestItem from './RequestItem';
 
 const messages = defineMessages({
   requests: 'Requests',
@@ -33,16 +33,18 @@ enum Filter {
   PROCESSING = 'processing',
   AVAILABLE = 'available',
   UNAVAILABLE = 'unavailable',
+  FAILED = 'failed',
 }
 
 type Sort = 'added' | 'modified';
 
-const RequestList: React.FC = () => {
+const RequestList = () => {
   const router = useRouter();
   const intl = useIntl();
   const { user } = useUser({
     id: Number(router.query.userId),
   });
+  const { user: currentUser } = useUser();
   const [currentFilter, setCurrentFilter] = useState<Filter>(Filter.PENDING);
   const [currentSort, setCurrentSort] = useState<Sort>('added');
   const [currentPageSize, setCurrentPageSize] = useState<number>(10);
@@ -59,7 +61,11 @@ const RequestList: React.FC = () => {
     `/api/v1/request?take=${currentPageSize}&skip=${
       pageIndex * currentPageSize
     }&filter=${currentFilter}&sort=${currentSort}${
-      router.query.userId ? `&requestedBy=${router.query.userId}` : ''
+      router.pathname.startsWith('/profile')
+        ? `&requestedBy=${currentUser?.id}`
+        : router.query.userId
+        ? `&requestedBy=${router.query.userId}`
+        : ''
     }`
   );
 
@@ -115,7 +121,11 @@ const RequestList: React.FC = () => {
       <div className="mb-4 flex flex-col justify-between lg:flex-row lg:items-end">
         <Header
           subtext={
-            router.query.userId ? (
+            router.pathname.startsWith('/profile') ? (
+              <Link href={`/profile`}>
+                <a className="hover:underline">{currentUser?.displayName}</a>
+              </Link>
+            ) : router.query.userId ? (
               <Link href={`/users/${user?.id}`}>
                 <a className="hover:underline">{user?.displayName}</a>
               </Link>
@@ -158,6 +168,9 @@ const RequestList: React.FC = () => {
               <option value="processing">
                 {intl.formatMessage(globalMessages.processing)}
               </option>
+              <option value="failed">
+                {intl.formatMessage(globalMessages.failed)}
+              </option>
               <option value="available">
                 {intl.formatMessage(globalMessages.available)}
               </option>
@@ -238,9 +251,9 @@ const RequestList: React.FC = () => {
                       ? pageIndex * currentPageSize + data.results.length
                       : (pageIndex + 1) * currentPageSize,
                   total: data.pageInfo.results,
-                  strong: function strong(msg) {
-                    return <span className="font-medium">{msg}</span>;
-                  },
+                  strong: (msg: React.ReactNode) => (
+                    <span className="font-medium">{msg}</span>
+                  ),
                 })}
             </p>
           </div>
diff --git a/src/components/RequestModal/AdvancedRequester/index.tsx b/src/components/RequestModal/AdvancedRequester/index.tsx
index d4cead4a..e8ac41b1 100644
--- a/src/components/RequestModal/AdvancedRequester/index.tsx
+++ b/src/components/RequestModal/AdvancedRequester/index.tsx
@@ -1,21 +1,22 @@
 /* eslint-disable react-hooks/exhaustive-deps */
+import { SmallLoadingSpinner } from '@app/components/Common/LoadingSpinner';
+import type { User } from '@app/hooks/useUser';
+import { Permission, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import { formatBytes } from '@app/utils/numberHelpers';
 import { Listbox, Transition } from '@headlessui/react';
-import { AdjustmentsIcon } from '@heroicons/react/outline';
 import { CheckIcon, ChevronDownIcon } from '@heroicons/react/solid';
+import type {
+  ServiceCommonServer,
+  ServiceCommonServerWithDetails,
+} from '@server/interfaces/api/serviceInterfaces';
+import type { UserResultsResponse } from '@server/interfaces/api/userInterfaces';
+import { hasPermission } from '@server/lib/permissions';
 import { isEqual } from 'lodash';
-import React, { useEffect, useState } from 'react';
+import { useEffect, useMemo, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import Select from 'react-select';
 import useSWR from 'swr';
-import type {
-  ServiceCommonServer,
-  ServiceCommonServerWithDetails,
-} from '../../../../server/interfaces/api/serviceInterfaces';
-import type { UserResultsResponse } from '../../../../server/interfaces/api/userInterfaces';
-import { Permission, User, useUser } from '../../../hooks/useUser';
-import globalMessages from '../../../i18n/globalMessages';
-import { formatBytes } from '../../../utils/numberHelpers';
-import { SmallLoadingSpinner } from '../../Common/LoadingSpinner';
 
 type OptionType = {
   value: number;
@@ -55,16 +56,16 @@ interface AdvancedRequesterProps {
   onChange: (overrides: RequestOverrides) => void;
 }
 
-const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
+const AdvancedRequester = ({
   type,
   is4k = false,
   isAnime = false,
   defaultOverrides,
   requestUser,
   onChange,
-}) => {
+}: AdvancedRequesterProps) => {
   const intl = useIntl();
-  const { user, hasPermission } = useUser();
+  const { user: currentUser, hasPermission: currentHasPermission } = useUser();
   const { data, error } = useSWR<ServiceCommonServer[]>(
     `/api/v1/service/${type === 'movie' ? 'radarr' : 'sonarr'}`,
     {
@@ -113,16 +114,41 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
   );
 
   const { data: userData } = useSWR<UserResultsResponse>(
-    hasPermission([Permission.MANAGE_REQUESTS, Permission.MANAGE_USERS])
+    currentHasPermission([Permission.MANAGE_REQUESTS, Permission.MANAGE_USERS])
       ? '/api/v1/user?take=1000&sort=displayname'
       : null
   );
+  const filteredUserData = useMemo(
+    () =>
+      userData?.results.filter((user) =>
+        hasPermission(
+          is4k
+            ? [
+                Permission.REQUEST_4K,
+                type === 'movie'
+                  ? Permission.REQUEST_4K_MOVIE
+                  : Permission.REQUEST_4K_TV,
+              ]
+            : [
+                Permission.REQUEST,
+                type === 'movie'
+                  ? Permission.REQUEST_MOVIE
+                  : Permission.REQUEST_TV,
+              ],
+          user.permissions,
+          { type: 'or' }
+        )
+      ),
+    [userData?.results]
+  );
 
   useEffect(() => {
-    if (userData?.results && !requestUser) {
-      setSelectedUser(userData.results.find((u) => u.id === user?.id) ?? null);
+    if (filteredUserData && !requestUser) {
+      setSelectedUser(
+        filteredUserData.find((u) => u.id === currentUser?.id) ?? null
+      );
     }
-  }, [userData?.results]);
+  }, [filteredUserData]);
 
   useEffect(() => {
     let defaultServer = data?.find(
@@ -273,18 +299,17 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
             serverData.rootFolders.length < 2 &&
             (serverData.languageProfiles ?? []).length < 2 &&
             !serverData.tags?.length)))) &&
-    (!selectedUser || (userData?.results ?? []).length < 2)
+    (!selectedUser || (filteredUserData ?? []).length < 2)
   ) {
     return null;
   }
 
   return (
     <>
-      <div className="mt-4 mb-2 flex items-center font-bold tracking-wider">
-        <AdjustmentsIcon className="mr-1.5 h-5 w-5" />
+      <div className="mt-4 mb-2 flex items-center text-lg font-semibold">
         {intl.formatMessage(messages.advancedoptions)}
       </div>
-      <div className="rounded-md bg-gray-600 p-4 shadow">
+      <div className="rounded-md">
         {!!data && selectedServer !== null && (
           <div className="flex flex-col md:flex-row">
             {data.filter((server) => server.is4k === is4k).length > 1 && (
@@ -513,9 +538,12 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
               />
             </div>
           )}
-        {hasPermission([Permission.MANAGE_REQUESTS, Permission.MANAGE_USERS]) &&
+        {currentHasPermission([
+          Permission.MANAGE_REQUESTS,
+          Permission.MANAGE_USERS,
+        ]) &&
           selectedUser &&
-          (userData?.results ?? []).length > 1 && (
+          (filteredUserData ?? []).length > 1 && (
             <Listbox
               as="div"
               value={selectedUser}
@@ -534,7 +562,7 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
                           <img
                             src={selectedUser.avatar}
                             alt=""
-                            className="h-6 w-6 flex-shrink-0 rounded-full"
+                            className="h-6 w-6 flex-shrink-0 rounded-full object-cover"
                           />
                           <span className="ml-3 block">
                             {selectedUser.displayName}
@@ -560,13 +588,13 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
                       leave="transition ease-in duration-100"
                       leaveFrom="opacity-100"
                       leaveTo="opacity-0"
-                      className="mt-1 w-full rounded-md bg-gray-800 shadow-lg"
+                      className="mt-1 w-full rounded-md border border-gray-700 bg-gray-800 shadow-lg"
                     >
                       <Listbox.Options
                         static
                         className="shadow-xs max-h-60 overflow-auto rounded-md py-1 text-base leading-6 focus:outline-none sm:text-sm sm:leading-5"
                       >
-                        {userData?.results.map((user) => (
+                        {filteredUserData?.map((user) => (
                           <Listbox.Option key={user.id} value={user}>
                             {({ selected, active }) => (
                               <div
@@ -584,7 +612,7 @@ const AdvancedRequester: React.FC<AdvancedRequesterProps> = ({
                                   <img
                                     src={user.avatar}
                                     alt=""
-                                    className="h-6 w-6 flex-shrink-0 rounded-full"
+                                    className="h-6 w-6 flex-shrink-0 rounded-full object-cover"
                                   />
                                   <span className="ml-3 block flex-shrink-0">
                                     {user.displayName}
diff --git a/src/components/RequestModal/CollectionRequestModal.tsx b/src/components/RequestModal/CollectionRequestModal.tsx
index 5695760f..67357fe4 100644
--- a/src/components/RequestModal/CollectionRequestModal.tsx
+++ b/src/components/RequestModal/CollectionRequestModal.tsx
@@ -1,31 +1,28 @@
-import { DownloadIcon } from '@heroicons/react/outline';
+import Alert from '@app/components/Common/Alert';
+import Badge from '@app/components/Common/Badge';
+import CachedImage from '@app/components/Common/CachedImage';
+import Modal from '@app/components/Common/Modal';
+import type { RequestOverrides } from '@app/components/RequestModal/AdvancedRequester';
+import AdvancedRequester from '@app/components/RequestModal/AdvancedRequester';
+import QuotaDisplay from '@app/components/RequestModal/QuotaDisplay';
+import { useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import { MediaRequestStatus, MediaStatus } from '@server/constants/media';
+import type { MediaRequest } from '@server/entity/MediaRequest';
+import type { QuotaResponse } from '@server/interfaces/api/userInterfaces';
+import { Permission } from '@server/lib/permissions';
+import type { Collection } from '@server/models/Collection';
 import axios from 'axios';
-import React, { useCallback, useEffect, useState } from 'react';
+import { useCallback, useEffect, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
-import {
-  MediaRequestStatus,
-  MediaStatus,
-} from '../../../server/constants/media';
-import { MediaRequest } from '../../../server/entity/MediaRequest';
-import { QuotaResponse } from '../../../server/interfaces/api/userInterfaces';
-import { Permission } from '../../../server/lib/permissions';
-import { Collection } from '../../../server/models/Collection';
-import { useUser } from '../../hooks/useUser';
-import globalMessages from '../../i18n/globalMessages';
-import Alert from '../Common/Alert';
-import Badge from '../Common/Badge';
-import CachedImage from '../Common/CachedImage';
-import Modal from '../Common/Modal';
-import AdvancedRequester, { RequestOverrides } from './AdvancedRequester';
-import QuotaDisplay from './QuotaDisplay';
 
 const messages = defineMessages({
   requestadmin: 'This request will be approved automatically.',
   requestSuccess: '<strong>{title}</strong> requested successfully!',
-  requesttitle: 'Request {title}',
-  request4ktitle: 'Request {title} in 4K',
+  requestcollectiontitle: 'Request Collection',
+  requestcollection4ktitle: 'Request Collection in 4K',
   requesterror: 'Something went wrong while submitting the request.',
   selectmovies: 'Select Movie(s)',
   requestmovies: 'Request {count} {count, plural, one {Movie} other {Movies}}',
@@ -41,13 +38,13 @@ interface RequestModalProps extends React.HTMLAttributes<HTMLDivElement> {
   onUpdating?: (isUpdating: boolean) => void;
 }
 
-const CollectionRequestModal: React.FC<RequestModalProps> = ({
+const CollectionRequestModal = ({
   onCancel,
   onComplete,
   tmdbId,
   onUpdating,
   is4k = false,
-}) => {
+}: RequestModalProps) => {
   const [isUpdating, setIsUpdating] = useState(false);
   const [requestOverrides, setRequestOverrides] =
     useState<RequestOverrides | null>(null);
@@ -220,9 +217,7 @@ const CollectionRequestModal: React.FC<RequestModalProps> = ({
         <span>
           {intl.formatMessage(messages.requestSuccess, {
             title: data?.name,
-            strong: function strong(msg) {
-              return <strong>{msg}</strong>;
-            },
+            strong: (msg: React.ReactNode) => <strong>{msg}</strong>,
           })}
         </span>,
         { appearance: 'success', autoDismiss: true }
@@ -253,9 +248,11 @@ const CollectionRequestModal: React.FC<RequestModalProps> = ({
       onCancel={onCancel}
       onOk={sendRequest}
       title={intl.formatMessage(
-        is4k ? messages.request4ktitle : messages.requesttitle,
-        { title: data?.name }
+        is4k
+          ? messages.requestcollection4ktitle
+          : messages.requestcollectiontitle
       )}
+      subTitle={data?.name}
       okText={
         isUpdating
           ? intl.formatMessage(globalMessages.requesting)
@@ -270,7 +267,6 @@ const CollectionRequestModal: React.FC<RequestModalProps> = ({
       }
       okDisabled={selectedParts.length === 0}
       okButtonType={'primary'}
-      iconSvg={<DownloadIcon />}
       backdrop={`https://image.tmdb.org/t/p/w1920_and_h800_multi_faces/${data?.backdropPath}`}
     >
       {hasAutoApprove && !quota?.movie.restricted && (
@@ -296,11 +292,11 @@ const CollectionRequestModal: React.FC<RequestModalProps> = ({
       <div className="flex flex-col">
         <div className="-mx-4 sm:mx-0">
           <div className="inline-block min-w-full py-2 align-middle">
-            <div className="overflow-hidden shadow sm:rounded-lg">
+            <div className="overflow-hidden border border-gray-700 backdrop-blur sm:rounded-lg">
               <table className="min-w-full">
                 <thead>
                   <tr>
-                    <th className="w-16 bg-gray-500 px-4 py-3">
+                    <th className="w-16 bg-gray-700 bg-opacity-80 px-4 py-3">
                       <span
                         role="checkbox"
                         tabIndex={0}
@@ -332,15 +328,15 @@ const CollectionRequestModal: React.FC<RequestModalProps> = ({
                         ></span>
                       </span>
                     </th>
-                    <th className="bg-gray-500 px-1 py-3 text-left text-xs font-medium uppercase leading-4 tracking-wider text-gray-200 md:px-6">
+                    <th className="bg-gray-700 bg-opacity-80 px-1 py-3 text-left text-xs font-medium uppercase leading-4 tracking-wider text-gray-200 md:px-6">
                       {intl.formatMessage(globalMessages.movie)}
                     </th>
-                    <th className="bg-gray-500 px-2 py-3 text-left text-xs font-medium uppercase leading-4 tracking-wider text-gray-200 md:px-6">
+                    <th className="bg-gray-700 bg-opacity-80 px-2 py-3 text-left text-xs font-medium uppercase leading-4 tracking-wider text-gray-200 md:px-6">
                       {intl.formatMessage(globalMessages.status)}
                     </th>
                   </tr>
                 </thead>
-                <tbody className="divide-y divide-gray-700 bg-gray-600">
+                <tbody className="divide-y divide-gray-700">
                   {data?.parts.map((part) => {
                     const partRequest = getPartRequest(part.id);
                     const partMedia =
@@ -382,7 +378,7 @@ const CollectionRequestModal: React.FC<RequestModalProps> = ({
                                 partRequest ||
                                 isSelectedPart(part.id)
                                   ? 'bg-indigo-500'
-                                  : 'bg-gray-800'
+                                  : 'bg-gray-700'
                               } absolute mx-auto h-4 w-9 rounded-full transition-colors duration-200 ease-in-out`}
                             ></span>
                             <span
diff --git a/src/components/RequestModal/MovieRequestModal.tsx b/src/components/RequestModal/MovieRequestModal.tsx
index 648f9aff..76a12638 100644
--- a/src/components/RequestModal/MovieRequestModal.tsx
+++ b/src/components/RequestModal/MovieRequestModal.tsx
@@ -1,32 +1,32 @@
-import { DownloadIcon } from '@heroicons/react/outline';
+import Alert from '@app/components/Common/Alert';
+import Modal from '@app/components/Common/Modal';
+import type { RequestOverrides } from '@app/components/RequestModal/AdvancedRequester';
+import AdvancedRequester from '@app/components/RequestModal/AdvancedRequester';
+import QuotaDisplay from '@app/components/RequestModal/QuotaDisplay';
+import { useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import { MediaStatus } from '@server/constants/media';
+import type { MediaRequest } from '@server/entity/MediaRequest';
+import type { QuotaResponse } from '@server/interfaces/api/userInterfaces';
+import { Permission } from '@server/lib/permissions';
+import type { MovieDetails } from '@server/models/Movie';
 import axios from 'axios';
-import React, { useCallback, useEffect, useState } from 'react';
+import { useCallback, useEffect, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
-import useSWR from 'swr';
-import { MediaStatus } from '../../../server/constants/media';
-import { MediaRequest } from '../../../server/entity/MediaRequest';
-import { QuotaResponse } from '../../../server/interfaces/api/userInterfaces';
-import { Permission } from '../../../server/lib/permissions';
-import { MovieDetails } from '../../../server/models/Movie';
-import { useUser } from '../../hooks/useUser';
-import globalMessages from '../../i18n/globalMessages';
-import Alert from '../Common/Alert';
-import Modal from '../Common/Modal';
-import AdvancedRequester, { RequestOverrides } from './AdvancedRequester';
-import QuotaDisplay from './QuotaDisplay';
+import useSWR, { mutate } from 'swr';
 
 const messages = defineMessages({
   requestadmin: 'This request will be approved automatically.',
   requestSuccess: '<strong>{title}</strong> requested successfully!',
   requestCancel: 'Request for <strong>{title}</strong> canceled.',
-  requesttitle: 'Request {title}',
-  request4ktitle: 'Request {title} in 4K',
+  requestmovietitle: 'Request Movie',
+  requestmovie4ktitle: 'Request Movie in 4K',
   edit: 'Edit Request',
   approve: 'Approve Request',
   cancel: 'Cancel Request',
-  pendingrequest: 'Pending Request for {title}',
-  pending4krequest: 'Pending 4K Request for {title}',
+  pendingrequest: 'Pending Movie Request',
+  pending4krequest: 'Pending 4K Movie Request',
   requestfrom: "{username}'s request is pending approval.",
   errorediting: 'Something went wrong while editing the request.',
   requestedited: 'Request for <strong>{title}</strong> edited successfully!',
@@ -44,14 +44,14 @@ interface RequestModalProps extends React.HTMLAttributes<HTMLDivElement> {
   onUpdating?: (isUpdating: boolean) => void;
 }
 
-const MovieRequestModal: React.FC<RequestModalProps> = ({
+const MovieRequestModal = ({
   onCancel,
   onComplete,
   tmdbId,
   onUpdating,
   editRequest,
   is4k = false,
-}) => {
+}: RequestModalProps) => {
   const [isUpdating, setIsUpdating] = useState(false);
   const [requestOverrides, setRequestOverrides] =
     useState<RequestOverrides | null>(null);
@@ -94,6 +94,7 @@ const MovieRequestModal: React.FC<RequestModalProps> = ({
         is4k,
         ...overrideParams,
       });
+      mutate('/api/v1/request?filter=all&take=10&sort=modified&skip=0');
 
       if (response.data) {
         if (onComplete) {
@@ -114,9 +115,7 @@ const MovieRequestModal: React.FC<RequestModalProps> = ({
           <span>
             {intl.formatMessage(messages.requestSuccess, {
               title: data?.title,
-              strong: function strong(msg) {
-                return <strong>{msg}</strong>;
-              },
+              strong: (msg: React.ReactNode) => <strong>{msg}</strong>,
             })}
           </span>,
           { appearance: 'success', autoDismiss: true }
@@ -139,6 +138,7 @@ const MovieRequestModal: React.FC<RequestModalProps> = ({
       const response = await axios.delete<MediaRequest>(
         `/api/v1/request/${editRequest?.id}`
       );
+      mutate('/api/v1/request?filter=all&take=10&sort=modified&skip=0');
 
       if (response.status === 204) {
         if (onComplete) {
@@ -148,9 +148,7 @@ const MovieRequestModal: React.FC<RequestModalProps> = ({
           <span>
             {intl.formatMessage(messages.requestCancel, {
               title: data?.title,
-              strong: function strong(msg) {
-                return <strong>{msg}</strong>;
-              },
+              strong: (msg: React.ReactNode) => <strong>{msg}</strong>,
             })}
           </span>,
           { appearance: 'success', autoDismiss: true }
@@ -177,6 +175,7 @@ const MovieRequestModal: React.FC<RequestModalProps> = ({
       if (alsoApproveRequest) {
         await axios.post(`/api/v1/request/${editRequest?.id}/approve`);
       }
+      mutate('/api/v1/request?filter=all&take=10&sort=modified&skip=0');
 
       addToast(
         <span>
@@ -186,9 +185,7 @@ const MovieRequestModal: React.FC<RequestModalProps> = ({
               : messages.requestedited,
             {
               title: data?.title,
-              strong: function strong(msg) {
-                return <strong>{msg}</strong>;
-              },
+              strong: (msg: React.ReactNode) => <strong>{msg}</strong>,
             }
           )}
         </span>,
@@ -220,9 +217,9 @@ const MovieRequestModal: React.FC<RequestModalProps> = ({
         backgroundClickable
         onCancel={onCancel}
         title={intl.formatMessage(
-          is4k ? messages.pending4krequest : messages.pendingrequest,
-          { title: data?.title }
+          is4k ? messages.pending4krequest : messages.pendingrequest
         )}
+        subTitle={data?.title}
         onOk={() =>
           hasPermission(Permission.MANAGE_REQUESTS)
             ? updateRequest(true)
@@ -266,7 +263,6 @@ const MovieRequestModal: React.FC<RequestModalProps> = ({
         }
         secondaryButtonType="danger"
         cancelText={intl.formatMessage(globalMessages.close)}
-        iconSvg={<DownloadIcon />}
         backdrop={`https://image.tmdb.org/t/p/w1920_and_h800_multi_faces/${data?.backdropPath}`}
       >
         {isOwner
@@ -312,9 +308,9 @@ const MovieRequestModal: React.FC<RequestModalProps> = ({
       onOk={sendRequest}
       okDisabled={isUpdating || quota?.movie.restricted}
       title={intl.formatMessage(
-        is4k ? messages.request4ktitle : messages.requesttitle,
-        { title: data?.title }
+        is4k ? messages.requestmovie4ktitle : messages.requestmovietitle
       )}
+      subTitle={data?.title}
       okText={
         isUpdating
           ? intl.formatMessage(globalMessages.requesting)
@@ -323,7 +319,6 @@ const MovieRequestModal: React.FC<RequestModalProps> = ({
             )
       }
       okButtonType={'primary'}
-      iconSvg={<DownloadIcon />}
       backdrop={`https://image.tmdb.org/t/p/w1920_and_h800_multi_faces/${data?.backdropPath}`}
     >
       {hasAutoApprove && !quota?.movie.restricted && (
diff --git a/src/components/RequestModal/QuotaDisplay/index.tsx b/src/components/RequestModal/QuotaDisplay/index.tsx
index d5a268ba..d3b1aa3f 100644
--- a/src/components/RequestModal/QuotaDisplay/index.tsx
+++ b/src/components/RequestModal/QuotaDisplay/index.tsx
@@ -1,9 +1,9 @@
+import ProgressCircle from '@app/components/Common/ProgressCircle';
 import { ChevronDownIcon, ChevronUpIcon } from '@heroicons/react/solid';
+import type { QuotaStatus } from '@server/interfaces/api/userInterfaces';
 import Link from 'next/link';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
-import { QuotaStatus } from '../../../../server/interfaces/api/userInterfaces';
-import ProgressCircle from '../../Common/ProgressCircle';
 
 const messages = defineMessages({
   requestsremaining:
@@ -35,18 +35,18 @@ interface QuotaDisplayProps {
   overLimit?: number;
 }
 
-const QuotaDisplay: React.FC<QuotaDisplayProps> = ({
+const QuotaDisplay = ({
   quota,
   mediaType,
   userOverride,
   remaining,
   overLimit,
-}) => {
+}: QuotaDisplayProps) => {
   const intl = useIntl();
   const [showDetails, setShowDetails] = useState(false);
   return (
     <div
-      className="my-4 flex flex-col rounded-md bg-gray-800 p-4"
+      className="my-4 flex flex-col rounded-md border border-gray-700 p-4 backdrop-blur"
       onClick={() => setShowDetails((s) => !s)}
       onKeyDown={(e) => {
         if (e.key === 'Enter') {
@@ -79,9 +79,7 @@ const QuotaDisplay: React.FC<QuotaDisplayProps> = ({
                   type: intl.formatMessage(
                     mediaType === 'movie' ? messages.movie : messages.season
                   ),
-                  strong: function strong(msg) {
-                    return <span className="font-bold">{msg}</span>;
-                  },
+                  strong: (msg: React.ReactNode) => <strong>{msg}</strong>,
                 })}
           </div>
         </div>
@@ -103,9 +101,7 @@ const QuotaDisplay: React.FC<QuotaDisplayProps> = ({
                   : messages.requiredquota,
                 {
                   seasons: overLimit,
-                  strong: function strong(msg) {
-                    return <span className="font-bold">{msg}</span>;
-                  },
+                  strong: (msg: React.ReactNode) => <strong>{msg}</strong>,
                 }
               )}
             </div>
@@ -124,9 +120,7 @@ const QuotaDisplay: React.FC<QuotaDisplayProps> = ({
                     : messages.seasonlimit,
                   { limit: quota?.limit }
                 ),
-                strong: function strong(msg) {
-                  return <span className="font-bold">{msg}</span>;
-                },
+                strong: (msg: React.ReactNode) => <strong>{msg}</strong>,
               }
             )}
           </div>
@@ -134,19 +128,15 @@ const QuotaDisplay: React.FC<QuotaDisplayProps> = ({
             {intl.formatMessage(
               userOverride ? messages.quotaLinkUser : messages.quotaLink,
               {
-                ProfileLink: function ProfileLink(msg) {
-                  return (
-                    <Link
-                      href={
-                        userOverride ? `/users/${userOverride}` : '/profile'
-                      }
-                    >
-                      <a className="text-white transition duration-300 hover:underline">
-                        {msg}
-                      </a>
-                    </Link>
-                  );
-                },
+                ProfileLink: (msg: React.ReactNode) => (
+                  <Link
+                    href={userOverride ? `/users/${userOverride}` : '/profile'}
+                  >
+                    <a className="text-white transition duration-300 hover:underline">
+                      {msg}
+                    </a>
+                  </Link>
+                ),
               }
             )}
           </div>
diff --git a/src/components/RequestModal/SearchByNameModal/index.tsx b/src/components/RequestModal/SearchByNameModal/index.tsx
index e2dc3c45..0c42017e 100644
--- a/src/components/RequestModal/SearchByNameModal/index.tsx
+++ b/src/components/RequestModal/SearchByNameModal/index.tsx
@@ -1,38 +1,37 @@
-import { DownloadIcon } from '@heroicons/react/outline';
-import React from 'react';
+import Alert from '@app/components/Common/Alert';
+import Modal from '@app/components/Common/Modal';
+import globalMessages from '@app/i18n/globalMessages';
+import type { SonarrSeries } from '@server/api/servarr/sonarr';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import { SonarrSeries } from '../../../../server/api/servarr/sonarr';
-import globalMessages from '../../../i18n/globalMessages';
-import Alert from '../../Common/Alert';
-import { SmallLoadingSpinner } from '../../Common/LoadingSpinner';
-import Modal from '../../Common/Modal';
 
 const messages = defineMessages({
   notvdbiddescription:
-    "We couldn't automatically match your request. Please select the correct match from the list below.",
-  nosummary: 'No summary for this title was found.',
+    'We were unable to automatically match this series. Please select the correct match below.',
+  nomatches: 'We were unable to find a match for this series.',
 });
 
 interface SearchByNameModalProps {
   setTvdbId: (id: number) => void;
   tvdbId: number | undefined;
-  loading: boolean;
   onCancel?: () => void;
   closeModal: () => void;
   modalTitle: string;
+  modalSubTitle: string;
   tmdbId: number;
+  backdrop?: string;
 }
 
-const SearchByNameModal: React.FC<SearchByNameModalProps> = ({
+const SearchByNameModal = ({
   setTvdbId,
   tvdbId,
-  loading,
   onCancel,
   closeModal,
   modalTitle,
+  modalSubTitle,
   tmdbId,
-}) => {
+  backdrop,
+}: SearchByNameModalProps) => {
   const intl = useIntl();
   const { data, error } = useSWR<SonarrSeries[]>(
     `/api/v1/service/sonarr/lookup/${tmdbId}`
@@ -42,23 +41,39 @@ const SearchByNameModal: React.FC<SearchByNameModalProps> = ({
     setTvdbId(tvdbId);
   };
 
+  if ((data ?? []).length === 0 || error) {
+    return (
+      <Modal
+        loading={!data && !error}
+        backgroundClickable
+        onOk={onCancel}
+        title={modalTitle}
+        subTitle={modalSubTitle}
+        okText={intl.formatMessage(globalMessages.close)}
+        okButtonType="primary"
+        backdrop={backdrop}
+      >
+        <Alert title={intl.formatMessage(messages.nomatches)} type="info" />
+      </Modal>
+    );
+  }
+
   return (
     <Modal
-      loading={loading && !error}
       backgroundClickable
       onCancel={onCancel}
       onOk={closeModal}
       title={modalTitle}
+      subTitle={modalSubTitle}
       okText={intl.formatMessage(globalMessages.next)}
       okDisabled={!tvdbId}
       okButtonType="primary"
-      iconSvg={<DownloadIcon />}
+      backdrop={backdrop}
     >
       <Alert
         title={intl.formatMessage(messages.notvdbiddescription)}
         type="info"
       />
-      {!data && !error && <SmallLoadingSpinner />}
       <div className="grid grid-cols-1 gap-4 pb-2 md:grid-cols-2">
         {data?.slice(0, 6).map((item) => (
           <button
@@ -67,7 +82,7 @@ const SearchByNameModal: React.FC<SearchByNameModalProps> = ({
             onClick={() => handleClick(item.tvdbId)}
           >
             <div
-              className={`flex h-40 w-full items-center overflow-hidden rounded-xl bg-gray-600 p-2 shadow transition ${
+              className={`flex h-40 w-full items-center overflow-hidden rounded-xl border border-gray-700 bg-gray-700 bg-opacity-20 p-2 shadow backdrop-blur transition ${
                 tvdbId === item.tvdbId ? 'ring ring-indigo-500' : ''
               } `}
             >
@@ -82,12 +97,35 @@ const SearchByNameModal: React.FC<SearchByNameModalProps> = ({
                 />
               </div>
               <div className="flex-grow self-start p-3 text-left">
-                <div className="text-grey-200 text-sm font-medium">
-                  {item.title}
+                <div className="text-sm font-medium leading-tight">
+                  {item.year}
                 </div>
-                <div className="h-24 overflow-hidden text-sm text-gray-400">
-                  {item.overview ?? intl.formatMessage(messages.nosummary)}
+                <div
+                  className="text-grey-200 text-xl font-bold leading-tight"
+                  style={{
+                    WebkitLineClamp: 1,
+                    display: '-webkit-box',
+                    overflow: 'hidden',
+                    WebkitBoxOrient: 'vertical',
+                    wordBreak: 'break-word',
+                  }}
+                >
+                  {item.title}
                 </div>
+                {item.overview && (
+                  <div
+                    className="whitespace-normal text-xs text-gray-400"
+                    style={{
+                      WebkitLineClamp: 5,
+                      display: '-webkit-box',
+                      overflow: 'hidden',
+                      WebkitBoxOrient: 'vertical',
+                      wordBreak: 'break-word',
+                    }}
+                  >
+                    {item.overview}
+                  </div>
+                )}
               </div>
             </div>
           </button>
diff --git a/src/components/RequestModal/TvRequestModal.tsx b/src/components/RequestModal/TvRequestModal.tsx
index 0a6da80f..bd4ca37d 100644
--- a/src/components/RequestModal/TvRequestModal.tsx
+++ b/src/components/RequestModal/TvRequestModal.tsx
@@ -1,39 +1,36 @@
-import { DownloadIcon } from '@heroicons/react/outline';
+import Alert from '@app/components/Common/Alert';
+import Badge from '@app/components/Common/Badge';
+import Modal from '@app/components/Common/Modal';
+import type { RequestOverrides } from '@app/components/RequestModal/AdvancedRequester';
+import AdvancedRequester from '@app/components/RequestModal/AdvancedRequester';
+import QuotaDisplay from '@app/components/RequestModal/QuotaDisplay';
+import SearchByNameModal from '@app/components/RequestModal/SearchByNameModal';
+import useSettings from '@app/hooks/useSettings';
+import { useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import { ANIME_KEYWORD_ID } from '@server/api/themoviedb/constants';
+import { MediaRequestStatus, MediaStatus } from '@server/constants/media';
+import type { MediaRequest } from '@server/entity/MediaRequest';
+import type SeasonRequest from '@server/entity/SeasonRequest';
+import type { QuotaResponse } from '@server/interfaces/api/userInterfaces';
+import { Permission } from '@server/lib/permissions';
+import type { TvDetails } from '@server/models/Tv';
 import axios from 'axios';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
-import useSWR from 'swr';
-import { ANIME_KEYWORD_ID } from '../../../server/api/themoviedb/constants';
-import {
-  MediaRequestStatus,
-  MediaStatus,
-} from '../../../server/constants/media';
-import { MediaRequest } from '../../../server/entity/MediaRequest';
-import SeasonRequest from '../../../server/entity/SeasonRequest';
-import { QuotaResponse } from '../../../server/interfaces/api/userInterfaces';
-import { Permission } from '../../../server/lib/permissions';
-import { TvDetails } from '../../../server/models/Tv';
-import useSettings from '../../hooks/useSettings';
-import { useUser } from '../../hooks/useUser';
-import globalMessages from '../../i18n/globalMessages';
-import Alert from '../Common/Alert';
-import Badge from '../Common/Badge';
-import Modal from '../Common/Modal';
-import AdvancedRequester, { RequestOverrides } from './AdvancedRequester';
-import QuotaDisplay from './QuotaDisplay';
-import SearchByNameModal from './SearchByNameModal';
+import useSWR, { mutate } from 'swr';
 
 const messages = defineMessages({
   requestadmin: 'This request will be approved automatically.',
   requestSuccess: '<strong>{title}</strong> requested successfully!',
-  requesttitle: 'Request {title}',
-  request4ktitle: 'Request {title} in 4K',
+  requestseriestitle: 'Request Series',
+  requestseries4ktitle: 'Request Series in 4K',
   edit: 'Edit Request',
   approve: 'Approve Request',
   cancel: 'Cancel Request',
-  pendingrequest: 'Pending Request for {title}',
-  pending4krequest: 'Pending 4K Request for {title}',
+  pendingrequest: 'Pending Request',
+  pending4krequest: 'Pending 4K Request',
   requestfrom: "{username}'s request is pending approval.",
   requestseasons:
     'Request {seasonCount} {seasonCount, plural, one {Season} other {Seasons}}',
@@ -63,14 +60,14 @@ interface RequestModalProps extends React.HTMLAttributes<HTMLDivElement> {
   editRequest?: MediaRequest;
 }
 
-const TvRequestModal: React.FC<RequestModalProps> = ({
+const TvRequestModal = ({
   onCancel,
   onComplete,
   tmdbId,
   onUpdating,
   editRequest,
   is4k = false,
-}) => {
+}: RequestModalProps) => {
   const settings = useSettings();
   const { addToast } = useToasts();
   const editingSeasons: number[] = (editRequest?.seasons ?? []).map(
@@ -130,6 +127,7 @@ const TvRequestModal: React.FC<RequestModalProps> = ({
       } else {
         await axios.delete(`/api/v1/request/${editRequest.id}`);
       }
+      mutate('/api/v1/request?filter=all&take=10&sort=modified&skip=0');
 
       addToast(
         <span>
@@ -140,16 +138,12 @@ const TvRequestModal: React.FC<RequestModalProps> = ({
                   : messages.requestedited,
                 {
                   title: data?.name,
-                  strong: function strong(msg) {
-                    return <strong>{msg}</strong>;
-                  },
+                  strong: (msg: React.ReactNode) => <strong>{msg}</strong>,
                 }
               )
             : intl.formatMessage(messages.requestcancelled, {
                 title: data?.name,
-                strong: function strong(msg) {
-                  return <strong>{msg}</strong>;
-                },
+                strong: (msg: React.ReactNode) => <strong>{msg}</strong>,
               })}
         </span>,
         {
@@ -208,6 +202,7 @@ const TvRequestModal: React.FC<RequestModalProps> = ({
             ),
         ...overrideParams,
       });
+      mutate('/api/v1/request?filter=all&take=10&sort=modified&skip=0');
 
       if (response.data) {
         if (onComplete) {
@@ -217,9 +212,7 @@ const TvRequestModal: React.FC<RequestModalProps> = ({
           <span>
             {intl.formatMessage(messages.requestSuccess, {
               title: data?.name,
-              strong: function strong(msg) {
-                return <strong>{msg}</strong>;
-              },
+              strong: (msg: React.ReactNode) => <strong>{msg}</strong>,
             })}
           </span>,
           { appearance: 'success', autoDismiss: true }
@@ -365,18 +358,18 @@ const TvRequestModal: React.FC<RequestModalProps> = ({
 
   const isOwner = editRequest && editRequest.requestedBy.id === user?.id;
 
-  return !data?.externalIds.tvdbId && searchModal.show ? (
+  return data && !error && !data.externalIds.tvdbId && searchModal.show ? (
     <SearchByNameModal
       tvdbId={tvdbId}
       setTvdbId={setTvdbId}
       closeModal={() => setSearchModal({ show: false })}
-      loading={!data && !error}
       onCancel={onCancel}
       modalTitle={intl.formatMessage(
-        is4k ? messages.request4ktitle : messages.requesttitle,
-        { title: data?.name }
+        is4k ? messages.requestseries4ktitle : messages.requestseriestitle
       )}
+      modalSubTitle={data.name}
       tmdbId={tmdbId}
+      backdrop={`https://image.tmdb.org/t/p/w1920_and_h800_multi_faces/${data?.backdropPath}`}
     />
   ) : (
     <Modal
@@ -396,10 +389,10 @@ const TvRequestModal: React.FC<RequestModalProps> = ({
             ? messages.pending4krequest
             : messages.pendingrequest
           : is4k
-          ? messages.request4ktitle
-          : messages.requesttitle,
-        { title: data?.name }
+          ? messages.requestseries4ktitle
+          : messages.requestseriestitle
       )}
+      subTitle={data?.name}
       okText={
         editRequest
           ? selectedSeasons.length === 0
@@ -450,7 +443,6 @@ const TvRequestModal: React.FC<RequestModalProps> = ({
           ? intl.formatMessage(globalMessages.back)
           : intl.formatMessage(globalMessages.cancel)
       }
-      iconSvg={<DownloadIcon />}
       backdrop={`https://image.tmdb.org/t/p/w1920_and_h800_multi_faces/${data?.backdropPath}`}
     >
       {editRequest
@@ -508,12 +500,12 @@ const TvRequestModal: React.FC<RequestModalProps> = ({
       <div className="flex flex-col">
         <div className="-mx-4 sm:mx-0">
           <div className="inline-block min-w-full py-2 align-middle">
-            <div className="overflow-hidden shadow sm:rounded-lg">
+            <div className="overflow-hidden border border-gray-700 shadow backdrop-blur sm:rounded-lg">
               <table className="min-w-full">
                 <thead>
                   <tr>
                     <th
-                      className={`w-16 bg-gray-500 px-4 py-3 ${
+                      className={`w-16 bg-gray-700 bg-opacity-80 px-4 py-3 ${
                         !settings.currentSettings.partialRequestsEnabled &&
                         'hidden'
                       }`}
@@ -550,18 +542,18 @@ const TvRequestModal: React.FC<RequestModalProps> = ({
                         ></span>
                       </span>
                     </th>
-                    <th className="bg-gray-500 px-1 py-3 text-left text-xs font-medium uppercase leading-4 tracking-wider text-gray-200 md:px-6">
+                    <th className="bg-gray-700 bg-opacity-80 px-1 py-3 text-left text-xs font-medium uppercase leading-4 tracking-wider text-gray-200 md:px-6">
                       {intl.formatMessage(messages.season)}
                     </th>
-                    <th className="bg-gray-500 px-5 py-3 text-left text-xs font-medium uppercase leading-4 tracking-wider text-gray-200 md:px-6">
+                    <th className="bg-gray-700 bg-opacity-80 px-5 py-3 text-left text-xs font-medium uppercase leading-4 tracking-wider text-gray-200 md:px-6">
                       {intl.formatMessage(messages.numberofepisodes)}
                     </th>
-                    <th className="bg-gray-500 px-2 py-3 text-left text-xs font-medium uppercase leading-4 tracking-wider text-gray-200 md:px-6">
+                    <th className="bg-gray-700 bg-opacity-80 px-2 py-3 text-left text-xs font-medium uppercase leading-4 tracking-wider text-gray-200 md:px-6">
                       {intl.formatMessage(globalMessages.status)}
                     </th>
                   </tr>
                 </thead>
-                <tbody className="divide-y divide-gray-700 bg-gray-600">
+                <tbody className="divide-y divide-gray-700">
                   {data?.seasons
                     .filter((season) => season.seasonNumber !== 0)
                     .map((season) => {
@@ -620,7 +612,7 @@ const TvRequestModal: React.FC<RequestModalProps> = ({
                                     )) ||
                                   isSelectedSeason(season.seasonNumber)
                                     ? 'bg-indigo-500'
-                                    : 'bg-gray-800'
+                                    : 'bg-gray-700'
                                 } absolute mx-auto h-4 w-9 rounded-full transition-colors duration-200 ease-in-out`}
                               ></span>
                               <span
diff --git a/src/components/RequestModal/index.tsx b/src/components/RequestModal/index.tsx
index dfbb715e..e5421fb5 100644
--- a/src/components/RequestModal/index.tsx
+++ b/src/components/RequestModal/index.tsx
@@ -1,10 +1,9 @@
-import React from 'react';
-import type { MediaStatus } from '../../../server/constants/media';
-import { MediaRequest } from '../../../server/entity/MediaRequest';
-import Transition from '../Transition';
-import CollectionRequestModal from './CollectionRequestModal';
-import MovieRequestModal from './MovieRequestModal';
-import TvRequestModal from './TvRequestModal';
+import CollectionRequestModal from '@app/components/RequestModal/CollectionRequestModal';
+import MovieRequestModal from '@app/components/RequestModal/MovieRequestModal';
+import TvRequestModal from '@app/components/RequestModal/TvRequestModal';
+import { Transition } from '@headlessui/react';
+import type { MediaStatus } from '@server/constants/media';
+import type { MediaRequest } from '@server/entity/MediaRequest';
 
 interface RequestModalProps {
   show: boolean;
@@ -17,7 +16,7 @@ interface RequestModalProps {
   onUpdating?: (isUpdating: boolean) => void;
 }
 
-const RequestModal: React.FC<RequestModalProps> = ({
+const RequestModal = ({
   type,
   show,
   tmdbId,
@@ -26,9 +25,10 @@ const RequestModal: React.FC<RequestModalProps> = ({
   onComplete,
   onUpdating,
   onCancel,
-}) => {
+}: RequestModalProps) => {
   return (
     <Transition
+      as="div"
       enter="transition opacity-0 duration-300"
       enterFrom="opacity-0"
       enterTo="opacity-100"
diff --git a/src/components/ResetPassword/RequestResetLink.tsx b/src/components/ResetPassword/RequestResetLink.tsx
index 76d2c4a9..28d854f1 100644
--- a/src/components/ResetPassword/RequestResetLink.tsx
+++ b/src/components/ResetPassword/RequestResetLink.tsx
@@ -1,14 +1,14 @@
+import Button from '@app/components/Common/Button';
+import ImageFader from '@app/components/Common/ImageFader';
+import PageTitle from '@app/components/Common/PageTitle';
+import LanguagePicker from '@app/components/Layout/LanguagePicker';
 import { ArrowLeftIcon, MailIcon } from '@heroicons/react/solid';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
 import Link from 'next/link';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import * as Yup from 'yup';
-import Button from '../Common/Button';
-import ImageFader from '../Common/ImageFader';
-import PageTitle from '../Common/PageTitle';
-import LanguagePicker from '../Layout/LanguagePicker';
 
 const messages = defineMessages({
   passwordreset: 'Password Reset',
@@ -21,7 +21,7 @@ const messages = defineMessages({
     'A password reset link will be sent to the provided email address if it is associated with a valid user.',
 });
 
-const ResetPassword: React.FC = () => {
+const ResetPassword = () => {
   const intl = useIntl();
   const [hasSubmitted, setSubmitted] = useState(false);
 
@@ -113,9 +113,11 @@ const ResetPassword: React.FC = () => {
                               className="form-input-area block w-full min-w-0 flex-1 rounded-md border border-gray-500 bg-gray-700 text-white transition duration-150 ease-in-out sm:text-sm sm:leading-5"
                             />
                           </div>
-                          {errors.email && touched.email && (
-                            <div className="error">{errors.email}</div>
-                          )}
+                          {errors.email &&
+                            touched.email &&
+                            typeof errors.email === 'string' && (
+                              <div className="error">{errors.email}</div>
+                            )}
                         </div>
                       </div>
                       <div className="mt-4 border-t border-gray-700 pt-5">
diff --git a/src/components/ResetPassword/index.tsx b/src/components/ResetPassword/index.tsx
index a7077b54..dd644642 100644
--- a/src/components/ResetPassword/index.tsx
+++ b/src/components/ResetPassword/index.tsx
@@ -1,16 +1,16 @@
+import Button from '@app/components/Common/Button';
+import ImageFader from '@app/components/Common/ImageFader';
+import SensitiveInput from '@app/components/Common/SensitiveInput';
+import LanguagePicker from '@app/components/Layout/LanguagePicker';
+import globalMessages from '@app/i18n/globalMessages';
 import { SupportIcon } from '@heroicons/react/outline';
 import axios from 'axios';
 import { Form, Formik } from 'formik';
 import Link from 'next/link';
 import { useRouter } from 'next/router';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import * as Yup from 'yup';
-import globalMessages from '../../i18n/globalMessages';
-import Button from '../Common/Button';
-import ImageFader from '../Common/ImageFader';
-import SensitiveInput from '../Common/SensitiveInput';
-import LanguagePicker from '../Layout/LanguagePicker';
 
 const messages = defineMessages({
   passwordreset: 'Password Reset',
@@ -25,7 +25,7 @@ const messages = defineMessages({
   resetpasswordsuccessmessage: 'Password reset successfully!',
 });
 
-const ResetPassword: React.FC = () => {
+const ResetPassword = () => {
   const intl = useIntl();
   const router = useRouter();
   const [hasSubmitted, setSubmitted] = useState(false);
@@ -129,9 +129,11 @@ const ResetPassword: React.FC = () => {
                               className="form-input-area block w-full min-w-0 flex-1 rounded-md border border-gray-500 bg-gray-700 text-white transition duration-150 ease-in-out sm:text-sm sm:leading-5"
                             />
                           </div>
-                          {errors.password && touched.password && (
-                            <div className="error">{errors.password}</div>
-                          )}
+                          {errors.password &&
+                            touched.password &&
+                            typeof errors.password === 'string' && (
+                              <div className="error">{errors.password}</div>
+                            )}
                         </div>
                         <label
                           htmlFor="confirmPassword"
diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx
index e36442cf..22f143f2 100644
--- a/src/components/Search/index.tsx
+++ b/src/components/Search/index.tsx
@@ -1,23 +1,22 @@
-import React from 'react';
-import { useRouter } from 'next/router';
-import {
-  TvResult,
+import Header from '@app/components/Common/Header';
+import ListView from '@app/components/Common/ListView';
+import PageTitle from '@app/components/Common/PageTitle';
+import useDiscover from '@app/hooks/useDiscover';
+import Error from '@app/pages/_error';
+import type {
   MovieResult,
   PersonResult,
-} from '../../../server/models/Search';
-import ListView from '../Common/ListView';
+  TvResult,
+} from '@server/models/Search';
+import { useRouter } from 'next/router';
 import { defineMessages, useIntl } from 'react-intl';
-import Header from '../Common/Header';
-import PageTitle from '../Common/PageTitle';
-import Error from '../../pages/_error';
-import useDiscover from '../../hooks/useDiscover';
 
 const messages = defineMessages({
   search: 'Search',
   searchresults: 'Search Results',
 });
 
-const Search: React.FC = () => {
+const Search = () => {
   const intl = useIntl();
   const router = useRouter();
 
diff --git a/src/components/ServiceWorkerSetup/index.tsx b/src/components/ServiceWorkerSetup/index.tsx
index 56a558a3..f30a26d1 100644
--- a/src/components/ServiceWorkerSetup/index.tsx
+++ b/src/components/ServiceWorkerSetup/index.tsx
@@ -1,10 +1,10 @@
 /* eslint-disable no-console */
+import useSettings from '@app/hooks/useSettings';
+import { useUser } from '@app/hooks/useUser';
 import axios from 'axios';
-import React, { useEffect } from 'react';
-import useSettings from '../../hooks/useSettings';
-import { useUser } from '../../hooks/useUser';
+import { useEffect } from 'react';
 
-const ServiceWorkerSetup: React.FC = () => {
+const ServiceWorkerSetup = () => {
   const { currentSettings } = useSettings();
   const { user } = useUser();
   useEffect(() => {
diff --git a/src/components/Settings/CopyButton.tsx b/src/components/Settings/CopyButton.tsx
index bd9738a2..da48fe5d 100644
--- a/src/components/Settings/CopyButton.tsx
+++ b/src/components/Settings/CopyButton.tsx
@@ -1,5 +1,5 @@
 import { ClipboardCopyIcon } from '@heroicons/react/solid';
-import React, { useEffect } from 'react';
+import { useEffect } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useClipboard from 'react-use-clipboard';
@@ -8,7 +8,7 @@ const messages = defineMessages({
   copied: 'Copied API key to clipboard.',
 });
 
-const CopyButton: React.FC<{ textToCopy: string }> = ({ textToCopy }) => {
+const CopyButton = ({ textToCopy }: { textToCopy: string }) => {
   const intl = useIntl();
   const [isCopied, setCopied] = useClipboard(textToCopy, {
     successDuration: 1000,
diff --git a/src/components/Settings/LibraryItem.tsx b/src/components/Settings/LibraryItem.tsx
index 8d5b7ec7..eba0de40 100644
--- a/src/components/Settings/LibraryItem.tsx
+++ b/src/components/Settings/LibraryItem.tsx
@@ -1,5 +1,4 @@
 import { CheckIcon, XIcon } from '@heroicons/react/solid';
-import React from 'react';
 
 interface LibraryItemProps {
   isEnabled?: boolean;
@@ -7,11 +6,7 @@ interface LibraryItemProps {
   onToggle: () => void;
 }
 
-const LibraryItem: React.FC<LibraryItemProps> = ({
-  isEnabled,
-  name,
-  onToggle,
-}) => {
+const LibraryItem = ({ isEnabled, name, onToggle }: LibraryItemProps) => {
   return (
     <li className="col-span-1 flex rounded-md shadow-sm">
       <div className="flex flex-1 items-center justify-between truncate rounded-md border-t border-b border-r border-gray-700 bg-gray-600">
diff --git a/src/components/Settings/Notifications/NotificationsDiscord.tsx b/src/components/Settings/Notifications/NotificationsDiscord.tsx
index 38d24ba9..927bca6b 100644
--- a/src/components/Settings/Notifications/NotificationsDiscord.tsx
+++ b/src/components/Settings/Notifications/NotificationsDiscord.tsx
@@ -1,16 +1,16 @@
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
+import useSettings from '@app/hooks/useSettings';
+import globalMessages from '@app/i18n/globalMessages';
 import { BeakerIcon, SaveIcon } from '@heroicons/react/outline';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import useSettings from '../../../hooks/useSettings';
-import globalMessages from '../../../i18n/globalMessages';
-import Button from '../../Common/Button';
-import LoadingSpinner from '../../Common/LoadingSpinner';
-import NotificationTypeSelector from '../../NotificationTypeSelector';
 
 const messages = defineMessages({
   agentenabled: 'Enable Agent',
@@ -29,7 +29,7 @@ const messages = defineMessages({
   enableMentions: 'Enable Mentions',
 });
 
-const NotificationsDiscord: React.FC = () => {
+const NotificationsDiscord = () => {
   const intl = useIntl();
   const settings = useSettings();
   const { addToast, removeToast } = useToasts();
@@ -168,18 +168,16 @@ const NotificationsDiscord: React.FC = () => {
                 <span className="label-required">*</span>
                 <span className="label-tip">
                   {intl.formatMessage(messages.webhookUrlTip, {
-                    DiscordWebhookLink: function DiscordWebhookLink(msg) {
-                      return (
-                        <a
-                          href="https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks"
-                          className="text-white transition duration-300 hover:underline"
-                          target="_blank"
-                          rel="noreferrer"
-                        >
-                          {msg}
-                        </a>
-                      );
-                    },
+                    DiscordWebhookLink: (msg: React.ReactNode) => (
+                      <a
+                        href="https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks"
+                        className="text-white transition duration-300 hover:underline"
+                        target="_blank"
+                        rel="noreferrer"
+                      >
+                        {msg}
+                      </a>
+                    ),
                   })}
                 </span>
               </label>
@@ -192,9 +190,11 @@ const NotificationsDiscord: React.FC = () => {
                     inputMode="url"
                   />
                 </div>
-                {errors.webhookUrl && touched.webhookUrl && (
-                  <div className="error">{errors.webhookUrl}</div>
-                )}
+                {errors.webhookUrl &&
+                  touched.webhookUrl &&
+                  typeof errors.webhookUrl === 'string' && (
+                    <div className="error">{errors.webhookUrl}</div>
+                  )}
               </div>
             </div>
             <div className="form-row">
@@ -210,9 +210,11 @@ const NotificationsDiscord: React.FC = () => {
                     placeholder={settings.currentSettings.applicationTitle}
                   />
                 </div>
-                {errors.botUsername && touched.botUsername && (
-                  <div className="error">{errors.botUsername}</div>
-                )}
+                {errors.botUsername &&
+                  touched.botUsername &&
+                  typeof errors.botUsername === 'string' && (
+                    <div className="error">{errors.botUsername}</div>
+                  )}
               </div>
             </div>
             <div className="form-row">
@@ -228,9 +230,11 @@ const NotificationsDiscord: React.FC = () => {
                     inputMode="url"
                   />
                 </div>
-                {errors.botAvatarUrl && touched.botAvatarUrl && (
-                  <div className="error">{errors.botAvatarUrl}</div>
-                )}
+                {errors.botAvatarUrl &&
+                  touched.botAvatarUrl &&
+                  typeof errors.botAvatarUrl === 'string' && (
+                    <div className="error">{errors.botAvatarUrl}</div>
+                  )}
               </div>
             </div>
             <div className="form-row">
diff --git a/src/components/Settings/Notifications/NotificationsEmail.tsx b/src/components/Settings/Notifications/NotificationsEmail.tsx
index 40308390..242c0b85 100644
--- a/src/components/Settings/Notifications/NotificationsEmail.tsx
+++ b/src/components/Settings/Notifications/NotificationsEmail.tsx
@@ -1,16 +1,16 @@
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import SensitiveInput from '@app/components/Common/SensitiveInput';
+import SettingsBadge from '@app/components/Settings/SettingsBadge';
+import globalMessages from '@app/i18n/globalMessages';
 import { BeakerIcon, SaveIcon } from '@heroicons/react/outline';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR, { mutate } from 'swr';
 import * as Yup from 'yup';
-import globalMessages from '../../../i18n/globalMessages';
-import Badge from '../../Common/Badge';
-import Button from '../../Common/Button';
-import LoadingSpinner from '../../Common/LoadingSpinner';
-import SensitiveInput from '../../Common/SensitiveInput';
 
 const messages = defineMessages({
   validationSmtpHostRequired: 'You must provide a valid hostname or IP address',
@@ -46,7 +46,7 @@ const messages = defineMessages({
   validationPgpPassword: 'You must provide a PGP password',
 });
 
-export function OpenPgpLink(msg: string): JSX.Element {
+export function OpenPgpLink(msg: React.ReactNode) {
   return (
     <a href="https://www.openpgp.org/" target="_blank" rel="noreferrer">
       {msg}
@@ -54,7 +54,7 @@ export function OpenPgpLink(msg: string): JSX.Element {
   );
 }
 
-const NotificationsEmail: React.FC = () => {
+const NotificationsEmail = () => {
   const intl = useIntl();
   const { addToast, removeToast } = useToasts();
   const [isTesting, setIsTesting] = useState(false);
@@ -265,9 +265,11 @@ const NotificationsEmail: React.FC = () => {
                     inputMode="email"
                   />
                 </div>
-                {errors.emailFrom && touched.emailFrom && (
-                  <div className="error">{errors.emailFrom}</div>
-                )}
+                {errors.emailFrom &&
+                  touched.emailFrom &&
+                  typeof errors.emailFrom === 'string' && (
+                    <div className="error">{errors.emailFrom}</div>
+                  )}
               </div>
             </div>
             <div className="form-row">
@@ -284,9 +286,11 @@ const NotificationsEmail: React.FC = () => {
                     inputMode="url"
                   />
                 </div>
-                {errors.smtpHost && touched.smtpHost && (
-                  <div className="error">{errors.smtpHost}</div>
-                )}
+                {errors.smtpHost &&
+                  touched.smtpHost &&
+                  typeof errors.smtpHost === 'string' && (
+                    <div className="error">{errors.smtpHost}</div>
+                  )}
               </div>
             </div>
             <div className="form-row">
@@ -302,9 +306,11 @@ const NotificationsEmail: React.FC = () => {
                   inputMode="numeric"
                   className="short"
                 />
-                {errors.smtpPort && touched.smtpPort && (
-                  <div className="error">{errors.smtpPort}</div>
-                )}
+                {errors.smtpPort &&
+                  touched.smtpPort &&
+                  typeof errors.smtpPort === 'string' && (
+                    <div className="error">{errors.smtpPort}</div>
+                  )}
               </div>
             </div>
             <div className="form-row">
@@ -376,9 +382,7 @@ const NotificationsEmail: React.FC = () => {
                 <span className="mr-2">
                   {intl.formatMessage(messages.pgpPrivateKey)}
                 </span>
-                <Badge badgeType="danger">
-                  {intl.formatMessage(globalMessages.advanced)}
-                </Badge>
+                <SettingsBadge badgeType="advanced" />
                 <span className="label-tip">
                   {intl.formatMessage(messages.pgpPrivateKeyTip, {
                     OpenPgpLink: OpenPgpLink,
@@ -396,9 +400,11 @@ const NotificationsEmail: React.FC = () => {
                     className="font-mono text-xs"
                   />
                 </div>
-                {errors.pgpPrivateKey && touched.pgpPrivateKey && (
-                  <div className="error">{errors.pgpPrivateKey}</div>
-                )}
+                {errors.pgpPrivateKey &&
+                  touched.pgpPrivateKey &&
+                  typeof errors.pgpPrivateKey === 'string' && (
+                    <div className="error">{errors.pgpPrivateKey}</div>
+                  )}
               </div>
             </div>
             <div className="form-row">
@@ -406,9 +412,7 @@ const NotificationsEmail: React.FC = () => {
                 <span className="mr-2">
                   {intl.formatMessage(messages.pgpPassword)}
                 </span>
-                <Badge badgeType="danger">
-                  {intl.formatMessage(globalMessages.advanced)}
-                </Badge>
+                <SettingsBadge badgeType="advanced" />
                 <span className="label-tip">
                   {intl.formatMessage(messages.pgpPasswordTip, {
                     OpenPgpLink: OpenPgpLink,
@@ -424,9 +428,11 @@ const NotificationsEmail: React.FC = () => {
                     autoComplete="one-time-code"
                   />
                 </div>
-                {errors.pgpPassword && touched.pgpPassword && (
-                  <div className="error">{errors.pgpPassword}</div>
-                )}
+                {errors.pgpPassword &&
+                  touched.pgpPassword &&
+                  typeof errors.pgpPassword === 'string' && (
+                    <div className="error">{errors.pgpPassword}</div>
+                  )}
               </div>
             </div>
             <div className="actions">
diff --git a/src/components/Settings/Notifications/NotificationsGotify/index.tsx b/src/components/Settings/Notifications/NotificationsGotify/index.tsx
index dd03210c..77fb21b8 100644
--- a/src/components/Settings/Notifications/NotificationsGotify/index.tsx
+++ b/src/components/Settings/Notifications/NotificationsGotify/index.tsx
@@ -1,15 +1,15 @@
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
+import globalMessages from '@app/i18n/globalMessages';
 import { BeakerIcon, SaveIcon } from '@heroicons/react/solid';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import globalMessages from '../../../../i18n/globalMessages';
-import Button from '../../../Common/Button';
-import LoadingSpinner from '../../../Common/LoadingSpinner';
-import NotificationTypeSelector from '../../../NotificationTypeSelector';
 
 const messages = defineMessages({
   agentenabled: 'Enable Agent',
@@ -26,7 +26,7 @@ const messages = defineMessages({
   validationTypes: 'You must select at least one notification type',
 });
 
-const NotificationsGotify: React.FC = () => {
+const NotificationsGotify = () => {
   const intl = useIntl();
   const { addToast, removeToast } = useToasts();
   const [isTesting, setIsTesting] = useState(false);
@@ -173,9 +173,11 @@ const NotificationsGotify: React.FC = () => {
                 <div className="form-input-field">
                   <Field id="url" name="url" type="text" />
                 </div>
-                {errors.url && touched.url && (
-                  <div className="error">{errors.url}</div>
-                )}
+                {errors.url &&
+                  touched.url &&
+                  typeof errors.url === 'string' && (
+                    <div className="error">{errors.url}</div>
+                  )}
               </div>
             </div>
             <div className="form-row">
@@ -187,9 +189,11 @@ const NotificationsGotify: React.FC = () => {
                 <div className="form-input-field">
                   <Field id="token" name="token" type="text" />
                 </div>
-                {errors.token && touched.token && (
-                  <div className="error">{errors.token}</div>
-                )}
+                {errors.token &&
+                  touched.token &&
+                  typeof errors.token === 'string' && (
+                    <div className="error">{errors.token}</div>
+                  )}
               </div>
             </div>
             <NotificationTypeSelector
diff --git a/src/components/Settings/Notifications/NotificationsLunaSea/index.tsx b/src/components/Settings/Notifications/NotificationsLunaSea/index.tsx
index de112798..11636325 100644
--- a/src/components/Settings/Notifications/NotificationsLunaSea/index.tsx
+++ b/src/components/Settings/Notifications/NotificationsLunaSea/index.tsx
@@ -1,15 +1,15 @@
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
+import globalMessages from '@app/i18n/globalMessages';
 import { BeakerIcon, SaveIcon } from '@heroicons/react/outline';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import globalMessages from '../../../../i18n/globalMessages';
-import Button from '../../../Common/Button';
-import LoadingSpinner from '../../../Common/LoadingSpinner';
-import NotificationTypeSelector from '../../../NotificationTypeSelector';
 
 const messages = defineMessages({
   agentenabled: 'Enable Agent',
@@ -27,7 +27,7 @@ const messages = defineMessages({
   validationTypes: 'You must select at least one notification type',
 });
 
-const NotificationsLunaSea: React.FC = () => {
+const NotificationsLunaSea = () => {
   const intl = useIntl();
   const { addToast, removeToast } = useToasts();
   const [isTesting, setIsTesting] = useState(false);
@@ -155,18 +155,16 @@ const NotificationsLunaSea: React.FC = () => {
                 <span className="label-required">*</span>
                 <span className="label-tip">
                   {intl.formatMessage(messages.webhookUrlTip, {
-                    LunaSeaLink: function LunaSeaLink(msg) {
-                      return (
-                        <a
-                          href="https://docs.lunasea.app/lunasea/notifications/overseerr"
-                          className="text-white transition duration-300 hover:underline"
-                          target="_blank"
-                          rel="noreferrer"
-                        >
-                          {msg}
-                        </a>
-                      );
-                    },
+                    LunaSeaLink: (msg: React.ReactNode) => (
+                      <a
+                        href="https://docs.lunasea.app/lunasea/notifications/overseerr"
+                        className="text-white transition duration-300 hover:underline"
+                        target="_blank"
+                        rel="noreferrer"
+                      >
+                        {msg}
+                      </a>
+                    ),
                   })}
                 </span>
               </label>
@@ -179,9 +177,11 @@ const NotificationsLunaSea: React.FC = () => {
                     inputMode="url"
                   />
                 </div>
-                {errors.webhookUrl && touched.webhookUrl && (
-                  <div className="error">{errors.webhookUrl}</div>
-                )}
+                {errors.webhookUrl &&
+                  touched.webhookUrl &&
+                  typeof errors.webhookUrl === 'string' && (
+                    <div className="error">{errors.webhookUrl}</div>
+                  )}
               </div>
             </div>
             <div className="form-row">
@@ -189,9 +189,9 @@ const NotificationsLunaSea: React.FC = () => {
                 {intl.formatMessage(messages.profileName)}
                 <span className="label-tip">
                   {intl.formatMessage(messages.profileNameTip, {
-                    code: function code(msg) {
-                      return <code className="bg-opacity-50">{msg}</code>;
-                    },
+                    code: (msg: React.ReactNode) => (
+                      <code className="bg-opacity-50">{msg}</code>
+                    ),
                   })}
                 </span>
               </label>
diff --git a/src/components/Settings/Notifications/NotificationsPushbullet/index.tsx b/src/components/Settings/Notifications/NotificationsPushbullet/index.tsx
index 1aa631c9..bf6a5956 100644
--- a/src/components/Settings/Notifications/NotificationsPushbullet/index.tsx
+++ b/src/components/Settings/Notifications/NotificationsPushbullet/index.tsx
@@ -1,16 +1,16 @@
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import SensitiveInput from '@app/components/Common/SensitiveInput';
+import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
+import globalMessages from '@app/i18n/globalMessages';
 import { BeakerIcon, SaveIcon } from '@heroicons/react/outline';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import globalMessages from '../../../../i18n/globalMessages';
-import Button from '../../../Common/Button';
-import LoadingSpinner from '../../../Common/LoadingSpinner';
-import SensitiveInput from '../../../Common/SensitiveInput';
-import NotificationTypeSelector from '../../../NotificationTypeSelector';
 
 const messages = defineMessages({
   agentEnabled: 'Enable Agent',
@@ -28,7 +28,7 @@ const messages = defineMessages({
   validationTypes: 'You must select at least one notification type',
 });
 
-const NotificationsPushbullet: React.FC = () => {
+const NotificationsPushbullet = () => {
   const intl = useIntl();
   const { addToast, removeToast } = useToasts();
   const [isTesting, setIsTesting] = useState(false);
@@ -154,20 +154,16 @@ const NotificationsPushbullet: React.FC = () => {
                 <span className="label-required">*</span>
                 <span className="label-tip">
                   {intl.formatMessage(messages.accessTokenTip, {
-                    PushbulletSettingsLink: function PushbulletSettingsLink(
-                      msg
-                    ) {
-                      return (
-                        <a
-                          href="https://www.pushbullet.com/#settings/account"
-                          className="text-white transition duration-300 hover:underline"
-                          target="_blank"
-                          rel="noreferrer"
-                        >
-                          {msg}
-                        </a>
-                      );
-                    },
+                    PushbulletSettingsLink: (msg: React.ReactNode) => (
+                      <a
+                        href="https://www.pushbullet.com/#settings/account"
+                        className="text-white transition duration-300 hover:underline"
+                        target="_blank"
+                        rel="noreferrer"
+                      >
+                        {msg}
+                      </a>
+                    ),
                   })}
                 </span>
               </label>
@@ -180,9 +176,11 @@ const NotificationsPushbullet: React.FC = () => {
                     autoComplete="one-time-code"
                   />
                 </div>
-                {errors.accessToken && touched.accessToken && (
-                  <div className="error">{errors.accessToken}</div>
-                )}
+                {errors.accessToken &&
+                  touched.accessToken &&
+                  typeof errors.accessToken === 'string' && (
+                    <div className="error">{errors.accessToken}</div>
+                  )}
               </div>
             </div>
             <div className="form-row">
diff --git a/src/components/Settings/Notifications/NotificationsPushover/index.tsx b/src/components/Settings/Notifications/NotificationsPushover/index.tsx
index 44229f57..d2e90ac9 100644
--- a/src/components/Settings/Notifications/NotificationsPushover/index.tsx
+++ b/src/components/Settings/Notifications/NotificationsPushover/index.tsx
@@ -1,15 +1,15 @@
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
+import globalMessages from '@app/i18n/globalMessages';
 import { BeakerIcon, SaveIcon } from '@heroicons/react/outline';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import globalMessages from '../../../../i18n/globalMessages';
-import Button from '../../../Common/Button';
-import LoadingSpinner from '../../../Common/LoadingSpinner';
-import NotificationTypeSelector from '../../../NotificationTypeSelector';
 
 const messages = defineMessages({
   agentenabled: 'Enable Agent',
@@ -29,7 +29,7 @@ const messages = defineMessages({
   validationTypes: 'You must select at least one notification type',
 });
 
-const NotificationsPushover: React.FC = () => {
+const NotificationsPushover = () => {
   const intl = useIntl();
   const { addToast, removeToast } = useToasts();
   const [isTesting, setIsTesting] = useState(false);
@@ -172,19 +172,16 @@ const NotificationsPushover: React.FC = () => {
                 <span className="label-required">*</span>
                 <span className="label-tip">
                   {intl.formatMessage(messages.accessTokenTip, {
-                    ApplicationRegistrationLink:
-                      function ApplicationRegistrationLink(msg) {
-                        return (
-                          <a
-                            href="https://pushover.net/api#registration"
-                            className="text-white transition duration-300 hover:underline"
-                            target="_blank"
-                            rel="noreferrer"
-                          >
-                            {msg}
-                          </a>
-                        );
-                      },
+                    ApplicationRegistrationLink: (msg: React.ReactNode) => (
+                      <a
+                        href="https://pushover.net/api#registration"
+                        className="text-white transition duration-300 hover:underline"
+                        target="_blank"
+                        rel="noreferrer"
+                      >
+                        {msg}
+                      </a>
+                    ),
                   })}
                 </span>
               </label>
@@ -192,9 +189,11 @@ const NotificationsPushover: React.FC = () => {
                 <div className="form-input-field">
                   <Field id="accessToken" name="accessToken" type="text" />
                 </div>
-                {errors.accessToken && touched.accessToken && (
-                  <div className="error">{errors.accessToken}</div>
-                )}
+                {errors.accessToken &&
+                  touched.accessToken &&
+                  typeof errors.accessToken === 'string' && (
+                    <div className="error">{errors.accessToken}</div>
+                  )}
               </div>
             </div>
             <div className="form-row">
@@ -203,18 +202,16 @@ const NotificationsPushover: React.FC = () => {
                 <span className="label-required">*</span>
                 <span className="label-tip">
                   {intl.formatMessage(messages.userTokenTip, {
-                    UsersGroupsLink: function UsersGroupsLink(msg) {
-                      return (
-                        <a
-                          href="https://pushover.net/api#identifiers"
-                          className="text-white transition duration-300 hover:underline"
-                          target="_blank"
-                          rel="noreferrer"
-                        >
-                          {msg}
-                        </a>
-                      );
-                    },
+                    UsersGroupsLink: (msg: React.ReactNode) => (
+                      <a
+                        href="https://pushover.net/api#identifiers"
+                        className="text-white transition duration-300 hover:underline"
+                        target="_blank"
+                        rel="noreferrer"
+                      >
+                        {msg}
+                      </a>
+                    ),
                   })}
                 </span>
               </label>
@@ -222,9 +219,11 @@ const NotificationsPushover: React.FC = () => {
                 <div className="form-input-field">
                   <Field id="userToken" name="userToken" type="text" />
                 </div>
-                {errors.userToken && touched.userToken && (
-                  <div className="error">{errors.userToken}</div>
-                )}
+                {errors.userToken &&
+                  touched.userToken &&
+                  typeof errors.userToken === 'string' && (
+                    <div className="error">{errors.userToken}</div>
+                  )}
               </div>
             </div>
             <NotificationTypeSelector
diff --git a/src/components/Settings/Notifications/NotificationsSlack/index.tsx b/src/components/Settings/Notifications/NotificationsSlack/index.tsx
index 8551fdd1..09c63443 100644
--- a/src/components/Settings/Notifications/NotificationsSlack/index.tsx
+++ b/src/components/Settings/Notifications/NotificationsSlack/index.tsx
@@ -1,15 +1,15 @@
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
+import globalMessages from '@app/i18n/globalMessages';
 import { BeakerIcon, SaveIcon } from '@heroicons/react/outline';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import globalMessages from '../../../../i18n/globalMessages';
-import Button from '../../../Common/Button';
-import LoadingSpinner from '../../../Common/LoadingSpinner';
-import NotificationTypeSelector from '../../../NotificationTypeSelector';
 
 const messages = defineMessages({
   agentenabled: 'Enable Agent',
@@ -25,7 +25,7 @@ const messages = defineMessages({
   validationTypes: 'You must select at least one notification type',
 });
 
-const NotificationsSlack: React.FC = () => {
+const NotificationsSlack = () => {
   const intl = useIntl();
   const { addToast, removeToast } = useToasts();
   const [isTesting, setIsTesting] = useState(false);
@@ -150,18 +150,16 @@ const NotificationsSlack: React.FC = () => {
                 <span className="label-required">*</span>
                 <span className="label-tip">
                   {intl.formatMessage(messages.webhookUrlTip, {
-                    WebhookLink: function WebhookLink(msg) {
-                      return (
-                        <a
-                          href="https://my.slack.com/services/new/incoming-webhook/"
-                          className="text-white transition duration-300 hover:underline"
-                          target="_blank"
-                          rel="noreferrer"
-                        >
-                          {msg}
-                        </a>
-                      );
-                    },
+                    WebhookLink: (msg: React.ReactNode) => (
+                      <a
+                        href="https://my.slack.com/services/new/incoming-webhook/"
+                        className="text-white transition duration-300 hover:underline"
+                        target="_blank"
+                        rel="noreferrer"
+                      >
+                        {msg}
+                      </a>
+                    ),
                   })}
                 </span>
               </label>
@@ -174,9 +172,11 @@ const NotificationsSlack: React.FC = () => {
                     inputMode="url"
                   />
                 </div>
-                {errors.webhookUrl && touched.webhookUrl && (
-                  <div className="error">{errors.webhookUrl}</div>
-                )}
+                {errors.webhookUrl &&
+                  touched.webhookUrl &&
+                  typeof errors.webhookUrl === 'string' && (
+                    <div className="error">{errors.webhookUrl}</div>
+                  )}
               </div>
             </div>
             <NotificationTypeSelector
diff --git a/src/components/Settings/Notifications/NotificationsTelegram.tsx b/src/components/Settings/Notifications/NotificationsTelegram.tsx
index f09b2bc9..1959604e 100644
--- a/src/components/Settings/Notifications/NotificationsTelegram.tsx
+++ b/src/components/Settings/Notifications/NotificationsTelegram.tsx
@@ -1,16 +1,16 @@
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import SensitiveInput from '@app/components/Common/SensitiveInput';
+import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
+import globalMessages from '@app/i18n/globalMessages';
 import { BeakerIcon, SaveIcon } from '@heroicons/react/outline';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import globalMessages from '../../../i18n/globalMessages';
-import Button from '../../Common/Button';
-import LoadingSpinner from '../../Common/LoadingSpinner';
-import SensitiveInput from '../../Common/SensitiveInput';
-import NotificationTypeSelector from '../../NotificationTypeSelector';
 
 const messages = defineMessages({
   agentenabled: 'Enable Agent',
@@ -34,7 +34,7 @@ const messages = defineMessages({
   sendSilentlyTip: 'Send notifications with no sound',
 });
 
-const NotificationsTelegram: React.FC = () => {
+const NotificationsTelegram = () => {
   const intl = useIntl();
   const { addToast, removeToast } = useToasts();
   const [isTesting, setIsTesting] = useState(false);
@@ -179,33 +179,29 @@ const NotificationsTelegram: React.FC = () => {
                 <span className="label-required">*</span>
                 <span className="label-tip">
                   {intl.formatMessage(messages.botApiTip, {
-                    CreateBotLink: function CreateBotLink(msg) {
-                      return (
-                        <a
-                          href="https://core.telegram.org/bots#6-botfather"
-                          className="text-white transition duration-300 hover:underline"
-                          target="_blank"
-                          rel="noreferrer"
-                        >
-                          {msg}
-                        </a>
-                      );
-                    },
-                    GetIdBotLink: function GetIdBotLink(msg) {
-                      return (
-                        <a
-                          href="https://telegram.me/get_id_bot"
-                          className="text-white transition duration-300 hover:underline"
-                          target="_blank"
-                          rel="noreferrer"
-                        >
-                          {msg}
-                        </a>
-                      );
-                    },
-                    code: function code(msg) {
-                      return <code className="bg-opacity-50">{msg}</code>;
-                    },
+                    CreateBotLink: (msg: React.ReactNode) => (
+                      <a
+                        href="https://core.telegram.org/bots#6-botfather"
+                        className="text-white transition duration-300 hover:underline"
+                        target="_blank"
+                        rel="noreferrer"
+                      >
+                        {msg}
+                      </a>
+                    ),
+                    GetIdBotLink: (msg: React.ReactNode) => (
+                      <a
+                        href="https://telegram.me/get_id_bot"
+                        className="text-white transition duration-300 hover:underline"
+                        target="_blank"
+                        rel="noreferrer"
+                      >
+                        {msg}
+                      </a>
+                    ),
+                    code: (msg: React.ReactNode) => (
+                      <code className="bg-opacity-50">{msg}</code>
+                    ),
                   })}
                 </span>
               </label>
@@ -218,9 +214,11 @@ const NotificationsTelegram: React.FC = () => {
                     autoComplete="one-time-code"
                   />
                 </div>
-                {errors.botAPI && touched.botAPI && (
-                  <div className="error">{errors.botAPI}</div>
-                )}
+                {errors.botAPI &&
+                  touched.botAPI &&
+                  typeof errors.botAPI === 'string' && (
+                    <div className="error">{errors.botAPI}</div>
+                  )}
               </div>
             </div>
             <div className="form-row">
@@ -234,9 +232,11 @@ const NotificationsTelegram: React.FC = () => {
                 <div className="form-input-field">
                   <Field id="botUsername" name="botUsername" type="text" />
                 </div>
-                {errors.botUsername && touched.botUsername && (
-                  <div className="error">{errors.botUsername}</div>
-                )}
+                {errors.botUsername &&
+                  touched.botUsername &&
+                  typeof errors.botUsername === 'string' && (
+                    <div className="error">{errors.botUsername}</div>
+                  )}
               </div>
             </div>
             <div className="form-row">
@@ -245,20 +245,16 @@ const NotificationsTelegram: React.FC = () => {
                 <span className="label-required">*</span>
                 <span className="label-tip">
                   {intl.formatMessage(messages.chatIdTip, {
-                    GetIdBotLink: function GetIdBotLink(msg) {
-                      return (
-                        <a
-                          href="https://telegram.me/get_id_bot"
-                          target="_blank"
-                          rel="noreferrer"
-                        >
-                          {msg}
-                        </a>
-                      );
-                    },
-                    code: function code(msg) {
-                      return <code>{msg}</code>;
-                    },
+                    GetIdBotLink: (msg: React.ReactNode) => (
+                      <a
+                        href="https://telegram.me/get_id_bot"
+                        target="_blank"
+                        rel="noreferrer"
+                      >
+                        {msg}
+                      </a>
+                    ),
+                    code: (msg: React.ReactNode) => <code>{msg}</code>,
                   })}
                 </span>
               </label>
@@ -266,9 +262,11 @@ const NotificationsTelegram: React.FC = () => {
                 <div className="form-input-field">
                   <Field id="chatId" name="chatId" type="text" />
                 </div>
-                {errors.chatId && touched.chatId && (
-                  <div className="error">{errors.chatId}</div>
-                )}
+                {errors.chatId &&
+                  touched.chatId &&
+                  typeof errors.chatId === 'string' && (
+                    <div className="error">{errors.chatId}</div>
+                  )}
               </div>
             </div>
             <div className="form-row">
diff --git a/src/components/Settings/Notifications/NotificationsWebPush/index.tsx b/src/components/Settings/Notifications/NotificationsWebPush/index.tsx
index 8d4a6c0b..0f56c0c9 100644
--- a/src/components/Settings/Notifications/NotificationsWebPush/index.tsx
+++ b/src/components/Settings/Notifications/NotificationsWebPush/index.tsx
@@ -1,14 +1,14 @@
+import Alert from '@app/components/Common/Alert';
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import globalMessages from '@app/i18n/globalMessages';
 import { BeakerIcon, SaveIcon } from '@heroicons/react/outline';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
-import React, { useEffect, useState } from 'react';
+import { useEffect, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR, { mutate } from 'swr';
-import globalMessages from '../../../../i18n/globalMessages';
-import Alert from '../../../Common/Alert';
-import Button from '../../../Common/Button';
-import LoadingSpinner from '../../../Common/LoadingSpinner';
 
 const messages = defineMessages({
   agentenabled: 'Enable Agent',
@@ -21,7 +21,7 @@ const messages = defineMessages({
     'In order to receive web push notifications, Overseerr must be served over HTTPS.',
 });
 
-const NotificationsWebPush: React.FC = () => {
+const NotificationsWebPush = () => {
   const intl = useIntl();
   const { addToast, removeToast } = useToasts();
   const [isTesting, setIsTesting] = useState(false);
diff --git a/src/components/Settings/Notifications/NotificationsWebhook/index.tsx b/src/components/Settings/Notifications/NotificationsWebhook/index.tsx
index d47bd1b2..375d869c 100644
--- a/src/components/Settings/Notifications/NotificationsWebhook/index.tsx
+++ b/src/components/Settings/Notifications/NotificationsWebhook/index.tsx
@@ -1,20 +1,22 @@
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
+import globalMessages from '@app/i18n/globalMessages';
 import { BeakerIcon, SaveIcon } from '@heroicons/react/outline';
 import { QuestionMarkCircleIcon, RefreshIcon } from '@heroicons/react/solid';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
 import dynamic from 'next/dynamic';
 import Link from 'next/link';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import globalMessages from '../../../../i18n/globalMessages';
-import Button from '../../../Common/Button';
-import LoadingSpinner from '../../../Common/LoadingSpinner';
-import NotificationTypeSelector from '../../../NotificationTypeSelector';
 
-const JSONEditor = dynamic(() => import('../../../JSONEditor'), { ssr: false });
+const JSONEditor = dynamic(() => import('@app/components/JSONEditor'), {
+  ssr: false,
+});
 
 const defaultPayload = {
   notification_type: '{{notification_type}}',
@@ -70,7 +72,7 @@ const messages = defineMessages({
   validationTypes: 'You must select at least one notification type',
 });
 
-const NotificationsWebhook: React.FC = () => {
+const NotificationsWebhook = () => {
   const intl = useIntl();
   const { addToast, removeToast } = useToasts();
   const [isTesting, setIsTesting] = useState(false);
@@ -244,9 +246,11 @@ const NotificationsWebhook: React.FC = () => {
                     inputMode="url"
                   />
                 </div>
-                {errors.webhookUrl && touched.webhookUrl && (
-                  <div className="error">{errors.webhookUrl}</div>
-                )}
+                {errors.webhookUrl &&
+                  touched.webhookUrl &&
+                  typeof errors.webhookUrl === 'string' && (
+                    <div className="error">{errors.webhookUrl}</div>
+                  )}
               </div>
             </div>
             <div className="form-row">
@@ -273,9 +277,11 @@ const NotificationsWebhook: React.FC = () => {
                     onBlur={() => setFieldTouched('jsonPayload')}
                   />
                 </div>
-                {errors.jsonPayload && touched.jsonPayload && (
-                  <div className="error">{errors.jsonPayload}</div>
-                )}
+                {errors.jsonPayload &&
+                  touched.jsonPayload &&
+                  typeof errors.jsonPayload === 'string' && (
+                    <div className="error">{errors.jsonPayload}</div>
+                  )}
                 <div className="mt-2">
                   <Button
                     buttonSize="sm"
diff --git a/src/components/Settings/RadarrModal/index.tsx b/src/components/Settings/RadarrModal/index.tsx
index fa1d8dec..840f99a9 100644
--- a/src/components/Settings/RadarrModal/index.tsx
+++ b/src/components/Settings/RadarrModal/index.tsx
@@ -1,16 +1,15 @@
-import { PencilIcon, PlusIcon } from '@heroicons/react/solid';
+import Modal from '@app/components/Common/Modal';
+import SensitiveInput from '@app/components/Common/SensitiveInput';
+import globalMessages from '@app/i18n/globalMessages';
+import { Transition } from '@headlessui/react';
+import type { RadarrSettings } from '@server/lib/settings';
 import axios from 'axios';
 import { Field, Formik } from 'formik';
-import React, { useCallback, useEffect, useRef, useState } from 'react';
+import { useCallback, useEffect, useRef, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import Select from 'react-select';
 import { useToasts } from 'react-toast-notifications';
 import * as Yup from 'yup';
-import type { RadarrSettings } from '../../../../server/lib/settings';
-import globalMessages from '../../../i18n/globalMessages';
-import Modal from '../../Common/Modal';
-import SensitiveInput from '../../Common/SensitiveInput';
-import Transition from '../../Transition';
 
 type OptionType = {
   value: number;
@@ -91,11 +90,7 @@ interface RadarrModalProps {
   onSave: () => void;
 }
 
-const RadarrModal: React.FC<RadarrModalProps> = ({
-  onClose,
-  radarr,
-  onSave,
-}) => {
+const RadarrModal = ({ onClose, radarr, onSave }: RadarrModalProps) => {
   const intl = useIntl();
   const initialLoad = useRef(false);
   const { addToast } = useToasts();
@@ -216,6 +211,7 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
 
   return (
     <Transition
+      as="div"
       appear
       show
       enter="transition ease-in-out duration-300 transform opacity-0"
@@ -343,7 +339,6 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
                       values.is4k ? messages.edit4kradarr : messages.editradarr
                     )
               }
-              iconSvg={!radarr ? <PlusIcon /> : <PencilIcon />}
             >
               <div className="mb-6">
                 <div className="form-row">
@@ -383,9 +378,11 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
                         }}
                       />
                     </div>
-                    {errors.name && touched.name && (
-                      <div className="error">{errors.name}</div>
-                    )}
+                    {errors.name &&
+                      touched.name &&
+                      typeof errors.name === 'string' && (
+                        <div className="error">{errors.name}</div>
+                      )}
                   </div>
                 </div>
                 <div className="form-row">
@@ -410,9 +407,11 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
                         className="rounded-r-only"
                       />
                     </div>
-                    {errors.hostname && touched.hostname && (
-                      <div className="error">{errors.hostname}</div>
-                    )}
+                    {errors.hostname &&
+                      touched.hostname &&
+                      typeof errors.hostname === 'string' && (
+                        <div className="error">{errors.hostname}</div>
+                      )}
                   </div>
                 </div>
                 <div className="form-row">
@@ -432,9 +431,11 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
                         setFieldValue('port', e.target.value);
                       }}
                     />
-                    {errors.port && touched.port && (
-                      <div className="error">{errors.port}</div>
-                    )}
+                    {errors.port &&
+                      touched.port &&
+                      typeof errors.port === 'string' && (
+                        <div className="error">{errors.port}</div>
+                      )}
                   </div>
                 </div>
                 <div className="form-row">
@@ -471,9 +472,11 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
                         }}
                       />
                     </div>
-                    {errors.apiKey && touched.apiKey && (
-                      <div className="error">{errors.apiKey}</div>
-                    )}
+                    {errors.apiKey &&
+                      touched.apiKey &&
+                      typeof errors.apiKey === 'string' && (
+                        <div className="error">{errors.apiKey}</div>
+                      )}
                   </div>
                 </div>
                 <div className="form-row">
@@ -493,9 +496,11 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
                         }}
                       />
                     </div>
-                    {errors.baseUrl && touched.baseUrl && (
-                      <div className="error">{errors.baseUrl}</div>
-                    )}
+                    {errors.baseUrl &&
+                      touched.baseUrl &&
+                      typeof errors.baseUrl === 'string' && (
+                        <div className="error">{errors.baseUrl}</div>
+                      )}
                   </div>
                 </div>
                 <div className="form-row">
@@ -531,9 +536,11 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
                           ))}
                       </Field>
                     </div>
-                    {errors.activeProfileId && touched.activeProfileId && (
-                      <div className="error">{errors.activeProfileId}</div>
-                    )}
+                    {errors.activeProfileId &&
+                      touched.activeProfileId &&
+                      typeof errors.activeProfileId === 'string' && (
+                        <div className="error">{errors.activeProfileId}</div>
+                      )}
                   </div>
                 </div>
                 <div className="form-row">
@@ -567,9 +574,11 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
                           ))}
                       </Field>
                     </div>
-                    {errors.rootFolder && touched.rootFolder && (
-                      <div className="error">{errors.rootFolder}</div>
-                    )}
+                    {errors.rootFolder &&
+                      touched.rootFolder &&
+                      typeof errors.rootFolder === 'string' && (
+                        <div className="error">{errors.rootFolder}</div>
+                      )}
                   </div>
                 </div>
                 <div className="form-row">
@@ -673,9 +682,11 @@ const RadarrModal: React.FC<RadarrModalProps> = ({
                         inputMode="url"
                       />
                     </div>
-                    {errors.externalUrl && touched.externalUrl && (
-                      <div className="error">{errors.externalUrl}</div>
-                    )}
+                    {errors.externalUrl &&
+                      touched.externalUrl &&
+                      typeof errors.externalUrl === 'string' && (
+                        <div className="error">{errors.externalUrl}</div>
+                      )}
                   </div>
                 </div>
                 <div className="form-row">
diff --git a/src/components/Settings/SettingsAbout/Releases/index.tsx b/src/components/Settings/SettingsAbout/Releases/index.tsx
index 81db42e5..601d4f44 100644
--- a/src/components/Settings/SettingsAbout/Releases/index.tsx
+++ b/src/components/Settings/SettingsAbout/Releases/index.tsx
@@ -1,14 +1,21 @@
+import Badge from '@app/components/Common/Badge';
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import Modal from '@app/components/Common/Modal';
+import globalMessages from '@app/i18n/globalMessages';
+import { Transition } from '@headlessui/react';
 import { DocumentTextIcon } from '@heroicons/react/outline';
-import React, { useState } from 'react';
+import dynamic from 'next/dynamic';
+import { Fragment, useState } from 'react';
 import { defineMessages, FormattedRelativeTime, useIntl } from 'react-intl';
-import ReactMarkdown from 'react-markdown';
 import useSWR from 'swr';
-import globalMessages from '../../../../i18n/globalMessages';
-import Badge from '../../../Common/Badge';
-import Button from '../../../Common/Button';
-import LoadingSpinner from '../../../Common/LoadingSpinner';
-import Modal from '../../../Common/Modal';
-import Transition from '../../../Transition';
+
+// dyanmic is having trouble extracting the props for react-markdown here so we are just ignoring it since its really
+// only children we are using
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+const ReactMarkdown = dynamic<any>(() => import('react-markdown'), {
+  ssr: false,
+});
 
 const messages = defineMessages({
   releases: 'Releases',
@@ -48,17 +55,14 @@ interface ReleaseProps {
   currentVersion: string;
 }
 
-const Release: React.FC<ReleaseProps> = ({
-  currentVersion,
-  release,
-  isLatest,
-}) => {
+const Release = ({ currentVersion, release, isLatest }: ReleaseProps) => {
   const intl = useIntl();
   const [isModalOpen, setModalOpen] = useState(false);
 
   return (
     <div className="flex w-full flex-col space-y-3 rounded-md bg-gray-800 px-4 py-2 shadow-md ring-1 ring-gray-700 sm:flex-row sm:space-y-0 sm:space-x-3">
       <Transition
+        as={Fragment}
         enter="opacity-0 transition duration-300"
         enterFrom="opacity-0"
         enterTo="opacity-100"
@@ -69,7 +73,6 @@ const Release: React.FC<ReleaseProps> = ({
       >
         <Modal
           onCancel={() => setModalOpen(false)}
-          iconSvg={<DocumentTextIcon />}
           title={intl.formatMessage(messages.versionChangelog, {
             version: release.name,
           })}
@@ -120,7 +123,7 @@ interface ReleasesProps {
   currentVersion: string;
 }
 
-const Releases: React.FC<ReleasesProps> = ({ currentVersion }) => {
+const Releases = ({ currentVersion }: ReleasesProps) => {
   const intl = useIntl();
   const { data, error } = useSWR<GitHubRelease[]>(REPO_RELEASE_API);
 
diff --git a/src/components/Settings/SettingsAbout/index.tsx b/src/components/Settings/SettingsAbout/index.tsx
index 2b638108..1d3f0566 100644
--- a/src/components/Settings/SettingsAbout/index.tsx
+++ b/src/components/Settings/SettingsAbout/index.tsx
@@ -1,19 +1,18 @@
+import Alert from '@app/components/Common/Alert';
+import Badge from '@app/components/Common/Badge';
+import List from '@app/components/Common/List';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import Releases from '@app/components/Settings/SettingsAbout/Releases';
+import globalMessages from '@app/i18n/globalMessages';
+import Error from '@app/pages/_error';
 import { InformationCircleIcon } from '@heroicons/react/solid';
-import React from 'react';
-import { defineMessages, useIntl } from 'react-intl';
-import useSWR from 'swr';
-import {
+import type {
   SettingsAboutResponse,
   StatusResponse,
-} from '../../../../server/interfaces/api/settingsInterfaces';
-import globalMessages from '../../../i18n/globalMessages';
-import Error from '../../../pages/_error';
-import Alert from '../../Common/Alert';
-import Badge from '../../Common/Badge';
-import List from '../../Common/List';
-import LoadingSpinner from '../../Common/LoadingSpinner';
-import PageTitle from '../../Common/PageTitle';
-import Releases from './Releases';
+} from '@server/interfaces/api/settingsInterfaces';
+import { defineMessages, useIntl } from 'react-intl';
+import useSWR from 'swr';
 
 const messages = defineMessages({
   about: 'About',
@@ -37,7 +36,7 @@ const messages = defineMessages({
     'You are running the <code>develop</code> branch of Overseerr, which is only recommended for those contributing to development or assisting with bleeding-edge testing.',
 });
 
-const SettingsAbout: React.FC = () => {
+const SettingsAbout = () => {
   const intl = useIntl();
   const { data, error } = useSWR<SettingsAboutResponse>(
     '/api/v1/settings/about'
@@ -61,19 +60,19 @@ const SettingsAbout: React.FC = () => {
           intl.formatMessage(globalMessages.settings),
         ]}
       />
-      <div className="mt-6 rounded-md bg-indigo-700 p-4">
+      <div className="mt-6 rounded-md border border-indigo-500 bg-indigo-400 bg-opacity-20 p-4 backdrop-blur">
         <div className="flex">
           <div className="flex-shrink-0">
-            <InformationCircleIcon className="h-5 w-5 text-white" />
+            <InformationCircleIcon className="h-5 w-5 text-gray-100" />
           </div>
           <div className="ml-3 flex-1 md:flex md:justify-between">
-            <p className="text-sm leading-5 text-white">
+            <p className="text-sm leading-5 text-gray-100">
               {intl.formatMessage(messages.betawarning)}
             </p>
             <p className="mt-3 text-sm leading-5 md:mt-0 md:ml-6">
               <a
                 href="http://github.com/sct/overseerr"
-                className="whitespace-nowrap font-medium text-indigo-100 transition duration-150 ease-in-out hover:text-white"
+                className="whitespace-nowrap font-medium text-gray-100 transition duration-150 ease-in-out hover:text-white"
                 target="_blank"
                 rel="noreferrer"
               >
@@ -88,9 +87,9 @@ const SettingsAbout: React.FC = () => {
           {data.version.startsWith('develop-') && (
             <Alert
               title={intl.formatMessage(messages.runningDevelop, {
-                code: function code(msg) {
-                  return <code className="bg-opacity-50">{msg}</code>;
-                },
+                code: (msg: React.ReactNode) => (
+                  <code className="bg-opacity-50">{msg}</code>
+                ),
               })}
             />
           )}
diff --git a/src/components/Settings/SettingsBadge.tsx b/src/components/Settings/SettingsBadge.tsx
new file mode 100644
index 00000000..c4f12ef3
--- /dev/null
+++ b/src/components/Settings/SettingsBadge.tsx
@@ -0,0 +1,54 @@
+import Badge from '@app/components/Common/Badge';
+import Tooltip from '@app/components/Common/Tooltip';
+import globalMessages from '@app/i18n/globalMessages';
+import { defineMessages, useIntl } from 'react-intl';
+
+const messages = defineMessages({
+  advancedTooltip:
+    'Incorrectly configuring this setting may result in broken functionality',
+  experimentalTooltip:
+    'Enabling this setting may result in unexpected application behavior',
+  restartrequiredTooltip:
+    'Overseerr must be restarted for changes to this setting to take effect',
+});
+
+const SettingsBadge = ({
+  badgeType,
+  className,
+}: {
+  badgeType: 'advanced' | 'experimental' | 'restartRequired';
+  className?: string;
+}) => {
+  const intl = useIntl();
+
+  switch (badgeType) {
+    case 'advanced':
+      return (
+        <Tooltip content={intl.formatMessage(messages.advancedTooltip)}>
+          <Badge badgeType="danger" className={className}>
+            {intl.formatMessage(globalMessages.advanced)}
+          </Badge>
+        </Tooltip>
+      );
+    case 'experimental':
+      return (
+        <Tooltip content={intl.formatMessage(messages.experimentalTooltip)}>
+          <Badge badgeType="warning">
+            {intl.formatMessage(globalMessages.experimental)}
+          </Badge>
+        </Tooltip>
+      );
+    case 'restartRequired':
+      return (
+        <Tooltip content={intl.formatMessage(messages.restartrequiredTooltip)}>
+          <Badge badgeType="primary" className={className}>
+            {intl.formatMessage(globalMessages.restartRequired)}
+          </Badge>
+        </Tooltip>
+      );
+    default:
+      return null;
+  }
+};
+
+export default SettingsBadge;
diff --git a/src/components/Settings/SettingsJobsCache/index.tsx b/src/components/Settings/SettingsJobsCache/index.tsx
index 015747af..d9b31bd0 100644
--- a/src/components/Settings/SettingsJobsCache/index.tsx
+++ b/src/components/Settings/SettingsJobsCache/index.tsx
@@ -1,27 +1,25 @@
+import Spinner from '@app/assets/spinner.svg';
+import Badge from '@app/components/Common/Badge';
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import Modal from '@app/components/Common/Modal';
+import PageTitle from '@app/components/Common/PageTitle';
+import Table from '@app/components/Common/Table';
+import useLocale from '@app/hooks/useLocale';
+import globalMessages from '@app/i18n/globalMessages';
+import { formatBytes } from '@app/utils/numberHelpers';
+import { Transition } from '@headlessui/react';
 import { PlayIcon, StopIcon, TrashIcon } from '@heroicons/react/outline';
 import { PencilIcon } from '@heroicons/react/solid';
+import type { CacheItem } from '@server/interfaces/api/settingsInterfaces';
+import type { JobId } from '@server/lib/settings';
 import axios from 'axios';
-import React, { useState } from 'react';
-import {
-  defineMessages,
-  FormattedRelativeTime,
-  MessageDescriptor,
-  useIntl,
-} from 'react-intl';
+import cronstrue from 'cronstrue/i18n';
+import { Fragment, useReducer, useState } from 'react';
+import type { MessageDescriptor } from 'react-intl';
+import { defineMessages, FormattedRelativeTime, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
-import { CacheItem } from '../../../../server/interfaces/api/settingsInterfaces';
-import { JobId } from '../../../../server/lib/settings';
-import Spinner from '../../../assets/spinner.svg';
-import globalMessages from '../../../i18n/globalMessages';
-import { formatBytes } from '../../../utils/numberHelpers';
-import Badge from '../../Common/Badge';
-import Button from '../../Common/Button';
-import LoadingSpinner from '../../Common/LoadingSpinner';
-import Modal from '../../Common/Modal';
-import PageTitle from '../../Common/PageTitle';
-import Table from '../../Common/Table';
-import Transition from '../../Transition';
 
 const messages: { [messageName: string]: MessageDescriptor } = defineMessages({
   jobsandcache: 'Jobs & Cache',
@@ -51,6 +49,7 @@ const messages: { [messageName: string]: MessageDescriptor } = defineMessages({
   unknownJob: 'Unknown Job',
   'plex-recently-added-scan': 'Plex Recently Added Scan',
   'plex-full-scan': 'Plex Full Library Scan',
+  'plex-watchlist-sync': 'Plex Watchlist Sync',
   'radarr-scan': 'Radarr Scan',
   'sonarr-scan': 'Sonarr Scan',
   'download-sync': 'Download Sync',
@@ -58,7 +57,8 @@ const messages: { [messageName: string]: MessageDescriptor } = defineMessages({
   editJobSchedule: 'Modify Job',
   jobScheduleEditSaved: 'Job edited successfully!',
   jobScheduleEditFailed: 'Something went wrong while saving the job.',
-  editJobSchedulePrompt: 'Frequency',
+  editJobScheduleCurrent: 'Current Frequency',
+  editJobSchedulePrompt: 'New Frequency',
   editJobScheduleSelectorHours:
     'Every {jobScheduleHours, plural, one {hour} other {{jobScheduleHours} hours}}',
   editJobScheduleSelectorMinutes:
@@ -70,12 +70,56 @@ interface Job {
   name: string;
   type: 'process' | 'command';
   interval: 'short' | 'long' | 'fixed';
+  cronSchedule: string;
   nextExecutionTime: string;
   running: boolean;
 }
 
-const SettingsJobs: React.FC = () => {
+type JobModalState = {
+  isOpen?: boolean;
+  job?: Job;
+  scheduleHours: number;
+  scheduleMinutes: number;
+};
+
+type JobModalAction =
+  | { type: 'set'; hours?: number; minutes?: number }
+  | {
+      type: 'close';
+    }
+  | { type: 'open'; job?: Job };
+
+const jobModalReducer = (
+  state: JobModalState,
+  action: JobModalAction
+): JobModalState => {
+  switch (action.type) {
+    case 'close':
+      return {
+        ...state,
+        isOpen: false,
+      };
+
+    case 'open':
+      return {
+        isOpen: true,
+        job: action.job,
+        scheduleHours: 1,
+        scheduleMinutes: 5,
+      };
+
+    case 'set':
+      return {
+        ...state,
+        scheduleHours: action.hours ?? state.scheduleHours,
+        scheduleMinutes: action.minutes ?? state.scheduleMinutes,
+      };
+  }
+};
+
+const SettingsJobs = () => {
   const intl = useIntl();
+  const { locale } = useLocale();
   const { addToast } = useToasts();
   const {
     data,
@@ -91,15 +135,12 @@ const SettingsJobs: React.FC = () => {
     }
   );
 
-  const [jobEditModal, setJobEditModal] = useState<{
-    isOpen: boolean;
-    job?: Job;
-  }>({
+  const [jobModalState, dispatch] = useReducer(jobModalReducer, {
     isOpen: false,
+    scheduleHours: 1,
+    scheduleMinutes: 5,
   });
   const [isSaving, setIsSaving] = useState(false);
-  const [jobScheduleMinutes, setJobScheduleMinutes] = useState(5);
-  const [jobScheduleHours, setJobScheduleHours] = useState(1);
 
   if (!data && !error) {
     return <LoadingSpinner />;
@@ -149,10 +190,10 @@ const SettingsJobs: React.FC = () => {
     const jobScheduleCron = ['0', '0', '*', '*', '*', '*'];
 
     try {
-      if (jobEditModal.job?.interval === 'short') {
-        jobScheduleCron[1] = `*/${jobScheduleMinutes}`;
-      } else if (jobEditModal.job?.interval === 'long') {
-        jobScheduleCron[2] = `*/${jobScheduleHours}`;
+      if (jobModalState.job?.interval === 'short') {
+        jobScheduleCron[1] = `*/${jobModalState.scheduleMinutes}`;
+      } else if (jobModalState.job?.interval === 'long') {
+        jobScheduleCron[2] = `*/${jobModalState.scheduleHours}`;
       } else {
         // jobs with interval: fixed should not be editable
         throw new Error();
@@ -160,16 +201,18 @@ const SettingsJobs: React.FC = () => {
 
       setIsSaving(true);
       await axios.post(
-        `/api/v1/settings/jobs/${jobEditModal.job?.id}/schedule`,
+        `/api/v1/settings/jobs/${jobModalState.job.id}/schedule`,
         {
           schedule: jobScheduleCron.join(' '),
         }
       );
+
       addToast(intl.formatMessage(messages.jobScheduleEditSaved), {
         appearance: 'success',
         autoDismiss: true,
       });
-      setJobEditModal({ isOpen: false });
+
+      dispatch({ type: 'close' });
       revalidate();
     } catch (e) {
       addToast(intl.formatMessage(messages.jobScheduleEditFailed), {
@@ -190,13 +233,14 @@ const SettingsJobs: React.FC = () => {
         ]}
       />
       <Transition
+        as={Fragment}
         enter="opacity-0 transition duration-300"
         enterFrom="opacity-0"
         enterTo="opacity-100"
         leave="opacity-100 transition duration-300"
         leaveFrom="opacity-100"
         leaveTo="opacity-0"
-        show={jobEditModal.isOpen}
+        show={jobModalState.isOpen}
       >
         <Modal
           title={intl.formatMessage(messages.editJobSchedule)}
@@ -205,25 +249,43 @@ const SettingsJobs: React.FC = () => {
               ? intl.formatMessage(globalMessages.saving)
               : intl.formatMessage(globalMessages.save)
           }
-          iconSvg={<PencilIcon />}
-          onCancel={() => setJobEditModal({ isOpen: false })}
+          onCancel={() => dispatch({ type: 'close' })}
           okDisabled={isSaving}
           onOk={() => scheduleJob()}
         >
           <div className="section">
-            <form>
-              <div className="form-row pb-6">
+            <form className="mb-6">
+              <div className="form-row">
+                <label className="text-label">
+                  {intl.formatMessage(messages.editJobScheduleCurrent)}
+                </label>
+                <div className="form-input-area mt-2 mb-1">
+                  <div>
+                    {jobModalState.job &&
+                      cronstrue.toString(jobModalState.job.cronSchedule, {
+                        locale,
+                      })}
+                  </div>
+                  <div className="text-sm text-gray-500">
+                    {jobModalState.job?.cronSchedule}
+                  </div>
+                </div>
+              </div>
+              <div className="form-row">
                 <label htmlFor="jobSchedule" className="text-label">
                   {intl.formatMessage(messages.editJobSchedulePrompt)}
                 </label>
                 <div className="form-input-area">
-                  {jobEditModal.job?.interval === 'short' ? (
+                  {jobModalState.job?.interval === 'short' ? (
                     <select
                       name="jobScheduleMinutes"
                       className="inline"
-                      value={jobScheduleMinutes}
+                      value={jobModalState.scheduleMinutes}
                       onChange={(e) =>
-                        setJobScheduleMinutes(Number(e.target.value))
+                        dispatch({
+                          type: 'set',
+                          minutes: Number(e.target.value),
+                        })
                       }
                     >
                       {[5, 10, 15, 20, 30, 60].map((v) => (
@@ -241,9 +303,12 @@ const SettingsJobs: React.FC = () => {
                     <select
                       name="jobScheduleHours"
                       className="inline"
-                      value={jobScheduleHours}
+                      value={jobModalState.scheduleHours}
                       onChange={(e) =>
-                        setJobScheduleHours(Number(e.target.value))
+                        dispatch({
+                          type: 'set',
+                          hours: Number(e.target.value),
+                        })
                       }
                     >
                       {[1, 2, 3, 4, 6, 8, 12, 24, 48, 72].map((v) => (
@@ -322,12 +387,10 @@ const SettingsJobs: React.FC = () => {
                     <Button
                       className="mr-2"
                       buttonType="warning"
-                      onClick={() =>
-                        setJobEditModal({ isOpen: true, job: job })
-                      }
+                      onClick={() => dispatch({ type: 'open', job })}
                     >
                       <PencilIcon />
-                      {intl.formatMessage(globalMessages.edit)}
+                      <span>{intl.formatMessage(globalMessages.edit)}</span>
                     </Button>
                   )}
                   {job.running ? (
@@ -337,7 +400,7 @@ const SettingsJobs: React.FC = () => {
                     </Button>
                   ) : (
                     <Button buttonType="primary" onClick={() => runJob(job)}>
-                      <PlayIcon className="mr-1 h-5 w-5" />
+                      <PlayIcon />
                       <span>{intl.formatMessage(messages.runnow)}</span>
                     </Button>
                   )}
diff --git a/src/components/Settings/SettingsLayout.tsx b/src/components/Settings/SettingsLayout.tsx
index 65f4d548..8d712fd1 100644
--- a/src/components/Settings/SettingsLayout.tsx
+++ b/src/components/Settings/SettingsLayout.tsx
@@ -1,8 +1,8 @@
-import React from 'react';
+import PageTitle from '@app/components/Common/PageTitle';
+import type { SettingsRoute } from '@app/components/Common/SettingsTabs';
+import SettingsTabs from '@app/components/Common/SettingsTabs';
+import globalMessages from '@app/i18n/globalMessages';
 import { defineMessages, useIntl } from 'react-intl';
-import globalMessages from '../../i18n/globalMessages';
-import PageTitle from '../Common/PageTitle';
-import SettingsTabs, { SettingsRoute } from '../Common/SettingsTabs';
 
 const messages = defineMessages({
   menuGeneralSettings: 'General',
@@ -15,7 +15,11 @@ const messages = defineMessages({
   menuAbout: 'About',
 });
 
-const SettingsLayout: React.FC = ({ children }) => {
+type SettingsLayoutProps = {
+  children: React.ReactNode;
+};
+
+const SettingsLayout = ({ children }: SettingsLayoutProps) => {
   const intl = useIntl();
 
   const settingsRoutes: SettingsRoute[] = [
diff --git a/src/components/Settings/SettingsLogs/index.tsx b/src/components/Settings/SettingsLogs/index.tsx
index 0a607e0a..fbf5d5e0 100644
--- a/src/components/Settings/SettingsLogs/index.tsx
+++ b/src/components/Settings/SettingsLogs/index.tsx
@@ -1,3 +1,15 @@
+import Badge from '@app/components/Common/Badge';
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import Modal from '@app/components/Common/Modal';
+import PageTitle from '@app/components/Common/PageTitle';
+import Table from '@app/components/Common/Table';
+import Tooltip from '@app/components/Common/Tooltip';
+import useDebouncedState from '@app/hooks/useDebouncedState';
+import { useUpdateQueryParams } from '@app/hooks/useUpdateQueryParams';
+import globalMessages from '@app/i18n/globalMessages';
+import Error from '@app/pages/_error';
+import { Transition } from '@headlessui/react';
 import {
   ChevronLeftIcon,
   ChevronRightIcon,
@@ -6,27 +18,18 @@ import {
   FilterIcon,
   PauseIcon,
   PlayIcon,
+  SearchIcon,
 } from '@heroicons/react/solid';
+import type {
+  LogMessage,
+  LogsResultsResponse,
+} from '@server/interfaces/api/settingsInterfaces';
 import copy from 'copy-to-clipboard';
 import { useRouter } from 'next/router';
-import React, { useEffect, useState } from 'react';
+import { Fragment, useEffect, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
-import {
-  LogMessage,
-  LogsResultsResponse,
-} from '../../../../server/interfaces/api/settingsInterfaces';
-import { useUpdateQueryParams } from '../../../hooks/useUpdateQueryParams';
-import globalMessages from '../../../i18n/globalMessages';
-import Error from '../../../pages/_error';
-import Badge from '../../Common/Badge';
-import Button from '../../Common/Button';
-import LoadingSpinner from '../../Common/LoadingSpinner';
-import Modal from '../../Common/Modal';
-import PageTitle from '../../Common/PageTitle';
-import Table from '../../Common/Table';
-import Transition from '../../Transition';
 
 const messages = defineMessages({
   logs: 'Logs',
@@ -47,18 +50,24 @@ const messages = defineMessages({
   logDetails: 'Log Details',
   extraData: 'Additional Data',
   copiedLogMessage: 'Copied log message to clipboard.',
+  viewdetails: 'View Details',
 });
 
 type Filter = 'debug' | 'info' | 'warn' | 'error';
 
-const SettingsLogs: React.FC = () => {
+const SettingsLogs = () => {
   const router = useRouter();
   const intl = useIntl();
   const { addToast } = useToasts();
   const [currentFilter, setCurrentFilter] = useState<Filter>('debug');
   const [currentPageSize, setCurrentPageSize] = useState(25);
+  const [searchFilter, debouncedSearchFilter, setSearchFilter] =
+    useDebouncedState('');
   const [refreshInterval, setRefreshInterval] = useState(5000);
-  const [activeLog, setActiveLog] = useState<LogMessage | null>(null);
+  const [activeLog, setActiveLog] = useState<{
+    isOpen: boolean;
+    log?: LogMessage;
+  }>({ isOpen: false });
 
   const page = router.query.page ? Number(router.query.page) : 1;
   const pageIndex = page - 1;
@@ -71,7 +80,9 @@ const SettingsLogs: React.FC = () => {
   const { data, error } = useSWR<LogsResultsResponse>(
     `/api/v1/settings/logs?take=${currentPageSize}&skip=${
       pageIndex * currentPageSize
-    }&filter=${currentFilter}`,
+    }&filter=${currentFilter}${
+      debouncedSearchFilter ? `&search=${debouncedSearchFilter}` : ''
+    }`,
     {
       refreshInterval: refreshInterval,
       revalidateOnFocus: false,
@@ -113,15 +124,13 @@ const SettingsLogs: React.FC = () => {
     });
   };
 
-  if (!data && !error) {
-    return <LoadingSpinner />;
-  }
-
-  if (!data) {
+  // check if there's no data and no errors in the table
+  // so as to show a spinner inside the table and not refresh the whole component
+  if (!data && error) {
     return <Error statusCode={500} />;
   }
 
-  const hasNextPage = data.pageInfo.pages > pageIndex + 1;
+  const hasNextPage = data?.pageInfo.pages ?? 0 > pageIndex + 1;
   const hasPrevPage = pageIndex > 0;
 
   return (
@@ -133,6 +142,7 @@ const SettingsLogs: React.FC = () => {
         ]}
       />
       <Transition
+        as={Fragment}
         enter="opacity-0 transition duration-300"
         enterFrom="opacity-0"
         enterTo="opacity-100"
@@ -140,14 +150,15 @@ const SettingsLogs: React.FC = () => {
         leaveFrom="opacity-100"
         leaveTo="opacity-0"
         appear
-        show={!!activeLog}
+        show={activeLog.isOpen}
       >
         <Modal
           title={intl.formatMessage(messages.logDetails)}
-          iconSvg={<DocumentSearchIcon />}
-          onCancel={() => setActiveLog(null)}
+          onCancel={() => setActiveLog({ log: activeLog.log, isOpen: false })}
           cancelText={intl.formatMessage(globalMessages.close)}
-          onOk={() => (activeLog ? copyLogString(activeLog) : undefined)}
+          onOk={() =>
+            activeLog.log ? copyLogString(activeLog.log) : undefined
+          }
           okText={intl.formatMessage(messages.copyToClipboard)}
           okButtonType="primary"
         >
@@ -159,7 +170,7 @@ const SettingsLogs: React.FC = () => {
                 </div>
                 <div className="mb-1 text-sm font-medium leading-5 text-gray-400 sm:mt-2">
                   <div className="flex max-w-lg items-center">
-                    {intl.formatDate(activeLog.timestamp, {
+                    {intl.formatDate(activeLog.log?.timestamp, {
                       year: 'numeric',
                       month: 'short',
                       day: '2-digit',
@@ -178,16 +189,16 @@ const SettingsLogs: React.FC = () => {
                   <div className="flex max-w-lg items-center">
                     <Badge
                       badgeType={
-                        activeLog.level === 'error'
+                        activeLog.log?.level === 'error'
                           ? 'danger'
-                          : activeLog.level === 'warn'
+                          : activeLog.log?.level === 'warn'
                           ? 'warning'
-                          : activeLog.level === 'info'
+                          : activeLog.log?.level === 'info'
                           ? 'success'
                           : 'default'
                       }
                     >
-                      {activeLog.level.toUpperCase()}
+                      {activeLog.log?.level.toUpperCase()}
                     </Badge>
                   </div>
                 </div>
@@ -198,7 +209,7 @@ const SettingsLogs: React.FC = () => {
                 </div>
                 <div className="mb-1 text-sm font-medium leading-5 text-gray-400 sm:mt-2">
                   <div className="flex max-w-lg items-center">
-                    {activeLog.label}
+                    {activeLog.log?.label}
                   </div>
                 </div>
               </div>
@@ -208,18 +219,18 @@ const SettingsLogs: React.FC = () => {
                 </div>
                 <div className="col-span-2 mb-1 text-sm font-medium leading-5 text-gray-400 sm:mt-2">
                   <div className="flex max-w-lg items-center">
-                    {activeLog.message}
+                    {activeLog.log?.message}
                   </div>
                 </div>
               </div>
-              {activeLog.data && (
+              {activeLog.log?.data && (
                 <div className="form-row">
                   <div className="text-label">
                     {intl.formatMessage(messages.extraData)}
                   </div>
                   <div className="col-span-2 mb-1 text-sm font-medium leading-5 text-gray-400 sm:mt-2">
                     <code className="block max-h-64 w-full overflow-auto whitespace-pre bg-gray-800 px-6 py-4 ring-1 ring-gray-700">
-                      {JSON.stringify(activeLog.data, null, ' ')}
+                      {JSON.stringify(activeLog.log?.data, null, ' ')}
                     </code>
                   </div>
                 </div>
@@ -232,16 +243,27 @@ const SettingsLogs: React.FC = () => {
         <h3 className="heading">{intl.formatMessage(messages.logs)}</h3>
         <p className="description">
           {intl.formatMessage(messages.logsDescription, {
-            code: function code(msg) {
-              return <code className="bg-opacity-50">{msg}</code>;
-            },
+            code: (msg: React.ReactNode) => (
+              <code className="bg-opacity-50">{msg}</code>
+            ),
             appDataPath: appData ? appData.appDataPath : '/app/config',
           })}
         </p>
-        <div className="mt-2 flex flex-grow flex-row sm:flex-grow-0 sm:justify-end">
+        <div className="mt-2 flex flex-grow flex-col sm:flex-grow-0 sm:flex-row sm:justify-end">
+          <div className="mb-2 flex flex-grow sm:mb-0 sm:mr-2 md:flex-grow-0">
+            <span className="inline-flex cursor-default items-center rounded-l-md border border-r-0 border-gray-500 bg-gray-800 px-3 text-sm text-gray-100">
+              <SearchIcon className="h-6 w-6" />
+            </span>
+            <input
+              type="text"
+              className="rounded-r-only"
+              value={searchFilter}
+              onChange={(e) => setSearchFilter(e.target.value as string)}
+            />
+          </div>
           <div className="mb-2 flex flex-1 flex-row justify-between sm:mb-0 sm:flex-none">
             <Button
-              className="mr-2 w-full flex-grow"
+              className="mr-2 flex flex-grow"
               buttonType={refreshInterval ? 'default' : 'primary'}
               onClick={() => toggleLogs()}
             >
@@ -252,34 +274,34 @@ const SettingsLogs: React.FC = () => {
                 )}
               </span>
             </Button>
-          </div>
-          <div className="mb-2 flex flex-1 sm:mb-0 sm:flex-none">
-            <span className="inline-flex cursor-default items-center rounded-l-md border border-r-0 border-gray-500 bg-gray-800 px-3 text-sm text-gray-100">
-              <FilterIcon className="h-6 w-6" />
-            </span>
-            <select
-              id="filter"
-              name="filter"
-              onChange={(e) => {
-                setCurrentFilter(e.target.value as Filter);
-                router.push(router.pathname);
-              }}
-              value={currentFilter}
-              className="rounded-r-only"
-            >
-              <option value="debug">
-                {intl.formatMessage(messages.filterDebug)}
-              </option>
-              <option value="info">
-                {intl.formatMessage(messages.filterInfo)}
-              </option>
-              <option value="warn">
-                {intl.formatMessage(messages.filterWarn)}
-              </option>
-              <option value="error">
-                {intl.formatMessage(messages.filterError)}
-              </option>
-            </select>
+            <div className="flex flex-grow">
+              <span className="inline-flex cursor-default items-center rounded-l-md border border-r-0 border-gray-500 bg-gray-800 px-3 text-sm text-gray-100">
+                <FilterIcon className="h-6 w-6" />
+              </span>
+              <select
+                id="filter"
+                name="filter"
+                onChange={(e) => {
+                  setCurrentFilter(e.target.value as Filter);
+                  router.push(router.pathname);
+                }}
+                value={currentFilter}
+                className="rounded-r-only"
+              >
+                <option value="debug">
+                  {intl.formatMessage(messages.filterDebug)}
+                </option>
+                <option value="info">
+                  {intl.formatMessage(messages.filterInfo)}
+                </option>
+                <option value="warn">
+                  {intl.formatMessage(messages.filterWarn)}
+                </option>
+                <option value="error">
+                  {intl.formatMessage(messages.filterError)}
+                </option>
+              </select>
+            </div>
           </div>
         </div>
         <Table>
@@ -293,63 +315,81 @@ const SettingsLogs: React.FC = () => {
             </tr>
           </thead>
           <Table.TBody>
-            {data.results.map((row: LogMessage, index: number) => {
-              return (
-                <tr key={`log-list-${index}`}>
-                  <Table.TD className="text-gray-300">
-                    {intl.formatDate(row.timestamp, {
-                      year: 'numeric',
-                      month: 'short',
-                      day: '2-digit',
-                      hour: 'numeric',
-                      minute: 'numeric',
-                      second: 'numeric',
-                    })}
-                  </Table.TD>
-                  <Table.TD className="text-gray-300">
-                    <Badge
-                      badgeType={
-                        row.level === 'error'
-                          ? 'danger'
-                          : row.level === 'warn'
-                          ? 'warning'
-                          : row.level === 'info'
-                          ? 'success'
-                          : 'default'
-                      }
-                    >
-                      {row.level.toUpperCase()}
-                    </Badge>
-                  </Table.TD>
-                  <Table.TD className="text-gray-300">
-                    {row.label ?? ''}
-                  </Table.TD>
-                  <Table.TD className="text-gray-300">{row.message}</Table.TD>
-                  <Table.TD className="-m-1 flex flex-wrap items-center justify-end">
-                    {row.data && (
-                      <Button
-                        buttonType="primary"
-                        buttonSize="sm"
-                        onClick={() => setActiveLog(row)}
-                        className="m-1"
+            {!data ? (
+              <tr>
+                <Table.TD colSpan={5} noPadding>
+                  <LoadingSpinner />
+                </Table.TD>
+              </tr>
+            ) : (
+              data.results.map((row: LogMessage, index: number) => {
+                return (
+                  <tr key={`log-list-${index}`}>
+                    <Table.TD className="text-gray-300">
+                      {intl.formatDate(row.timestamp, {
+                        year: 'numeric',
+                        month: 'short',
+                        day: '2-digit',
+                        hour: 'numeric',
+                        minute: 'numeric',
+                        second: 'numeric',
+                      })}
+                    </Table.TD>
+                    <Table.TD className="text-gray-300">
+                      <Badge
+                        badgeType={
+                          row.level === 'error'
+                            ? 'danger'
+                            : row.level === 'warn'
+                            ? 'warning'
+                            : row.level === 'info'
+                            ? 'success'
+                            : 'default'
+                        }
                       >
-                        <DocumentSearchIcon className="icon-md" />
-                      </Button>
-                    )}
-                    <Button
-                      buttonType="primary"
-                      buttonSize="sm"
-                      onClick={() => copyLogString(row)}
-                      className="m-1"
-                    >
-                      <ClipboardCopyIcon className="icon-md" />
-                    </Button>
-                  </Table.TD>
-                </tr>
-              );
-            })}
+                        {row.level.toUpperCase()}
+                      </Badge>
+                    </Table.TD>
+                    <Table.TD className="text-gray-300">
+                      {row.label ?? ''}
+                    </Table.TD>
+                    <Table.TD className="text-gray-300">{row.message}</Table.TD>
+                    <Table.TD className="-m-1 flex flex-wrap items-center justify-end">
+                      {row.data && (
+                        <Tooltip
+                          content={intl.formatMessage(messages.viewdetails)}
+                        >
+                          <Button
+                            buttonSize="sm"
+                            buttonType="primary"
+                            onClick={() =>
+                              setActiveLog({ log: row, isOpen: true })
+                            }
+                            className="m-1"
+                          >
+                            <DocumentSearchIcon className="icon-md" />
+                          </Button>
+                        </Tooltip>
+                      )}
+                      <Tooltip
+                        content={intl.formatMessage(messages.copyToClipboard)}
+                      >
+                        <Button
+                          buttonType="primary"
+                          buttonSize="sm"
+                          onClick={() => copyLogString(row)}
+                          className="m-1"
+                        >
+                          <ClipboardCopyIcon className="icon-md" />
+                        </Button>
+                      </Tooltip>
+                    </Table.TD>
+                  </tr>
+                );
+              })
+            )}
 
-            {data.results.length === 0 && (
+            {data?.results.length === 0 && (
               <tr className="relative h-24 p-2 text-white">
                 <Table.TD colSpan={5} noPadding>
                   <div className="flex w-screen flex-col items-center justify-center p-6 md:w-full">
@@ -379,18 +419,18 @@ const SettingsLogs: React.FC = () => {
                 >
                   <div className="hidden lg:flex lg:flex-1">
                     <p className="text-sm">
-                      {data.results.length > 0 &&
+                      {(data?.results.length ?? 0) > 0 &&
                         intl.formatMessage(globalMessages.showingresults, {
                           from: pageIndex * currentPageSize + 1,
                           to:
-                            data.results.length < currentPageSize
+                            data?.results.length ?? 0 < currentPageSize
                               ? pageIndex * currentPageSize +
-                                data.results.length
+                                (data?.results.length ?? 0)
                               : (pageIndex + 1) * currentPageSize,
-                          total: data.pageInfo.results,
-                          strong: function strong(msg) {
-                            return <span className="font-medium">{msg}</span>;
-                          },
+                          total: data?.pageInfo.results ?? 0,
+                          strong: (msg: React.ReactNode) => (
+                            <span className="font-medium">{msg}</span>
+                          ),
                         })}
                     </p>
                   </div>
diff --git a/src/components/Settings/SettingsMain.tsx b/src/components/Settings/SettingsMain.tsx
index 8c9d06f6..3ac7b09b 100644
--- a/src/components/Settings/SettingsMain.tsx
+++ b/src/components/Settings/SettingsMain.tsx
@@ -1,29 +1,27 @@
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import SensitiveInput from '@app/components/Common/SensitiveInput';
+import Tooltip from '@app/components/Common/Tooltip';
+import LanguageSelector from '@app/components/LanguageSelector';
+import RegionSelector from '@app/components/RegionSelector';
+import CopyButton from '@app/components/Settings/CopyButton';
+import SettingsBadge from '@app/components/Settings/SettingsBadge';
+import type { AvailableLocale } from '@app/context/LanguageContext';
+import { availableLanguages } from '@app/context/LanguageContext';
+import useLocale from '@app/hooks/useLocale';
+import { Permission, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
 import { SaveIcon } from '@heroicons/react/outline';
 import { RefreshIcon } from '@heroicons/react/solid';
+import type { UserSettingsGeneralResponse } from '@server/interfaces/api/userSettingsInterfaces';
+import type { MainSettings } from '@server/lib/settings';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR, { mutate } from 'swr';
 import * as Yup from 'yup';
-import { UserSettingsGeneralResponse } from '../../../server/interfaces/api/userSettingsInterfaces';
-import type { MainSettings } from '../../../server/lib/settings';
-import {
-  availableLanguages,
-  AvailableLocale,
-} from '../../context/LanguageContext';
-import useLocale from '../../hooks/useLocale';
-import { Permission, useUser } from '../../hooks/useUser';
-import globalMessages from '../../i18n/globalMessages';
-import Badge from '../Common/Badge';
-import Button from '../Common/Button';
-import LoadingSpinner from '../Common/LoadingSpinner';
-import PageTitle from '../Common/PageTitle';
-import SensitiveInput from '../Common/SensitiveInput';
-import LanguageSelector from '../LanguageSelector';
-import RegionSelector from '../RegionSelector';
-import CopyButton from './CopyButton';
 
 const messages = defineMessages({
   general: 'General',
@@ -43,16 +41,15 @@ const messages = defineMessages({
   toastSettingsFailure: 'Something went wrong while saving settings.',
   hideAvailable: 'Hide Available Media',
   csrfProtection: 'Enable CSRF Protection',
-  csrfProtectionTip:
-    'Set external API access to read-only (requires HTTPS, and Overseerr must be reloaded for changes to take effect)',
+  csrfProtectionTip: 'Set external API access to read-only (requires HTTPS)',
   csrfProtectionHoverTip:
     'Do NOT enable this setting unless you understand what you are doing!',
   cacheImages: 'Enable Image Caching',
   cacheImagesTip:
-    'Optimize and store all images locally (consumes a significant amount of disk space)',
+    'Cache and serve optimized images (requires a significant amount of disk space)',
   trustProxy: 'Enable Proxy Support',
   trustProxyTip:
-    'Allow Overseerr to correctly register client IP addresses behind a proxy (Overseerr must be reloaded for changes to take effect)',
+    'Allow Overseerr to correctly register client IP addresses behind a proxy',
   validationApplicationTitle: 'You must provide an application title',
   validationApplicationUrl: 'You must provide a valid URL',
   validationApplicationUrlTrailingSlash: 'URL must not end in a trailing slash',
@@ -60,7 +57,7 @@ const messages = defineMessages({
   locale: 'Display Language',
 });
 
-const SettingsMain: React.FC = () => {
+const SettingsMain = () => {
   const { addToast } = useToasts();
   const { user: currentUser, hasPermission: userHasPermission } = useUser();
   const intl = useIntl();
@@ -136,6 +133,7 @@ const SettingsMain: React.FC = () => {
             originalLanguage: data?.originalLanguage,
             partialRequestsEnabled: data?.partialRequestsEnabled,
             trustProxy: data?.trustProxy,
+            cacheImages: data?.cacheImages,
           }}
           enableReinitialize
           validationSchema={MainSettingsSchema}
@@ -151,8 +149,10 @@ const SettingsMain: React.FC = () => {
                 originalLanguage: values.originalLanguage,
                 partialRequestsEnabled: values.partialRequestsEnabled,
                 trustProxy: values.trustProxy,
+                cacheImages: values.cacheImages,
               });
               mutate('/api/v1/settings/public');
+              mutate('/api/v1/status');
 
               if (setLocale) {
                 setLocale(
@@ -229,9 +229,11 @@ const SettingsMain: React.FC = () => {
                         type="text"
                       />
                     </div>
-                    {errors.applicationTitle && touched.applicationTitle && (
-                      <div className="error">{errors.applicationTitle}</div>
-                    )}
+                    {errors.applicationTitle &&
+                      touched.applicationTitle &&
+                      typeof errors.applicationTitle === 'string' && (
+                        <div className="error">{errors.applicationTitle}</div>
+                      )}
                   </div>
                 </div>
                 <div className="form-row">
@@ -247,14 +249,19 @@ const SettingsMain: React.FC = () => {
                         inputMode="url"
                       />
                     </div>
-                    {errors.applicationUrl && touched.applicationUrl && (
-                      <div className="error">{errors.applicationUrl}</div>
-                    )}
+                    {errors.applicationUrl &&
+                      touched.applicationUrl &&
+                      typeof errors.applicationUrl === 'string' && (
+                        <div className="error">{errors.applicationUrl}</div>
+                      )}
                   </div>
                 </div>
                 <div className="form-row">
                   <label htmlFor="trustProxy" className="checkbox-label">
-                    <span>{intl.formatMessage(messages.trustProxy)}</span>
+                    <span className="mr-2">
+                      {intl.formatMessage(messages.trustProxy)}
+                    </span>
+                    <SettingsBadge badgeType="restartRequired" />
                     <span className="label-tip">
                       {intl.formatMessage(messages.trustProxyTip)}
                     </span>
@@ -275,23 +282,49 @@ const SettingsMain: React.FC = () => {
                     <span className="mr-2">
                       {intl.formatMessage(messages.csrfProtection)}
                     </span>
-                    <Badge badgeType="danger">
-                      {intl.formatMessage(globalMessages.advanced)}
-                    </Badge>
+                    <SettingsBadge badgeType="advanced" className="mr-2" />
+                    <SettingsBadge badgeType="restartRequired" />
                     <span className="label-tip">
                       {intl.formatMessage(messages.csrfProtectionTip)}
                     </span>
                   </label>
                   <div className="form-input-area">
-                    <Field
-                      type="checkbox"
-                      id="csrfProtection"
-                      name="csrfProtection"
-                      title={intl.formatMessage(
+                    <Tooltip
+                      content={intl.formatMessage(
                         messages.csrfProtectionHoverTip
                       )}
+                    >
+                      <Field
+                        type="checkbox"
+                        id="csrfProtection"
+                        name="csrfProtection"
+                        onChange={() => {
+                          setFieldValue(
+                            'csrfProtection',
+                            !values.csrfProtection
+                          );
+                        }}
+                      />
+                    </Tooltip>
+                  </div>
+                </div>
+                <div className="form-row">
+                  <label htmlFor="csrfProtection" className="checkbox-label">
+                    <span className="mr-2">
+                      {intl.formatMessage(messages.cacheImages)}
+                    </span>
+                    <SettingsBadge badgeType="experimental" />
+                    <span className="label-tip">
+                      {intl.formatMessage(messages.cacheImagesTip)}
+                    </span>
+                  </label>
+                  <div className="form-input-area">
+                    <Field
+                      type="checkbox"
+                      id="cacheImages"
+                      name="cacheImages"
                       onChange={() => {
-                        setFieldValue('csrfProtection', !values.csrfProtection);
+                        setFieldValue('cacheImages', !values.cacheImages);
                       }}
                     />
                   </div>
@@ -358,9 +391,7 @@ const SettingsMain: React.FC = () => {
                     <span className="mr-2">
                       {intl.formatMessage(messages.hideAvailable)}
                     </span>
-                    <Badge badgeType="warning">
-                      {intl.formatMessage(globalMessages.experimental)}
-                    </Badge>
+                    <SettingsBadge badgeType="experimental" />
                   </label>
                   <div className="form-input-area">
                     <Field
diff --git a/src/components/Settings/SettingsNotifications.tsx b/src/components/Settings/SettingsNotifications.tsx
index c086512e..ca28c80b 100644
--- a/src/components/Settings/SettingsNotifications.tsx
+++ b/src/components/Settings/SettingsNotifications.tsx
@@ -1,16 +1,16 @@
+import DiscordLogo from '@app/assets/extlogos/discord.svg';
+import GotifyLogo from '@app/assets/extlogos/gotify.svg';
+import LunaSeaLogo from '@app/assets/extlogos/lunasea.svg';
+import PushbulletLogo from '@app/assets/extlogos/pushbullet.svg';
+import PushoverLogo from '@app/assets/extlogos/pushover.svg';
+import SlackLogo from '@app/assets/extlogos/slack.svg';
+import TelegramLogo from '@app/assets/extlogos/telegram.svg';
+import PageTitle from '@app/components/Common/PageTitle';
+import type { SettingsRoute } from '@app/components/Common/SettingsTabs';
+import SettingsTabs from '@app/components/Common/SettingsTabs';
+import globalMessages from '@app/i18n/globalMessages';
 import { CloudIcon, LightningBoltIcon, MailIcon } from '@heroicons/react/solid';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
-import DiscordLogo from '../../assets/extlogos/discord.svg';
-import GotifyLogo from '../../assets/extlogos/gotify.svg';
-import LunaSeaLogo from '../../assets/extlogos/lunasea.svg';
-import PushbulletLogo from '../../assets/extlogos/pushbullet.svg';
-import PushoverLogo from '../../assets/extlogos/pushover.svg';
-import SlackLogo from '../../assets/extlogos/slack.svg';
-import TelegramLogo from '../../assets/extlogos/telegram.svg';
-import globalMessages from '../../i18n/globalMessages';
-import PageTitle from '../Common/PageTitle';
-import SettingsTabs, { SettingsRoute } from '../Common/SettingsTabs';
 
 const messages = defineMessages({
   notifications: 'Notifications',
@@ -22,7 +22,11 @@ const messages = defineMessages({
   webpush: 'Web Push',
 });
 
-const SettingsNotifications: React.FC = ({ children }) => {
+type SettingsNotificationsProps = {
+  children: React.ReactNode;
+};
+
+const SettingsNotifications = ({ children }: SettingsNotificationsProps) => {
   const intl = useIntl();
 
   const settingsRoutes: SettingsRoute[] = [
diff --git a/src/components/Settings/SettingsPlex.tsx b/src/components/Settings/SettingsPlex.tsx
index d5aa7749..27564aca 100644
--- a/src/components/Settings/SettingsPlex.tsx
+++ b/src/components/Settings/SettingsPlex.tsx
@@ -1,26 +1,24 @@
+import Alert from '@app/components/Common/Alert';
+import Badge from '@app/components/Common/Badge';
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import SensitiveInput from '@app/components/Common/SensitiveInput';
+import LibraryItem from '@app/components/Settings/LibraryItem';
+import SettingsBadge from '@app/components/Settings/SettingsBadge';
+import globalMessages from '@app/i18n/globalMessages';
 import { SaveIcon } from '@heroicons/react/outline';
 import { RefreshIcon, SearchIcon, XIcon } from '@heroicons/react/solid';
+import type { PlexDevice } from '@server/interfaces/api/plexInterfaces';
+import type { PlexSettings, TautulliSettings } from '@server/lib/settings';
 import axios from 'axios';
 import { Field, Formik } from 'formik';
 import { orderBy } from 'lodash';
-import React, { useMemo, useState } from 'react';
+import { useMemo, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import type { PlexDevice } from '../../../server/interfaces/api/plexInterfaces';
-import type {
-  PlexSettings,
-  TautulliSettings,
-} from '../../../server/lib/settings';
-import globalMessages from '../../i18n/globalMessages';
-import Alert from '../Common/Alert';
-import Badge from '../Common/Badge';
-import Button from '../Common/Button';
-import LoadingSpinner from '../Common/LoadingSpinner';
-import PageTitle from '../Common/PageTitle';
-import SensitiveInput from '../Common/SensitiveInput';
-import LibraryItem from './LibraryItem';
 
 const messages = defineMessages({
   plex: 'Plex',
@@ -107,7 +105,7 @@ interface SettingsPlexProps {
   onComplete?: () => void;
 }
 
-const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
+const SettingsPlex = ({ onComplete }: SettingsPlexProps) => {
   const [isSyncing, setIsSyncing] = useState(false);
   const [isRefreshingPresets, setIsRefreshingPresets] = useState(false);
   const [availableServers, setAvailableServers] = useState<PlexDevice[] | null>(
@@ -344,18 +342,16 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
           <div className="section">
             <Alert
               title={intl.formatMessage(messages.settingUpPlexDescription, {
-                RegisterPlexTVLink: function RegisterPlexTVLink(msg) {
-                  return (
-                    <a
-                      href="https://plex.tv"
-                      className="text-white transition duration-300 hover:underline"
-                      target="_blank"
-                      rel="noreferrer"
-                    >
-                      {msg}
-                    </a>
-                  );
-                },
+                RegisterPlexTVLink: (msg: React.ReactNode) => (
+                  <a
+                    href="https://plex.tv"
+                    className="text-white transition duration-300 hover:underline"
+                    target="_blank"
+                    rel="noreferrer"
+                  >
+                    {msg}
+                  </a>
+                ),
               })}
               type="info"
             />
@@ -517,9 +513,11 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
                       className="rounded-r-only"
                     />
                   </div>
-                  {errors.hostname && touched.hostname && (
-                    <div className="error">{errors.hostname}</div>
-                  )}
+                  {errors.hostname &&
+                    touched.hostname &&
+                    typeof errors.hostname === 'string' && (
+                      <div className="error">{errors.hostname}</div>
+                    )}
                 </div>
               </div>
               <div className="form-row">
@@ -535,9 +533,11 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
                     name="port"
                     className="short"
                   />
-                  {errors.port && touched.port && (
-                    <div className="error">{errors.port}</div>
-                  )}
+                  {errors.port &&
+                    touched.port &&
+                    typeof errors.port === 'string' && (
+                      <div className="error">{errors.port}</div>
+                    )}
                 </div>
               </div>
               <div className="form-row">
@@ -558,21 +558,17 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
               <div className="form-row">
                 <label htmlFor="webAppUrl" className="text-label">
                   {intl.formatMessage(messages.webAppUrl, {
-                    WebAppLink: function WebAppLink(msg) {
-                      return (
-                        <a
-                          href="https://support.plex.tv/articles/200288666-opening-plex-web-app/"
-                          target="_blank"
-                          rel="noreferrer"
-                        >
-                          {msg}
-                        </a>
-                      );
-                    },
+                    WebAppLink: (msg: React.ReactNode) => (
+                      <a
+                        href="https://support.plex.tv/articles/200288666-opening-plex-web-app/"
+                        target="_blank"
+                        rel="noreferrer"
+                      >
+                        {msg}
+                      </a>
+                    ),
                   })}
-                  <Badge badgeType="danger" className="ml-2">
-                    {intl.formatMessage(globalMessages.advanced)}
-                  </Badge>
+                  <SettingsBadge badgeType="advanced" className="ml-2" />
                   <span className="label-tip">
                     {intl.formatMessage(messages.webAppUrlTip)}
                   </span>
@@ -587,9 +583,11 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
                       placeholder="https://app.plex.tv/desktop"
                     />
                   </div>
-                  {errors.webAppUrl && touched.webAppUrl && (
-                    <div className="error">{errors.webAppUrl}</div>
-                  )}
+                  {errors.webAppUrl &&
+                    touched.webAppUrl &&
+                    typeof errors.webAppUrl === 'string' && (
+                      <div className="error">{errors.webAppUrl}</div>
+                    )}
                 </div>
               </div>
               <div className="actions">
@@ -803,9 +801,11 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
                           className="rounded-r-only"
                         />
                       </div>
-                      {errors.tautulliHostname && touched.tautulliHostname && (
-                        <div className="error">{errors.tautulliHostname}</div>
-                      )}
+                      {errors.tautulliHostname &&
+                        touched.tautulliHostname &&
+                        typeof errors.tautulliHostname === 'string' && (
+                          <div className="error">{errors.tautulliHostname}</div>
+                        )}
                     </div>
                   </div>
                   <div className="form-row">
@@ -821,9 +821,11 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
                         name="tautulliPort"
                         className="short"
                       />
-                      {errors.tautulliPort && touched.tautulliPort && (
-                        <div className="error">{errors.tautulliPort}</div>
-                      )}
+                      {errors.tautulliPort &&
+                        touched.tautulliPort &&
+                        typeof errors.tautulliPort === 'string' && (
+                          <div className="error">{errors.tautulliPort}</div>
+                        )}
                     </div>
                   </div>
                   <div className="form-row">
@@ -857,9 +859,11 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
                           name="tautulliUrlBase"
                         />
                       </div>
-                      {errors.tautulliUrlBase && touched.tautulliUrlBase && (
-                        <div className="error">{errors.tautulliUrlBase}</div>
-                      )}
+                      {errors.tautulliUrlBase &&
+                        touched.tautulliUrlBase &&
+                        typeof errors.tautulliUrlBase === 'string' && (
+                          <div className="error">{errors.tautulliUrlBase}</div>
+                        )}
                     </div>
                   </div>
                   <div className="form-row">
@@ -876,9 +880,11 @@ const SettingsPlex: React.FC<SettingsPlexProps> = ({ onComplete }) => {
                           autoComplete="one-time-code"
                         />
                       </div>
-                      {errors.tautulliApiKey && touched.tautulliApiKey && (
-                        <div className="error">{errors.tautulliApiKey}</div>
-                      )}
+                      {errors.tautulliApiKey &&
+                        touched.tautulliApiKey &&
+                        typeof errors.tautulliApiKey === 'string' && (
+                          <div className="error">{errors.tautulliApiKey}</div>
+                        )}
                     </div>
                   </div>
                   <div className="form-row">
diff --git a/src/components/Settings/SettingsServices.tsx b/src/components/Settings/SettingsServices.tsx
index a54a4494..6cbd118e 100644
--- a/src/components/Settings/SettingsServices.tsx
+++ b/src/components/Settings/SettingsServices.tsx
@@ -1,24 +1,21 @@
+import RadarrLogo from '@app/assets/services/radarr.svg';
+import SonarrLogo from '@app/assets/services/sonarr.svg';
+import Alert from '@app/components/Common/Alert';
+import Badge from '@app/components/Common/Badge';
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import Modal from '@app/components/Common/Modal';
+import PageTitle from '@app/components/Common/PageTitle';
+import RadarrModal from '@app/components/Settings/RadarrModal';
+import SonarrModal from '@app/components/Settings/SonarrModal';
+import globalMessages from '@app/i18n/globalMessages';
+import { Transition } from '@headlessui/react';
 import { PencilIcon, PlusIcon, TrashIcon } from '@heroicons/react/solid';
+import type { RadarrSettings, SonarrSettings } from '@server/lib/settings';
 import axios from 'axios';
-import React, { useState } from 'react';
+import { Fragment, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR, { mutate } from 'swr';
-import type {
-  RadarrSettings,
-  SonarrSettings,
-} from '../../../server/lib/settings';
-import RadarrLogo from '../../assets/services/radarr.svg';
-import SonarrLogo from '../../assets/services/sonarr.svg';
-import globalMessages from '../../i18n/globalMessages';
-import Alert from '../Common/Alert';
-import Badge from '../Common/Badge';
-import Button from '../Common/Button';
-import LoadingSpinner from '../Common/LoadingSpinner';
-import Modal from '../Common/Modal';
-import PageTitle from '../Common/PageTitle';
-import Transition from '../Transition';
-import RadarrModal from './RadarrModal';
-import SonarrModal from './SonarrModal';
 
 const messages = defineMessages({
   services: 'Services',
@@ -43,6 +40,7 @@ const messages = defineMessages({
     'A 4K {serverType} server must be marked as default in order to enable users to submit 4K {mediaType} requests.',
   mediaTypeMovie: 'movie',
   mediaTypeSeries: 'series',
+  deleteServer: 'Delete {serverType} Server',
 });
 
 interface ServerInstanceProps {
@@ -59,7 +57,7 @@ interface ServerInstanceProps {
   onDelete: () => void;
 }
 
-const ServerInstance: React.FC<ServerInstanceProps> = ({
+const ServerInstance = ({
   name,
   hostname,
   port,
@@ -71,7 +69,7 @@ const ServerInstance: React.FC<ServerInstanceProps> = ({
   externalUrl,
   onEdit,
   onDelete,
-}) => {
+}: ServerInstanceProps) => {
   const intl = useIntl();
 
   const internalUrl =
@@ -160,7 +158,7 @@ const ServerInstance: React.FC<ServerInstanceProps> = ({
   );
 };
 
-const SettingsServices: React.FC = () => {
+const SettingsServices = () => {
   const intl = useIntl();
   const {
     data: radarrData,
@@ -247,6 +245,7 @@ const SettingsServices: React.FC = () => {
         />
       )}
       <Transition
+        as={Fragment}
         show={deleteServerModal.open}
         enter="transition ease-in-out duration-300 transform opacity-0"
         enterFrom="opacity-0"
@@ -256,7 +255,7 @@ const SettingsServices: React.FC = () => {
         leaveTo="opacity-0"
       >
         <Modal
-          okText="Delete"
+          okText={intl.formatMessage(globalMessages.delete)}
           okButtonType="danger"
           onOk={() => deleteServer()}
           onCancel={() =>
@@ -266,8 +265,10 @@ const SettingsServices: React.FC = () => {
               type: 'radarr',
             })
           }
-          title="Delete Server"
-          iconSvg={<TrashIcon />}
+          title={intl.formatMessage(messages.deleteServer, {
+            serverType:
+              deleteServerModal.type === 'radarr' ? 'Radarr' : 'Sonarr',
+          })}
         >
           {intl.formatMessage(messages.deleteserverconfirm)}
         </Modal>
@@ -290,13 +291,11 @@ const SettingsServices: React.FC = () => {
                 <Alert
                   title={intl.formatMessage(messages.noDefaultNon4kServer, {
                     serverType: 'Radarr',
-                    strong: function strong(msg) {
-                      return (
-                        <strong className="font-semibold text-white">
-                          {msg}
-                        </strong>
-                      );
-                    },
+                    strong: (msg: React.ReactNode) => (
+                      <strong className="font-semibold text-white">
+                        {msg}
+                      </strong>
+                    ),
                   })}
                 />
               ) : (
@@ -380,13 +379,11 @@ const SettingsServices: React.FC = () => {
                 <Alert
                   title={intl.formatMessage(messages.noDefaultNon4kServer, {
                     serverType: 'Sonarr',
-                    strong: function strong(msg) {
-                      return (
-                        <strong className="font-semibold text-white">
-                          {msg}
-                        </strong>
-                      );
-                    },
+                    strong: (msg: React.ReactNode) => (
+                      <strong className="font-semibold text-white">
+                        {msg}
+                      </strong>
+                    ),
                   })}
                 />
               ) : (
diff --git a/src/components/Settings/SettingsUsers/index.tsx b/src/components/Settings/SettingsUsers/index.tsx
index 8e1d9350..fb01ba48 100644
--- a/src/components/Settings/SettingsUsers/index.tsx
+++ b/src/components/Settings/SettingsUsers/index.tsx
@@ -1,17 +1,16 @@
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import PermissionEdit from '@app/components/PermissionEdit';
+import QuotaSelector from '@app/components/QuotaSelector';
+import globalMessages from '@app/i18n/globalMessages';
 import { SaveIcon } from '@heroicons/react/outline';
+import type { MainSettings } from '@server/lib/settings';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR, { mutate } from 'swr';
-import type { MainSettings } from '../../../../server/lib/settings';
-import globalMessages from '../../../i18n/globalMessages';
-import Button from '../../Common/Button';
-import LoadingSpinner from '../../Common/LoadingSpinner';
-import PageTitle from '../../Common/PageTitle';
-import PermissionEdit from '../../PermissionEdit';
-import QuotaSelector from '../../QuotaSelector';
 
 const messages = defineMessages({
   users: 'Users',
@@ -30,7 +29,7 @@ const messages = defineMessages({
   defaultPermissionsTip: 'Initial permissions assigned to new users',
 });
 
-const SettingsUsers: React.FC = () => {
+const SettingsUsers = () => {
   const { addToast } = useToasts();
   const intl = useIntl();
   const {
diff --git a/src/components/Settings/SonarrModal/index.tsx b/src/components/Settings/SonarrModal/index.tsx
index 391db286..ab5f9758 100644
--- a/src/components/Settings/SonarrModal/index.tsx
+++ b/src/components/Settings/SonarrModal/index.tsx
@@ -1,16 +1,16 @@
-import { PencilIcon, PlusIcon } from '@heroicons/react/solid';
+import Modal from '@app/components/Common/Modal';
+import SensitiveInput from '@app/components/Common/SensitiveInput';
+import globalMessages from '@app/i18n/globalMessages';
+import { Transition } from '@headlessui/react';
+import type { SonarrSettings } from '@server/lib/settings';
 import axios from 'axios';
 import { Field, Formik } from 'formik';
-import React, { useCallback, useEffect, useRef, useState } from 'react';
+import { useCallback, useEffect, useRef, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
-import Select, { OnChangeValue } from 'react-select';
+import type { OnChangeValue } from 'react-select';
+import Select from 'react-select';
 import { useToasts } from 'react-toast-notifications';
 import * as Yup from 'yup';
-import type { SonarrSettings } from '../../../../server/lib/settings';
-import globalMessages from '../../../i18n/globalMessages';
-import Modal from '../../Common/Modal';
-import SensitiveInput from '../../Common/SensitiveInput';
-import Transition from '../../Transition';
 
 type OptionType = {
   value: number;
@@ -98,11 +98,7 @@ interface SonarrModalProps {
   onSave: () => void;
 }
 
-const SonarrModal: React.FC<SonarrModalProps> = ({
-  onClose,
-  sonarr,
-  onSave,
-}) => {
+const SonarrModal = ({ onClose, sonarr, onSave }: SonarrModalProps) => {
   const intl = useIntl();
   const initialLoad = useRef(false);
   const { addToast } = useToasts();
@@ -224,6 +220,7 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
 
   return (
     <Transition
+      as="div"
       appear
       show
       enter="transition ease-in-out duration-300 transform opacity-0"
@@ -371,7 +368,6 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
                       values.is4k ? messages.edit4ksonarr : messages.editsonarr
                     )
               }
-              iconSvg={!sonarr ? <PlusIcon /> : <PencilIcon />}
             >
               <div className="mb-6">
                 <div className="form-row">
@@ -411,9 +407,11 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
                         }}
                       />
                     </div>
-                    {errors.name && touched.name && (
-                      <div className="error">{errors.name}</div>
-                    )}
+                    {errors.name &&
+                      touched.name &&
+                      typeof errors.name === 'string' && (
+                        <div className="error">{errors.name}</div>
+                      )}
                   </div>
                 </div>
                 <div className="form-row">
@@ -438,9 +436,11 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
                         className="rounded-r-only"
                       />
                     </div>
-                    {errors.hostname && touched.hostname && (
-                      <div className="error">{errors.hostname}</div>
-                    )}
+                    {errors.hostname &&
+                      touched.hostname &&
+                      typeof errors.hostname === 'string' && (
+                        <div className="error">{errors.hostname}</div>
+                      )}
                   </div>
                 </div>
                 <div className="form-row">
@@ -460,9 +460,11 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
                         setFieldValue('port', e.target.value);
                       }}
                     />
-                    {errors.port && touched.port && (
-                      <div className="error">{errors.port}</div>
-                    )}
+                    {errors.port &&
+                      touched.port &&
+                      typeof errors.port === 'string' && (
+                        <div className="error">{errors.port}</div>
+                      )}
                   </div>
                 </div>
                 <div className="form-row">
@@ -499,9 +501,11 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
                         }}
                       />
                     </div>
-                    {errors.apiKey && touched.apiKey && (
-                      <div className="error">{errors.apiKey}</div>
-                    )}
+                    {errors.apiKey &&
+                      touched.apiKey &&
+                      typeof errors.apiKey === 'string' && (
+                        <div className="error">{errors.apiKey}</div>
+                      )}
                   </div>
                 </div>
                 <div className="form-row">
@@ -521,9 +525,11 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
                         }}
                       />
                     </div>
-                    {errors.baseUrl && touched.baseUrl && (
-                      <div className="error">{errors.baseUrl}</div>
-                    )}
+                    {errors.baseUrl &&
+                      touched.baseUrl &&
+                      typeof errors.baseUrl === 'string' && (
+                        <div className="error">{errors.baseUrl}</div>
+                      )}
                   </div>
                 </div>
                 <div className="form-row">
@@ -559,9 +565,11 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
                           ))}
                       </Field>
                     </div>
-                    {errors.activeProfileId && touched.activeProfileId && (
-                      <div className="error">{errors.activeProfileId}</div>
-                    )}
+                    {errors.activeProfileId &&
+                      touched.activeProfileId &&
+                      typeof errors.activeProfileId === 'string' && (
+                        <div className="error">{errors.activeProfileId}</div>
+                      )}
                   </div>
                 </div>
                 <div className="form-row">
@@ -595,9 +603,11 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
                           ))}
                       </Field>
                     </div>
-                    {errors.rootFolder && touched.rootFolder && (
-                      <div className="error">{errors.rootFolder}</div>
-                    )}
+                    {errors.rootFolder &&
+                      touched.rootFolder &&
+                      typeof errors.rootFolder === 'string' && (
+                        <div className="error">{errors.rootFolder}</div>
+                      )}
                   </div>
                 </div>
                 <div className="form-row">
@@ -919,9 +929,11 @@ const SonarrModal: React.FC<SonarrModalProps> = ({
                         inputMode="url"
                       />
                     </div>
-                    {errors.externalUrl && touched.externalUrl && (
-                      <div className="error">{errors.externalUrl}</div>
-                    )}
+                    {errors.externalUrl &&
+                      touched.externalUrl &&
+                      typeof errors.externalUrl === 'string' && (
+                        <div className="error">{errors.externalUrl}</div>
+                      )}
                   </div>
                 </div>
                 <div className="form-row">
diff --git a/src/components/Setup/LoginWithPlex.tsx b/src/components/Setup/LoginWithPlex.tsx
index 90d4425b..62778aed 100644
--- a/src/components/Setup/LoginWithPlex.tsx
+++ b/src/components/Setup/LoginWithPlex.tsx
@@ -1,8 +1,8 @@
+import PlexLoginButton from '@app/components/PlexLoginButton';
+import { useUser } from '@app/hooks/useUser';
 import axios from 'axios';
-import React, { useEffect, useState } from 'react';
+import { useEffect, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
-import { useUser } from '../../hooks/useUser';
-import PlexLoginButton from '../PlexLoginButton';
 
 const messages = defineMessages({
   welcome: 'Welcome to Overseerr',
@@ -13,7 +13,7 @@ interface LoginWithPlexProps {
   onComplete: () => void;
 }
 
-const LoginWithPlex: React.FC<LoginWithPlexProps> = ({ onComplete }) => {
+const LoginWithPlex = ({ onComplete }: LoginWithPlexProps) => {
   const intl = useIntl();
   const [authToken, setAuthToken] = useState<string | undefined>(undefined);
   const { user, revalidate } = useUser();
diff --git a/src/components/Setup/SetupSteps.tsx b/src/components/Setup/SetupSteps.tsx
index cee5263d..0529538a 100644
--- a/src/components/Setup/SetupSteps.tsx
+++ b/src/components/Setup/SetupSteps.tsx
@@ -1,5 +1,4 @@
 import { CheckIcon } from '@heroicons/react/solid';
-import React from 'react';
 
 interface CurrentStep {
   stepNumber: number;
@@ -9,13 +8,13 @@ interface CurrentStep {
   isLastStep?: boolean;
 }
 
-const SetupSteps: React.FC<CurrentStep> = ({
+const SetupSteps = ({
   stepNumber,
   description,
   active = false,
   completed = false,
   isLastStep = false,
-}) => {
+}: CurrentStep) => {
   return (
     <li className="relative md:flex md:flex-1">
       <div className="flex items-center space-x-4 px-6 py-4 text-sm font-medium leading-5">
diff --git a/src/components/Setup/index.tsx b/src/components/Setup/index.tsx
index a1916290..3926da90 100644
--- a/src/components/Setup/index.tsx
+++ b/src/components/Setup/index.tsx
@@ -1,19 +1,19 @@
+import AppDataWarning from '@app/components/AppDataWarning';
+import Badge from '@app/components/Common/Badge';
+import Button from '@app/components/Common/Button';
+import ImageFader from '@app/components/Common/ImageFader';
+import PageTitle from '@app/components/Common/PageTitle';
+import LanguagePicker from '@app/components/Layout/LanguagePicker';
+import SettingsPlex from '@app/components/Settings/SettingsPlex';
+import SettingsServices from '@app/components/Settings/SettingsServices';
+import LoginWithPlex from '@app/components/Setup/LoginWithPlex';
+import SetupSteps from '@app/components/Setup/SetupSteps';
+import useLocale from '@app/hooks/useLocale';
 import axios from 'axios';
 import { useRouter } from 'next/router';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR, { mutate } from 'swr';
-import useLocale from '../../hooks/useLocale';
-import AppDataWarning from '../AppDataWarning';
-import Badge from '../Common/Badge';
-import Button from '../Common/Button';
-import ImageFader from '../Common/ImageFader';
-import PageTitle from '../Common/PageTitle';
-import LanguagePicker from '../Layout/LanguagePicker';
-import SettingsPlex from '../Settings/SettingsPlex';
-import SettingsServices from '../Settings/SettingsServices';
-import LoginWithPlex from './LoginWithPlex';
-import SetupSteps from './SetupSteps';
 
 const messages = defineMessages({
   setup: 'Setup',
@@ -28,7 +28,7 @@ const messages = defineMessages({
     'Scanning will run in the background. You can continue the setup process in the meantime.',
 });
 
-const Setup: React.FC = () => {
+const Setup = () => {
   const intl = useIntl();
   const [isUpdating, setIsUpdating] = useState(false);
   const [currentStep, setCurrentStep] = useState(1);
@@ -63,7 +63,7 @@ const Setup: React.FC = () => {
       <ImageFader
         backgroundImages={
           backdrops?.map(
-            (backdrop) => `https://www.themoviedb.org/t/p/original${backdrop}`
+            (backdrop) => `https://image.tmdb.org/t/p/original${backdrop}`
           ) ?? []
         }
       />
diff --git a/src/components/Slider/index.tsx b/src/components/Slider/index.tsx
index 89b3173d..daef05f4 100644
--- a/src/components/Slider/index.tsx
+++ b/src/components/Slider/index.tsx
@@ -1,24 +1,18 @@
+import TitleCard from '@app/components/TitleCard';
+import globalMessages from '@app/i18n/globalMessages';
 import { ChevronLeftIcon, ChevronRightIcon } from '@heroicons/react/outline';
 import { debounce } from 'lodash';
-import React, {
-  ReactNode,
-  useCallback,
-  useEffect,
-  useRef,
-  useState,
-} from 'react';
+import { useCallback, useEffect, useRef, useState } from 'react';
 import { useIntl } from 'react-intl';
 import { useSpring } from 'react-spring';
-import globalMessages from '../../i18n/globalMessages';
-import TitleCard from '../TitleCard';
 
 interface SliderProps {
   sliderKey: string;
   items?: JSX.Element[];
   isLoading: boolean;
-  isEmpty: boolean;
-  emptyMessage?: string;
-  placeholder?: ReactNode;
+  isEmpty?: boolean;
+  emptyMessage?: React.ReactNode;
+  placeholder?: React.ReactNode;
 }
 
 enum Direction {
@@ -26,14 +20,14 @@ enum Direction {
   LEFT,
 }
 
-const Slider: React.FC<SliderProps> = ({
+const Slider = ({
   sliderKey,
   items,
   isLoading,
-  isEmpty,
+  isEmpty = false,
   emptyMessage,
   placeholder = <TitleCard.Placeholder />,
-}) => {
+}: SliderProps) => {
   const intl = useIntl();
   const containerRef = useRef<HTMLDivElement>(null);
   const [scrollPos, setScrollPos] = useState({ isStart: true, isEnd: false });
@@ -154,7 +148,7 @@ const Slider: React.FC<SliderProps> = ({
   };
 
   return (
-    <div className="relative">
+    <div className="relative" data-testid="media-slider">
       <div className="absolute right-0 -mt-10 flex text-gray-400">
         <button
           className={`${
@@ -198,7 +192,7 @@ const Slider: React.FC<SliderProps> = ({
             </div>
           ))}
         {isEmpty && (
-          <div className="mt-16 mb-16 text-center text-white">
+          <div className="mt-16 mb-16 text-center font-medium text-gray-400">
             {emptyMessage
               ? emptyMessage
               : intl.formatMessage(globalMessages.noresults)}
diff --git a/src/components/StatusBadge/index.tsx b/src/components/StatusBadge/index.tsx
index 196b3a5d..add2bbb8 100644
--- a/src/components/StatusBadge/index.tsx
+++ b/src/components/StatusBadge/index.tsx
@@ -1,15 +1,18 @@
-import React from 'react';
+import Spinner from '@app/assets/spinner.svg';
+import Badge from '@app/components/Common/Badge';
+import Tooltip from '@app/components/Common/Tooltip';
+import useSettings from '@app/hooks/useSettings';
+import { Permission, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import { MediaStatus } from '@server/constants/media';
 import { defineMessages, useIntl } from 'react-intl';
-import { MediaStatus } from '../../../server/constants/media';
-import Spinner from '../../assets/spinner.svg';
-import useSettings from '../../hooks/useSettings';
-import { Permission, useUser } from '../../hooks/useUser';
-import globalMessages from '../../i18n/globalMessages';
-import Badge from '../Common/Badge';
 
 const messages = defineMessages({
   status: '{status}',
   status4k: '4K {status}',
+  playonplex: 'Play on Plex',
+  openinarr: 'Open in {arr}',
+  managemedia: 'Manage {mediaType}',
 });
 
 interface StatusBadgeProps {
@@ -22,7 +25,7 @@ interface StatusBadgeProps {
   mediaType?: 'movie' | 'tv';
 }
 
-const StatusBadge: React.FC<StatusBadgeProps> = ({
+const StatusBadge = ({
   status,
   is4k = false,
   inProgress = false,
@@ -30,12 +33,13 @@ const StatusBadge: React.FC<StatusBadgeProps> = ({
   serviceUrl,
   tmdbId,
   mediaType,
-}) => {
+}: StatusBadgeProps) => {
   const intl = useIntl();
   const { hasPermission } = useUser();
   const settings = useSettings();
 
   let mediaLink: string | undefined;
+  let mediaLinkDescription: string | undefined;
 
   if (
     mediaType &&
@@ -64,63 +68,94 @@ const StatusBadge: React.FC<StatusBadgeProps> = ({
         : settings.currentSettings.series4kEnabled))
   ) {
     mediaLink = plexUrl;
+    mediaLinkDescription = intl.formatMessage(messages.playonplex);
   } else if (hasPermission(Permission.MANAGE_REQUESTS)) {
-    mediaLink =
-      mediaType && tmdbId ? `/${mediaType}/${tmdbId}?manage=1` : serviceUrl;
+    if (mediaType && tmdbId) {
+      mediaLink = `/${mediaType}/${tmdbId}?manage=1`;
+      mediaLinkDescription = intl.formatMessage(messages.managemedia, {
+        mediaType: intl.formatMessage(
+          mediaType === 'movie' ? globalMessages.movie : globalMessages.tvshow
+        ),
+      });
+    } else if (hasPermission(Permission.ADMIN)) {
+      mediaLink = serviceUrl;
+      mediaLinkDescription = intl.formatMessage(messages.openinarr, {
+        arr: mediaType === 'movie' ? 'Radarr' : 'Sonarr',
+      });
+    }
   }
 
   switch (status) {
     case MediaStatus.AVAILABLE:
       return (
-        <Badge badgeType="success" href={mediaLink}>
-          <div className="flex items-center">
-            <span>
-              {intl.formatMessage(is4k ? messages.status4k : messages.status, {
-                status: intl.formatMessage(globalMessages.available),
-              })}
-            </span>
-            {inProgress && <Spinner className="ml-1 h-3 w-3" />}
-          </div>
-        </Badge>
+        <Tooltip content={mediaLinkDescription}>
+          <Badge badgeType="success" href={mediaLink}>
+            <div className="flex items-center">
+              <span>
+                {intl.formatMessage(
+                  is4k ? messages.status4k : messages.status,
+                  {
+                    status: intl.formatMessage(globalMessages.available),
+                  }
+                )}
+              </span>
+              {inProgress && <Spinner className="ml-1 h-3 w-3" />}
+            </div>
+          </Badge>
+        </Tooltip>
       );
 
     case MediaStatus.PARTIALLY_AVAILABLE:
       return (
-        <Badge badgeType="success" href={mediaLink}>
-          <div className="flex items-center">
-            <span>
-              {intl.formatMessage(is4k ? messages.status4k : messages.status, {
-                status: intl.formatMessage(globalMessages.partiallyavailable),
-              })}
-            </span>
-            {inProgress && <Spinner className="ml-1 h-3 w-3" />}
-          </div>
-        </Badge>
+        <Tooltip content={mediaLinkDescription}>
+          <Badge badgeType="success" href={mediaLink}>
+            <div className="flex items-center">
+              <span>
+                {intl.formatMessage(
+                  is4k ? messages.status4k : messages.status,
+                  {
+                    status: intl.formatMessage(
+                      globalMessages.partiallyavailable
+                    ),
+                  }
+                )}
+              </span>
+              {inProgress && <Spinner className="ml-1 h-3 w-3" />}
+            </div>
+          </Badge>
+        </Tooltip>
       );
 
     case MediaStatus.PROCESSING:
       return (
-        <Badge badgeType="primary" href={mediaLink}>
-          <div className="flex items-center">
-            <span>
-              {intl.formatMessage(is4k ? messages.status4k : messages.status, {
-                status: inProgress
-                  ? intl.formatMessage(globalMessages.processing)
-                  : intl.formatMessage(globalMessages.requested),
-              })}
-            </span>
-            {inProgress && <Spinner className="ml-1 h-3 w-3" />}
-          </div>
-        </Badge>
+        <Tooltip content={mediaLinkDescription}>
+          <Badge badgeType="primary" href={mediaLink}>
+            <div className="flex items-center">
+              <span>
+                {intl.formatMessage(
+                  is4k ? messages.status4k : messages.status,
+                  {
+                    status: inProgress
+                      ? intl.formatMessage(globalMessages.processing)
+                      : intl.formatMessage(globalMessages.requested),
+                  }
+                )}
+              </span>
+              {inProgress && <Spinner className="ml-1 h-3 w-3" />}
+            </div>
+          </Badge>
+        </Tooltip>
       );
 
     case MediaStatus.PENDING:
       return (
-        <Badge badgeType="warning" href={mediaLink}>
-          {intl.formatMessage(is4k ? messages.status4k : messages.status, {
-            status: intl.formatMessage(globalMessages.pending),
-          })}
-        </Badge>
+        <Tooltip content={mediaLinkDescription}>
+          <Badge badgeType="warning" href={mediaLink}>
+            {intl.formatMessage(is4k ? messages.status4k : messages.status, {
+              status: intl.formatMessage(globalMessages.pending),
+            })}
+          </Badge>
+        </Tooltip>
       );
 
     default:
diff --git a/src/components/StatusChacker/index.tsx b/src/components/StatusChacker/index.tsx
deleted file mode 100644
index 82e449db..00000000
--- a/src/components/StatusChacker/index.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-import { SparklesIcon } from '@heroicons/react/outline';
-import React from 'react';
-import { defineMessages, useIntl } from 'react-intl';
-import useSWR from 'swr';
-import { StatusResponse } from '../../../server/interfaces/api/settingsInterfaces';
-import Modal from '../Common/Modal';
-import Transition from '../Transition';
-
-const messages = defineMessages({
-  newversionavailable: 'Application Update',
-  newversionDescription:
-    'Overseerr has been updated! Please click the button below to reload the page.',
-  reloadOverseerr: 'Reload',
-});
-
-const StatusChecker: React.FC = () => {
-  const intl = useIntl();
-  const { data, error } = useSWR<StatusResponse>('/api/v1/status', {
-    refreshInterval: 60 * 1000,
-  });
-
-  if (!data && !error) {
-    return null;
-  }
-
-  if (!data) {
-    return null;
-  }
-
-  return (
-    <Transition
-      enter="opacity-0 transition duration-300"
-      enterFrom="opacity-0"
-      enterTo="opacity-100"
-      leave="opacity-100 transition duration-300"
-      leaveFrom="opacity-100"
-      leaveTo="opacity-0"
-      appear
-      show={data.commitTag !== process.env.commitTag}
-    >
-      <Modal
-        iconSvg={<SparklesIcon />}
-        title={intl.formatMessage(messages.newversionavailable)}
-        onOk={() => location.reload()}
-        okText={intl.formatMessage(messages.reloadOverseerr)}
-        backgroundClickable={false}
-      >
-        {intl.formatMessage(messages.newversionDescription)}
-      </Modal>
-    </Transition>
-  );
-};
-
-export default StatusChecker;
diff --git a/src/components/StatusChecker/index.tsx b/src/components/StatusChecker/index.tsx
new file mode 100644
index 00000000..2a3977fd
--- /dev/null
+++ b/src/components/StatusChecker/index.tsx
@@ -0,0 +1,92 @@
+import Modal from '@app/components/Common/Modal';
+import useSettings from '@app/hooks/useSettings';
+import { Permission, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import { Transition } from '@headlessui/react';
+import type { StatusResponse } from '@server/interfaces/api/settingsInterfaces';
+import { Fragment, useEffect, useState } from 'react';
+import { defineMessages, useIntl } from 'react-intl';
+import useSWR from 'swr';
+
+const messages = defineMessages({
+  appUpdated: '{applicationTitle} Updated',
+  appUpdatedDescription:
+    'Please click the button below to reload the application.',
+  reloadApp: 'Reload {applicationTitle}',
+  restartRequired: 'Server Restart Required',
+  restartRequiredDescription:
+    'Please restart the server to apply the updated settings.',
+});
+
+const StatusChecker = () => {
+  const intl = useIntl();
+  const settings = useSettings();
+  const { hasPermission } = useUser();
+  const { data, error } = useSWR<StatusResponse>('/api/v1/status', {
+    refreshInterval: 60 * 1000,
+  });
+  const [alertDismissed, setAlertDismissed] = useState(false);
+
+  useEffect(() => {
+    if (!data?.restartRequired) {
+      setAlertDismissed(false);
+    }
+  }, [data?.restartRequired]);
+
+  if (!data && !error) {
+    return null;
+  }
+
+  if (!data) {
+    return null;
+  }
+
+  return (
+    <Transition
+      as={Fragment}
+      enter="opacity-0 transition duration-300"
+      enterFrom="opacity-0"
+      enterTo="opacity-100"
+      leave="opacity-100 transition duration-300"
+      leaveFrom="opacity-100"
+      leaveTo="opacity-0"
+      appear
+      show={
+        !alertDismissed &&
+        ((hasPermission(Permission.ADMIN) && data.restartRequired) ||
+          data.commitTag !== process.env.commitTag)
+      }
+    >
+      {hasPermission(Permission.ADMIN) && data.restartRequired ? (
+        <Modal
+          title={intl.formatMessage(messages.restartRequired)}
+          backgroundClickable={false}
+          onOk={() => {
+            setAlertDismissed(true);
+            if (data.commitTag !== process.env.commitTag) {
+              location.reload();
+            }
+          }}
+          okText={intl.formatMessage(globalMessages.close)}
+        >
+          {intl.formatMessage(messages.restartRequiredDescription)}
+        </Modal>
+      ) : (
+        <Modal
+          title={intl.formatMessage(messages.appUpdated, {
+            applicationTitle: settings.currentSettings.applicationTitle,
+          })}
+          onOk={() => location.reload()}
+          okText={intl.formatMessage(messages.reloadApp, {
+            applicationTitle: settings.currentSettings.applicationTitle,
+          })}
+          backgroundClickable={false}
+        >
+          {intl.formatMessage(messages.appUpdatedDescription)}
+        </Modal>
+      )}
+    </Transition>
+  );
+};
+
+export default StatusChecker;
diff --git a/src/components/TitleCard/ErrorCard.tsx b/src/components/TitleCard/ErrorCard.tsx
new file mode 100644
index 00000000..b244fb6d
--- /dev/null
+++ b/src/components/TitleCard/ErrorCard.tsx
@@ -0,0 +1,131 @@
+import Button from '@app/components/Common/Button';
+import globalMessages from '@app/i18n/globalMessages';
+import { CheckIcon, TrashIcon } from '@heroicons/react/solid';
+import axios from 'axios';
+import { defineMessages, useIntl } from 'react-intl';
+import { mutate } from 'swr';
+
+interface ErrorCardProps {
+  id: number;
+  tmdbId: number;
+  tvdbId?: number;
+  type: 'movie' | 'tv';
+  canExpand?: boolean;
+}
+
+const messages = defineMessages({
+  mediaerror: '{mediaType} Not Found',
+  tmdbid: 'TMDB ID',
+  tvdbid: 'TheTVDB ID',
+  cleardata: 'Clear Data',
+});
+
+const Error = ({ id, tmdbId, tvdbId, type, canExpand }: ErrorCardProps) => {
+  const intl = useIntl();
+
+  const deleteMedia = async () => {
+    await axios.delete(`/api/v1/media/${id}`);
+    mutate('/api/v1/media?filter=allavailable&take=20&sort=mediaAdded');
+    mutate('/api/v1/request?filter=all&take=10&sort=modified&skip=0');
+  };
+
+  return (
+    <div
+      className={canExpand ? 'w-full' : 'w-36 sm:w-36 md:w-44'}
+      data-testid="title-card"
+    >
+      <div
+        className="relative transform-gpu cursor-default overflow-hidden rounded-xl bg-gray-800 bg-cover shadow outline-none ring-1 ring-gray-700  transition duration-300"
+        style={{
+          paddingBottom: '150%',
+        }}
+      >
+        <div className="absolute inset-0 h-full w-full overflow-hidden">
+          <div className="absolute left-0 right-0 flex items-center justify-between p-2">
+            <div
+              className={`pointer-events-none z-40 rounded-full shadow ${
+                type === 'movie' ? 'bg-blue-500' : 'bg-purple-600'
+              }`}
+            >
+              <div className="flex h-4 items-center px-2 py-2 text-center text-xs font-medium uppercase tracking-wider text-white sm:h-5">
+                {type === 'movie'
+                  ? intl.formatMessage(globalMessages.movie)
+                  : intl.formatMessage(globalMessages.tvshow)}
+              </div>
+            </div>
+            <div className="pointer-events-none z-40">
+              <div className="flex h-4 w-4 items-center justify-center rounded-full bg-green-400 text-white shadow sm:h-5 sm:w-5">
+                <CheckIcon className="h-3 w-3 sm:h-4 sm:w-4" />
+              </div>
+            </div>
+          </div>
+
+          <div className="flex h-full w-full items-end">
+            <div className="px-2 pb-11 text-white">
+              <h1
+                className="whitespace-normal text-xl font-bold leading-tight"
+                style={{
+                  WebkitLineClamp: 3,
+                  display: '-webkit-box',
+                  overflow: 'hidden',
+                  WebkitBoxOrient: 'vertical',
+                  wordBreak: 'break-word',
+                }}
+                data-testid="title-card-title"
+              >
+                {intl.formatMessage(messages.mediaerror, {
+                  mediaType: intl.formatMessage(
+                    type === 'movie'
+                      ? globalMessages.movie
+                      : globalMessages.tvshow
+                  ),
+                })}
+              </h1>
+              <div
+                className="whitespace-normal text-xs"
+                style={{
+                  WebkitLineClamp: 3,
+                  display: '-webkit-box',
+                  overflow: 'hidden',
+                  WebkitBoxOrient: 'vertical',
+                  wordBreak: 'break-word',
+                }}
+              >
+                <div className="flex items-center">
+                  <span className="mr-2 font-bold text-gray-400">
+                    {intl.formatMessage(messages.tmdbid)}
+                  </span>
+                  {tmdbId}
+                </div>
+                {!!tvdbId && (
+                  <div className="mt-2 flex items-center sm:mt-1">
+                    <span className="mr-2 font-bold text-gray-400">
+                      {intl.formatMessage(messages.tvdbid)}
+                    </span>
+                    {tvdbId}
+                  </div>
+                )}
+              </div>
+            </div>
+          </div>
+
+          <div className="absolute bottom-0 left-0 right-0 flex justify-between px-2 py-2">
+            <Button
+              buttonType="danger"
+              buttonSize="sm"
+              onClick={(e) => {
+                e.preventDefault();
+                deleteMedia();
+              }}
+              className="h-7 w-full"
+            >
+              <TrashIcon />
+              <span>{intl.formatMessage(messages.cleardata)}</span>
+            </Button>
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+};
+export default Error;
diff --git a/src/components/TitleCard/Placeholder.tsx b/src/components/TitleCard/Placeholder.tsx
index 14148ddf..bf19f467 100644
--- a/src/components/TitleCard/Placeholder.tsx
+++ b/src/components/TitleCard/Placeholder.tsx
@@ -1,10 +1,8 @@
-import React from 'react';
-
 interface PlaceholderProps {
   canExpand?: boolean;
 }
 
-const Placeholder: React.FC<PlaceholderProps> = ({ canExpand = false }) => {
+const Placeholder = ({ canExpand = false }: PlaceholderProps) => {
   return (
     <div
       className={`relative animate-pulse rounded-xl bg-gray-700 ${
diff --git a/src/components/TitleCard/TmdbTitleCard.tsx b/src/components/TitleCard/TmdbTitleCard.tsx
index a783037a..f031c997 100644
--- a/src/components/TitleCard/TmdbTitleCard.tsx
+++ b/src/components/TitleCard/TmdbTitleCard.tsx
@@ -1,20 +1,31 @@
-import React from 'react';
+import TitleCard from '@app/components/TitleCard';
+import { Permission, useUser } from '@app/hooks/useUser';
+import type { MovieDetails } from '@server/models/Movie';
+import type { TvDetails } from '@server/models/Tv';
 import { useInView } from 'react-intersection-observer';
 import useSWR from 'swr';
-import TitleCard from '.';
-import type { MovieDetails } from '../../../server/models/Movie';
-import type { TvDetails } from '../../../server/models/Tv';
 
-interface TmdbTitleCardProps {
+export interface TmdbTitleCardProps {
+  id: number;
   tmdbId: number;
+  tvdbId?: number;
   type: 'movie' | 'tv';
+  canExpand?: boolean;
 }
 
 const isMovie = (movie: MovieDetails | TvDetails): movie is MovieDetails => {
   return (movie as MovieDetails).title !== undefined;
 };
 
-const TmdbTitleCard: React.FC<TmdbTitleCardProps> = ({ tmdbId, type }) => {
+const TmdbTitleCard = ({
+  id,
+  tmdbId,
+  tvdbId,
+  type,
+  canExpand,
+}: TmdbTitleCardProps) => {
+  const { hasPermission } = useUser();
+
   const { ref, inView } = useInView({
     triggerOnce: true,
   });
@@ -27,13 +38,20 @@ const TmdbTitleCard: React.FC<TmdbTitleCardProps> = ({ tmdbId, type }) => {
   if (!title && !error) {
     return (
       <div ref={ref}>
-        <TitleCard.Placeholder />
+        <TitleCard.Placeholder canExpand={canExpand} />
       </div>
     );
   }
 
   if (!title) {
-    return <TitleCard.Placeholder />;
+    return hasPermission(Permission.ADMIN) ? (
+      <TitleCard.ErrorCard
+        id={id}
+        tmdbId={tmdbId}
+        tvdbId={tvdbId}
+        type={type}
+      />
+    ) : null;
   }
 
   return isMovie(title) ? (
@@ -46,6 +64,7 @@ const TmdbTitleCard: React.FC<TmdbTitleCardProps> = ({ tmdbId, type }) => {
       userScore={title.voteAverage}
       year={title.releaseDate}
       mediaType={'movie'}
+      canExpand={canExpand}
     />
   ) : (
     <TitleCard
@@ -57,6 +76,7 @@ const TmdbTitleCard: React.FC<TmdbTitleCardProps> = ({ tmdbId, type }) => {
       userScore={title.voteAverage}
       year={title.firstAirDate}
       mediaType={'tv'}
+      canExpand={canExpand}
     />
   );
 };
diff --git a/src/components/TitleCard/index.tsx b/src/components/TitleCard/index.tsx
index df95cc31..f5f69605 100644
--- a/src/components/TitleCard/index.tsx
+++ b/src/components/TitleCard/index.tsx
@@ -1,20 +1,21 @@
+import Spinner from '@app/assets/spinner.svg';
+import Button from '@app/components/Common/Button';
+import CachedImage from '@app/components/Common/CachedImage';
+import RequestModal from '@app/components/RequestModal';
+import ErrorCard from '@app/components/TitleCard/ErrorCard';
+import Placeholder from '@app/components/TitleCard/Placeholder';
+import { useIsTouch } from '@app/hooks/useIsTouch';
+import { Permission, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import { withProperties } from '@app/utils/typeHelpers';
+import { Transition } from '@headlessui/react';
 import { DownloadIcon } from '@heroicons/react/outline';
 import { BellIcon, CheckIcon, ClockIcon } from '@heroicons/react/solid';
+import { MediaStatus } from '@server/constants/media';
+import type { MediaType } from '@server/models/Search';
 import Link from 'next/link';
-import React, { useCallback, useEffect, useState } from 'react';
+import { Fragment, useCallback, useEffect, useState } from 'react';
 import { useIntl } from 'react-intl';
-import { MediaStatus } from '../../../server/constants/media';
-import type { MediaType } from '../../../server/models/Search';
-import Spinner from '../../assets/spinner.svg';
-import { useIsTouch } from '../../hooks/useIsTouch';
-import { Permission, useUser } from '../../hooks/useUser';
-import globalMessages from '../../i18n/globalMessages';
-import { withProperties } from '../../utils/typeHelpers';
-import Button from '../Common/Button';
-import CachedImage from '../Common/CachedImage';
-import RequestModal from '../RequestModal';
-import Transition from '../Transition';
-import Placeholder from './Placeholder';
 
 interface TitleCardProps {
   id: number;
@@ -29,7 +30,7 @@ interface TitleCardProps {
   inProgress?: boolean;
 }
 
-const TitleCard: React.FC<TitleCardProps> = ({
+const TitleCard = ({
   id,
   image,
   summary,
@@ -39,7 +40,7 @@ const TitleCard: React.FC<TitleCardProps> = ({
   mediaType,
   inProgress = false,
   canExpand = false,
-}) => {
+}: TitleCardProps) => {
   const isTouch = useIsTouch();
   const intl = useIntl();
   const { hasPermission } = useUser();
@@ -78,7 +79,10 @@ const TitleCard: React.FC<TitleCardProps> = ({
   );
 
   return (
-    <div className={canExpand ? 'w-full' : 'w-36 sm:w-36 md:w-44'}>
+    <div
+      className={canExpand ? 'w-full' : 'w-36 sm:w-36 md:w-44'}
+      data-testid="title-card"
+    >
       <RequestModal
         tmdbId={id}
         show={showRequestModal}
@@ -159,6 +163,7 @@ const TitleCard: React.FC<TitleCardProps> = ({
             </div>
           </div>
           <Transition
+            as={Fragment}
             show={isUpdating}
             enter="transition ease-in-out duration-300 transform opacity-0"
             enterFrom="opacity-0"
@@ -173,6 +178,7 @@ const TitleCard: React.FC<TitleCardProps> = ({
           </Transition>
 
           <Transition
+            as={Fragment}
             show={!image || showDetail || showRequestModal}
             enter="transition transform opacity-0"
             enterFrom="opacity-0"
@@ -212,6 +218,7 @@ const TitleCard: React.FC<TitleCardProps> = ({
                           WebkitBoxOrient: 'vertical',
                           wordBreak: 'break-word',
                         }}
+                        data-testid="title-card-title"
                       >
                         {title}
                       </h1>
@@ -262,4 +269,4 @@ const TitleCard: React.FC<TitleCardProps> = ({
   );
 };
 
-export default withProperties(TitleCard, { Placeholder });
+export default withProperties(TitleCard, { Placeholder, ErrorCard });
diff --git a/src/components/Toast/index.tsx b/src/components/Toast/index.tsx
index 39d8e68b..062b0ba6 100644
--- a/src/components/Toast/index.tsx
+++ b/src/components/Toast/index.tsx
@@ -1,3 +1,4 @@
+import { Transition } from '@headlessui/react';
 import {
   CheckCircleIcon,
   ExclamationCircleIcon,
@@ -5,19 +6,19 @@ import {
   InformationCircleIcon,
 } from '@heroicons/react/outline';
 import { XIcon } from '@heroicons/react/solid';
-import React from 'react';
+import { Fragment } from 'react';
 import type { ToastProps } from 'react-toast-notifications';
-import Transition from '../Transition';
 
-const Toast: React.FC<ToastProps> = ({
+const Toast = ({
   appearance,
   children,
   onDismiss,
   transitionState,
-}) => {
+}: ToastProps) => {
   return (
     <div className="toast pointer-events-none flex max-w-full items-end justify-center px-2 py-2 sm:items-start sm:justify-end">
       <Transition
+        as={Fragment}
         show={transitionState === 'entered'}
         enter="transition duration-300 transform-gpu"
         enterFrom="opacity-0 scale-95"
diff --git a/src/components/ToastContainer/index.tsx b/src/components/ToastContainer/index.tsx
index e9e048c4..55233a9f 100644
--- a/src/components/ToastContainer/index.tsx
+++ b/src/components/ToastContainer/index.tsx
@@ -1,10 +1,6 @@
-import React from 'react';
-import { ToastContainerProps } from 'react-toast-notifications';
+import type { ToastContainerProps } from 'react-toast-notifications';
 
-const ToastContainer: React.FC<ToastContainerProps> = ({
-  hasToasts,
-  ...props
-}) => {
+const ToastContainer = ({ hasToasts, ...props }: ToastContainerProps) => {
   return (
     <div
       id="toast-container"
diff --git a/src/components/Transition/index.tsx b/src/components/Transition/index.tsx
deleted file mode 100644
index 0b940a5e..00000000
--- a/src/components/Transition/index.tsx
+++ /dev/null
@@ -1,124 +0,0 @@
-import React from 'react';
-import { CSSTransition as ReactCSSTransition } from 'react-transition-group';
-import { useRef, useEffect, useContext } from 'react';
-
-interface CSSTransitionProps {
-  show?: boolean;
-  enter?: string;
-  enterFrom?: string;
-  enterTo?: string;
-  leave?: string;
-  leaveFrom?: string;
-  leaveTo?: string;
-  appear?: boolean;
-}
-
-const TransitionContext = React.createContext<{
-  parent: { show?: boolean; isInitialRender?: boolean; appear?: boolean };
-}>({
-  parent: {},
-});
-
-function useIsInitialRender() {
-  const isInitialRender = useRef(true);
-  useEffect(() => {
-    isInitialRender.current = false;
-  }, []);
-  return isInitialRender.current;
-}
-
-const CSSTransition: React.FC<CSSTransitionProps> = ({
-  show,
-  enter = '',
-  enterFrom = '',
-  enterTo = '',
-  leave = '',
-  leaveFrom = '',
-  leaveTo = '',
-  appear,
-  children,
-}) => {
-  const enterClasses = enter.split(' ').filter((s) => s.length);
-  const enterFromClasses = enterFrom.split(' ').filter((s) => s.length);
-  const enterToClasses = enterTo.split(' ').filter((s) => s.length);
-  const leaveClasses = leave.split(' ').filter((s) => s.length);
-  const leaveFromClasses = leaveFrom.split(' ').filter((s) => s.length);
-  const leaveToClasses = leaveTo.split(' ').filter((s) => s.length);
-
-  const addClasses = (node: HTMLElement, classes: string[]) => {
-    classes.length && node.classList.add(...classes);
-  };
-
-  const removeClasses = (node: HTMLElement, classes: string[]) => {
-    classes.length && node.classList.remove(...classes);
-  };
-
-  return (
-    <ReactCSSTransition
-      appear={appear}
-      unmountOnExit
-      in={show}
-      addEndListener={(node, done) => {
-        node.addEventListener('transitionend', done, false);
-      }}
-      onEnter={(node: HTMLElement) => {
-        addClasses(node, [...enterClasses, ...enterFromClasses]);
-      }}
-      onEntering={(node: HTMLElement) => {
-        removeClasses(node, enterFromClasses);
-        addClasses(node, enterToClasses);
-      }}
-      onEntered={(node: HTMLElement) => {
-        removeClasses(node, [...enterToClasses, ...enterClasses]);
-      }}
-      onExit={(node) => {
-        addClasses(node, [...leaveClasses, ...leaveFromClasses]);
-      }}
-      onExiting={(node) => {
-        removeClasses(node, leaveFromClasses);
-        addClasses(node, leaveToClasses);
-      }}
-      onExited={(node) => {
-        removeClasses(node, [...leaveToClasses, ...leaveClasses]);
-      }}
-    >
-      {children}
-    </ReactCSSTransition>
-  );
-};
-
-const Transition: React.FC<CSSTransitionProps> = ({
-  show,
-  appear,
-  ...rest
-}) => {
-  const { parent } = useContext(TransitionContext);
-  const isInitialRender = useIsInitialRender();
-  const isChild = show === undefined;
-
-  if (isChild) {
-    return (
-      <CSSTransition
-        appear={parent.appear || !parent.isInitialRender}
-        show={parent.show}
-        {...rest}
-      />
-    );
-  }
-
-  return (
-    <TransitionContext.Provider
-      value={{
-        parent: {
-          show,
-          isInitialRender,
-          appear,
-        },
-      }}
-    >
-      <CSSTransition appear={appear} show={show} {...rest} />
-    </TransitionContext.Provider>
-  );
-};
-
-export default Transition;
diff --git a/src/components/TvDetails/Season/index.tsx b/src/components/TvDetails/Season/index.tsx
new file mode 100644
index 00000000..a8f45764
--- /dev/null
+++ b/src/components/TvDetails/Season/index.tsx
@@ -0,0 +1,62 @@
+import AirDateBadge from '@app/components/AirDateBadge';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import type { SeasonWithEpisodes } from '@server/models/Tv';
+import { defineMessages, useIntl } from 'react-intl';
+import useSWR from 'swr';
+
+const messages = defineMessages({
+  somethingwentwrong: 'Something went wrong while retrieving season data.',
+});
+
+type SeasonProps = {
+  seasonNumber: number;
+  tvId: number;
+};
+
+const Season = ({ seasonNumber, tvId }: SeasonProps) => {
+  const intl = useIntl();
+  const { data, error } = useSWR<SeasonWithEpisodes>(
+    `/api/v1/tv/${tvId}/season/${seasonNumber}`
+  );
+
+  if (!data && !error) {
+    return <LoadingSpinner />;
+  }
+
+  if (!data) {
+    return <div>{intl.formatMessage(messages.somethingwentwrong)}</div>;
+  }
+
+  return (
+    <div className="flex flex-col justify-center divide-y divide-gray-700">
+      {data.episodes
+        .slice()
+        .reverse()
+        .map((episode) => {
+          return (
+            <div
+              className="flex flex-col space-y-4 py-4 xl:flex-row xl:space-y-4 xl:space-x-4"
+              key={`season-${seasonNumber}-episode-${episode.episodeNumber}`}
+            >
+              <div className="flex-1">
+                <div className="flex flex-col space-y-2 xl:flex-row xl:items-center xl:space-y-0 xl:space-x-2">
+                  <h3 className="text-lg">{episode.name}</h3>
+                  <AirDateBadge airDate={episode.airDate} />
+                </div>
+                {episode.overview && <p>{episode.overview}</p>}
+              </div>
+              {episode.stillPath && (
+                <img
+                  className="h-auto w-full rounded-lg xl:h-32 xl:w-auto"
+                  src={`https://image.tmdb.org/t/p/original/${episode.stillPath}`}
+                  alt=""
+                />
+              )}
+            </div>
+          );
+        })}
+    </div>
+  );
+};
+
+export default Season;
diff --git a/src/components/TvDetails/TvCast/index.tsx b/src/components/TvDetails/TvCast/index.tsx
index 9631ad49..4c7697aa 100644
--- a/src/components/TvDetails/TvCast/index.tsx
+++ b/src/components/TvDetails/TvCast/index.tsx
@@ -1,20 +1,19 @@
+import Header from '@app/components/Common/Header';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import PersonCard from '@app/components/PersonCard';
+import Error from '@app/pages/_error';
+import type { TvDetails } from '@server/models/Tv';
 import Link from 'next/link';
 import { useRouter } from 'next/router';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import type { TvDetails } from '../../../../server/models/Tv';
-import Error from '../../../pages/_error';
-import Header from '../../Common/Header';
-import LoadingSpinner from '../../Common/LoadingSpinner';
-import PageTitle from '../../Common/PageTitle';
-import PersonCard from '../../PersonCard';
 
 const messages = defineMessages({
   fullseriescast: 'Full Series Cast',
 });
 
-const TvCast: React.FC = () => {
+const TvCast = () => {
   const router = useRouter();
   const intl = useIntl();
   const { data, error } = useSWR<TvDetails>(`/api/v1/tv/${router.query.tvId}`);
diff --git a/src/components/TvDetails/TvCrew/index.tsx b/src/components/TvDetails/TvCrew/index.tsx
index 5ed0297d..a6a65e96 100644
--- a/src/components/TvDetails/TvCrew/index.tsx
+++ b/src/components/TvDetails/TvCrew/index.tsx
@@ -1,20 +1,19 @@
+import Header from '@app/components/Common/Header';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import PersonCard from '@app/components/PersonCard';
+import Error from '@app/pages/_error';
+import type { TvDetails } from '@server/models/Tv';
 import Link from 'next/link';
 import { useRouter } from 'next/router';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import type { TvDetails } from '../../../../server/models/Tv';
-import Error from '../../../pages/_error';
-import Header from '../../Common/Header';
-import LoadingSpinner from '../../Common/LoadingSpinner';
-import PageTitle from '../../Common/PageTitle';
-import PersonCard from '../../PersonCard';
 
 const messages = defineMessages({
   fullseriescrew: 'Full Series Crew',
 });
 
-const TvCrew: React.FC = () => {
+const TvCrew = () => {
   const router = useRouter();
   const intl = useIntl();
   const { data, error } = useSWR<TvDetails>(`/api/v1/tv/${router.query.tvId}`);
diff --git a/src/components/TvDetails/TvRecommendations.tsx b/src/components/TvDetails/TvRecommendations.tsx
index 94e6f761..4ecbd248 100644
--- a/src/components/TvDetails/TvRecommendations.tsx
+++ b/src/components/TvDetails/TvRecommendations.tsx
@@ -1,21 +1,20 @@
+import Header from '@app/components/Common/Header';
+import ListView from '@app/components/Common/ListView';
+import PageTitle from '@app/components/Common/PageTitle';
+import useDiscover from '@app/hooks/useDiscover';
+import Error from '@app/pages/_error';
+import type { TvResult } from '@server/models/Search';
+import type { TvDetails } from '@server/models/Tv';
 import Link from 'next/link';
 import { useRouter } from 'next/router';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import type { TvResult } from '../../../server/models/Search';
-import { TvDetails } from '../../../server/models/Tv';
-import useDiscover from '../../hooks/useDiscover';
-import Error from '../../pages/_error';
-import Header from '../Common/Header';
-import ListView from '../Common/ListView';
-import PageTitle from '../Common/PageTitle';
 
 const messages = defineMessages({
   recommendations: 'Recommendations',
 });
 
-const TvRecommendations: React.FC = () => {
+const TvRecommendations = () => {
   const router = useRouter();
   const intl = useIntl();
   const { data: tvData } = useSWR<TvDetails>(`/api/v1/tv/${router.query.tvId}`);
diff --git a/src/components/TvDetails/TvSimilar.tsx b/src/components/TvDetails/TvSimilar.tsx
index a8214747..fb254a51 100644
--- a/src/components/TvDetails/TvSimilar.tsx
+++ b/src/components/TvDetails/TvSimilar.tsx
@@ -1,21 +1,20 @@
+import Header from '@app/components/Common/Header';
+import ListView from '@app/components/Common/ListView';
+import PageTitle from '@app/components/Common/PageTitle';
+import useDiscover from '@app/hooks/useDiscover';
+import Error from '@app/pages/_error';
+import type { TvResult } from '@server/models/Search';
+import type { TvDetails } from '@server/models/Tv';
 import Link from 'next/link';
 import { useRouter } from 'next/router';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import type { TvResult } from '../../../server/models/Search';
-import type { TvDetails } from '../../../server/models/Tv';
-import useDiscover from '../../hooks/useDiscover';
-import Error from '../../pages/_error';
-import Header from '../Common/Header';
-import ListView from '../Common/ListView';
-import PageTitle from '../Common/PageTitle';
 
 const messages = defineMessages({
   similar: 'Similar Series',
 });
 
-const TvSimilar: React.FC = () => {
+const TvSimilar = () => {
   const router = useRouter();
   const intl = useIntl();
   const { data: tvData } = useSWR<TvDetails>(`/api/v1/tv/${router.query.tvId}`);
diff --git a/src/components/TvDetails/index.tsx b/src/components/TvDetails/index.tsx
index 64327648..50643aa1 100644
--- a/src/components/TvDetails/index.tsx
+++ b/src/components/TvDetails/index.tsx
@@ -1,3 +1,34 @@
+import RTAudFresh from '@app/assets/rt_aud_fresh.svg';
+import RTAudRotten from '@app/assets/rt_aud_rotten.svg';
+import RTFresh from '@app/assets/rt_fresh.svg';
+import RTRotten from '@app/assets/rt_rotten.svg';
+import TmdbLogo from '@app/assets/tmdb_logo.svg';
+import Badge from '@app/components/Common/Badge';
+import Button from '@app/components/Common/Button';
+import CachedImage from '@app/components/Common/CachedImage';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import type { PlayButtonLink } from '@app/components/Common/PlayButton';
+import PlayButton from '@app/components/Common/PlayButton';
+import StatusBadgeMini from '@app/components/Common/StatusBadgeMini';
+import Tooltip from '@app/components/Common/Tooltip';
+import ExternalLinkBlock from '@app/components/ExternalLinkBlock';
+import IssueModal from '@app/components/IssueModal';
+import ManageSlideOver from '@app/components/ManageSlideOver';
+import MediaSlider from '@app/components/MediaSlider';
+import PersonCard from '@app/components/PersonCard';
+import RequestButton from '@app/components/RequestButton';
+import RequestModal from '@app/components/RequestModal';
+import Slider from '@app/components/Slider';
+import StatusBadge from '@app/components/StatusBadge';
+import Season from '@app/components/TvDetails/Season';
+import useLocale from '@app/hooks/useLocale';
+import useSettings from '@app/hooks/useSettings';
+import { Permission, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import Error from '@app/pages/_error';
+import { sortCrewPriority } from '@app/utils/creditHelpers';
+import { Disclosure, Transition } from '@headlessui/react';
 import {
   ArrowCircleRightIcon,
   CogIcon,
@@ -5,44 +36,20 @@ import {
   FilmIcon,
   PlayIcon,
 } from '@heroicons/react/outline';
+import { ChevronUpIcon } from '@heroicons/react/solid';
+import type { RTRating } from '@server/api/rottentomatoes';
+import { ANIME_KEYWORD_ID } from '@server/api/themoviedb/constants';
+import { IssueStatus } from '@server/constants/issue';
+import { MediaRequestStatus, MediaStatus } from '@server/constants/media';
+import type { Crew } from '@server/models/common';
+import type { TvDetails as TvDetailsType } from '@server/models/Tv';
 import { hasFlag } from 'country-flag-icons';
 import 'country-flag-icons/3x2/flags.css';
 import Link from 'next/link';
 import { useRouter } from 'next/router';
-import React, { useEffect, useMemo, useState } from 'react';
+import { useEffect, useMemo, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import type { RTRating } from '../../../server/api/rottentomatoes';
-import { ANIME_KEYWORD_ID } from '../../../server/api/themoviedb/constants';
-import { IssueStatus } from '../../../server/constants/issue';
-import { MediaStatus } from '../../../server/constants/media';
-import { Crew } from '../../../server/models/common';
-import { TvDetails as TvDetailsType } from '../../../server/models/Tv';
-import RTAudFresh from '../../assets/rt_aud_fresh.svg';
-import RTAudRotten from '../../assets/rt_aud_rotten.svg';
-import RTFresh from '../../assets/rt_fresh.svg';
-import RTRotten from '../../assets/rt_rotten.svg';
-import TmdbLogo from '../../assets/tmdb_logo.svg';
-import useLocale from '../../hooks/useLocale';
-import useSettings from '../../hooks/useSettings';
-import { Permission, useUser } from '../../hooks/useUser';
-import globalMessages from '../../i18n/globalMessages';
-import Error from '../../pages/_error';
-import { sortCrewPriority } from '../../utils/creditHelpers';
-import Button from '../Common/Button';
-import CachedImage from '../Common/CachedImage';
-import LoadingSpinner from '../Common/LoadingSpinner';
-import PageTitle from '../Common/PageTitle';
-import PlayButton, { PlayButtonLink } from '../Common/PlayButton';
-import ExternalLinkBlock from '../ExternalLinkBlock';
-import IssueModal from '../IssueModal';
-import ManageSlideOver from '../ManageSlideOver';
-import MediaSlider from '../MediaSlider';
-import PersonCard from '../PersonCard';
-import RequestButton from '../RequestButton';
-import RequestModal from '../RequestModal';
-import Slider from '../Slider';
-import StatusBadge from '../StatusBadge';
 
 const messages = defineMessages({
   firstAirDate: 'First Air Date',
@@ -67,13 +74,22 @@ const messages = defineMessages({
   streamingproviders: 'Currently Streaming On',
   productioncountries:
     'Production {countryCount, plural, one {Country} other {Countries}}',
+  reportissue: 'Report an Issue',
+  manageseries: 'Manage Series',
+  seasonstitle: 'Seasons',
+  episodeCount: '{episodeCount, plural, one {# Episode} other {# Episodes}}',
+  seasonnumber: 'Season {seasonNumber}',
+  status4k: '4K {status}',
+  rtcriticsscore: 'Rotten Tomatoes Tomatometer',
+  rtaudiencescore: 'Rotten Tomatoes Audience Score',
+  tmdbuserscore: 'TMDB User Score',
 });
 
 interface TvDetailsProps {
   tv?: TvDetailsType;
 }
 
-const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
+const TvDetails = ({ tv }: TvDetailsProps) => {
   const settings = useSettings();
   const { user, hasPermission } = useUser();
   const router = useRouter();
@@ -106,6 +122,30 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
     setShowManager(router.query.manage == '1' ? true : false);
   }, [router.query.manage]);
 
+  const [plexUrl, setPlexUrl] = useState(data?.mediaInfo?.plexUrl);
+  const [plexUrl4k, setPlexUrl4k] = useState(data?.mediaInfo?.plexUrl4k);
+
+  useEffect(() => {
+    if (data) {
+      if (
+        /iPad|iPhone|iPod/.test(navigator.userAgent) ||
+        (navigator.userAgent === 'MacIntel' && navigator.maxTouchPoints > 1)
+      ) {
+        setPlexUrl(data.mediaInfo?.iOSPlexUrl);
+        setPlexUrl4k(data.mediaInfo?.iOSPlexUrl4k);
+      } else {
+        setPlexUrl(data.mediaInfo?.plexUrl);
+        setPlexUrl4k(data.mediaInfo?.plexUrl4k);
+      }
+    }
+  }, [
+    data,
+    data?.mediaInfo?.iOSPlexUrl,
+    data?.mediaInfo?.iOSPlexUrl4k,
+    data?.mediaInfo?.plexUrl,
+    data?.mediaInfo?.plexUrl4k,
+  ]);
+
   if (!data && !error) {
     return <LoadingSpinner />;
   }
@@ -116,29 +156,24 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
 
   const mediaLinks: PlayButtonLink[] = [];
 
-  if (
-    data.mediaInfo?.plexUrl &&
-    hasPermission([Permission.REQUEST, Permission.REQUEST_TV], {
-      type: 'or',
-    })
-  ) {
+  if (plexUrl) {
     mediaLinks.push({
       text: intl.formatMessage(messages.playonplex),
-      url: data.mediaInfo?.plexUrl,
+      url: plexUrl,
       svg: <PlayIcon />,
     });
   }
 
   if (
     settings.currentSettings.series4kEnabled &&
-    data.mediaInfo?.plexUrl4k &&
+    plexUrl4k &&
     hasPermission([Permission.REQUEST_4K, Permission.REQUEST_4K_TV], {
       type: 'or',
     })
   ) {
     mediaLinks.push({
       text: intl.formatMessage(messages.play4konplex),
-      url: data.mediaInfo?.plexUrl4k,
+      url: plexUrl4k,
       svg: <PlayIcon />,
     });
   }
@@ -205,7 +240,9 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
     seasonCount <=
     (
       data.mediaInfo?.seasons.filter(
-        (season) => season.status === MediaStatus.AVAILABLE
+        (season) =>
+          season.status === MediaStatus.AVAILABLE ||
+          season.status === MediaStatus.PARTIALLY_AVAILABLE
       ) ?? []
     ).length;
 
@@ -213,7 +250,9 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
     seasonCount <=
     (
       data.mediaInfo?.seasons.filter(
-        (season) => season.status4k === MediaStatus.AVAILABLE
+        (season) =>
+          season.status4k === MediaStatus.AVAILABLE ||
+          season.status4k === MediaStatus.PARTIALLY_AVAILABLE
       ) ?? []
     ).length;
 
@@ -299,6 +338,7 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
               tmdbId={data.mediaInfo?.tmdbId}
               mediaType="tv"
               plexUrl={data.mediaInfo?.plexUrl}
+              serviceUrl={data.mediaInfo?.serviceUrl}
             />
             {settings.currentSettings.series4kEnabled &&
               hasPermission(
@@ -320,10 +360,11 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
                   tmdbId={data.mediaInfo?.tmdbId}
                   mediaType="tv"
                   plexUrl={data.mediaInfo?.plexUrl4k}
+                  serviceUrl={data.mediaInfo?.serviceUrl4k}
                 />
               )}
           </div>
-          <h1>
+          <h1 data-testid="media-title">
             {data.name}{' '}
             {data.firstAirDate && (
               <span className="media-year">
@@ -369,38 +410,42 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
                 type: 'or',
               }
             ) && (
+              <Tooltip content={intl.formatMessage(messages.reportissue)}>
+                <Button
+                  buttonType="warning"
+                  onClick={() => setShowIssueModal(true)}
+                  className="ml-2 first:ml-0"
+                >
+                  <ExclamationIcon />
+                </Button>
+              </Tooltip>
+            )}
+          {hasPermission(Permission.MANAGE_REQUESTS) && data.mediaInfo && (
+            <Tooltip content={intl.formatMessage(messages.manageseries)}>
               <Button
-                buttonType="warning"
-                className="ml-2 first:ml-0"
-                onClick={() => setShowIssueModal(true)}
+                buttonType="ghost"
+                onClick={() => setShowManager(true)}
+                className="relative ml-2 first:ml-0"
               >
-                <ExclamationIcon className="w-5" />
+                <CogIcon className="!mr-0" />
+                {hasPermission(
+                  [Permission.MANAGE_ISSUES, Permission.VIEW_ISSUES],
+                  {
+                    type: 'or',
+                  }
+                ) &&
+                  (
+                    data.mediaInfo?.issues.filter(
+                      (issue) => issue.status === IssueStatus.OPEN
+                    ) ?? []
+                  ).length > 0 && (
+                    <>
+                      <div className="absolute -right-1 -top-1 h-3 w-3 rounded-full bg-red-600" />
+                      <div className="absolute -right-1 -top-1 h-3 w-3 animate-ping rounded-full bg-red-600" />
+                    </>
+                  )}
               </Button>
-            )}
-          {hasPermission(Permission.MANAGE_REQUESTS) && data.mediaInfo && (
-            <Button
-              buttonType="default"
-              className="relative ml-2 first:ml-0"
-              onClick={() => setShowManager(true)}
-            >
-              <CogIcon className="!mr-0" />
-              {hasPermission(
-                [Permission.MANAGE_ISSUES, Permission.VIEW_ISSUES],
-                {
-                  type: 'or',
-                }
-              ) &&
-                (
-                  data.mediaInfo?.issues.filter(
-                    (issue) => issue.status === IssueStatus.OPEN
-                  ) ?? []
-                ).length > 0 && (
-                  <>
-                    <div className="absolute -right-1 -top-1 h-3 w-3 rounded-full bg-red-600" />
-                    <div className="absolute -right-1 -top-1 h-3 w-3 animate-ping rounded-full bg-red-600" />
-                  </>
-                )}
-            </Button>
+            </Tooltip>
           )}
         </div>
       </div>
@@ -449,6 +494,248 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
               </div>
             </>
           )}
+          <h2 className="py-4">{intl.formatMessage(messages.seasonstitle)}</h2>
+          <div className="flex w-full flex-col space-y-2">
+            {data.seasons
+              .slice()
+              .reverse()
+              .filter((season) => season.seasonNumber !== 0)
+              .map((season) => {
+                const show4k =
+                  settings.currentSettings.series4kEnabled &&
+                  hasPermission(
+                    [
+                      Permission.MANAGE_REQUESTS,
+                      Permission.REQUEST_4K,
+                      Permission.REQUEST_4K_TV,
+                    ],
+                    {
+                      type: 'or',
+                    }
+                  );
+                const mSeason = (data.mediaInfo?.seasons ?? []).find(
+                  (s) =>
+                    season.seasonNumber === s.seasonNumber &&
+                    s.status !== MediaStatus.UNKNOWN
+                );
+                const mSeason4k = (data.mediaInfo?.seasons ?? []).find(
+                  (s) =>
+                    season.seasonNumber === s.seasonNumber &&
+                    s.status4k !== MediaStatus.UNKNOWN
+                );
+                const request = (data.mediaInfo?.requests ?? []).find(
+                  (r) =>
+                    !!r.seasons.find(
+                      (s) => s.seasonNumber === season.seasonNumber
+                    ) && !r.is4k
+                );
+                const request4k = (data.mediaInfo?.requests ?? []).find(
+                  (r) =>
+                    !!r.seasons.find(
+                      (s) => s.seasonNumber === season.seasonNumber
+                    ) && r.is4k
+                );
+
+                return (
+                  <Disclosure key={`season-discoslure-${season.seasonNumber}`}>
+                    {({ open }) => (
+                      <>
+                        <Disclosure.Button
+                          className={`mt-2 flex w-full items-center justify-between space-x-2 border-gray-700 bg-gray-800 px-4 py-2 text-gray-200 ${
+                            open
+                              ? 'rounded-t-md border-t border-l border-r'
+                              : 'rounded-md border'
+                          }`}
+                        >
+                          <div className="flex flex-1 items-center space-x-2 text-lg">
+                            <span>
+                              {intl.formatMessage(messages.seasonnumber, {
+                                seasonNumber: season.seasonNumber,
+                              })}
+                            </span>
+                            <Badge badgeType="dark">
+                              {intl.formatMessage(messages.episodeCount, {
+                                episodeCount: season.episodeCount,
+                              })}
+                            </Badge>
+                          </div>
+                          {((!mSeason &&
+                            request?.status === MediaRequestStatus.APPROVED) ||
+                            mSeason?.status === MediaStatus.PROCESSING) && (
+                            <>
+                              <div className="hidden md:flex">
+                                <Badge badgeType="primary">
+                                  {intl.formatMessage(globalMessages.requested)}
+                                </Badge>
+                              </div>
+                              <div className="flex md:hidden">
+                                <StatusBadgeMini
+                                  status={MediaStatus.PROCESSING}
+                                />
+                              </div>
+                            </>
+                          )}
+                          {((!mSeason &&
+                            request?.status === MediaRequestStatus.PENDING) ||
+                            mSeason?.status === MediaStatus.PENDING) && (
+                            <>
+                              <div className="hidden md:flex">
+                                <Badge badgeType="warning">
+                                  {intl.formatMessage(globalMessages.pending)}
+                                </Badge>
+                              </div>
+                              <div className="flex md:hidden">
+                                <StatusBadgeMini status={MediaStatus.PENDING} />
+                              </div>
+                            </>
+                          )}
+                          {mSeason?.status ===
+                            MediaStatus.PARTIALLY_AVAILABLE && (
+                            <>
+                              <div className="hidden md:flex">
+                                <Badge badgeType="success">
+                                  {intl.formatMessage(
+                                    globalMessages.partiallyavailable
+                                  )}
+                                </Badge>
+                              </div>
+                              <div className="flex md:hidden">
+                                <StatusBadgeMini
+                                  status={MediaStatus.PARTIALLY_AVAILABLE}
+                                />
+                              </div>
+                            </>
+                          )}
+                          {mSeason?.status === MediaStatus.AVAILABLE && (
+                            <>
+                              <div className="hidden md:flex">
+                                <Badge badgeType="success">
+                                  {intl.formatMessage(globalMessages.available)}
+                                </Badge>
+                              </div>
+                              <div className="flex md:hidden">
+                                <StatusBadgeMini
+                                  status={MediaStatus.AVAILABLE}
+                                />
+                              </div>
+                            </>
+                          )}
+                          {((!mSeason4k &&
+                            request4k?.status ===
+                              MediaRequestStatus.APPROVED) ||
+                            mSeason4k?.status4k === MediaStatus.PROCESSING) &&
+                            show4k && (
+                              <>
+                                <div className="hidden md:flex">
+                                  <Badge badgeType="primary">
+                                    {intl.formatMessage(messages.status4k, {
+                                      status: intl.formatMessage(
+                                        globalMessages.requested
+                                      ),
+                                    })}
+                                  </Badge>
+                                </div>
+                                <div className="flex md:hidden">
+                                  <StatusBadgeMini
+                                    status={MediaStatus.PROCESSING}
+                                    is4k={true}
+                                  />
+                                </div>
+                              </>
+                            )}
+                          {((!mSeason4k &&
+                            request4k?.status === MediaRequestStatus.PENDING) ||
+                            mSeason?.status4k === MediaStatus.PENDING) &&
+                            show4k && (
+                              <>
+                                <div className="hidden md:flex">
+                                  <Badge badgeType="warning">
+                                    {intl.formatMessage(messages.status4k, {
+                                      status: intl.formatMessage(
+                                        globalMessages.pending
+                                      ),
+                                    })}
+                                  </Badge>
+                                </div>
+                                <div className="flex md:hidden">
+                                  <StatusBadgeMini
+                                    status={MediaStatus.PENDING}
+                                    is4k={true}
+                                  />
+                                </div>
+                              </>
+                            )}
+                          {mSeason4k?.status4k ===
+                            MediaStatus.PARTIALLY_AVAILABLE &&
+                            show4k && (
+                              <>
+                                <div className="hidden md:flex">
+                                  <Badge badgeType="success">
+                                    {intl.formatMessage(messages.status4k, {
+                                      status: intl.formatMessage(
+                                        globalMessages.partiallyavailable
+                                      ),
+                                    })}
+                                  </Badge>
+                                </div>
+                                <div className="flex md:hidden">
+                                  <StatusBadgeMini
+                                    status={MediaStatus.PARTIALLY_AVAILABLE}
+                                    is4k={true}
+                                  />
+                                </div>
+                              </>
+                            )}
+                          {mSeason4k?.status4k === MediaStatus.AVAILABLE &&
+                            show4k && (
+                              <>
+                                <div className="hidden md:flex">
+                                  <Badge badgeType="success">
+                                    {intl.formatMessage(messages.status4k, {
+                                      status: intl.formatMessage(
+                                        globalMessages.available
+                                      ),
+                                    })}
+                                  </Badge>
+                                </div>
+                                <div className="flex md:hidden">
+                                  <StatusBadgeMini
+                                    status={MediaStatus.AVAILABLE}
+                                    is4k={true}
+                                  />
+                                </div>
+                              </>
+                            )}
+                          <ChevronUpIcon
+                            className={`${
+                              open ? 'rotate-180 transform' : ''
+                            } h-6 w-6 text-gray-500`}
+                          />
+                        </Disclosure.Button>
+                        <Transition
+                          show={open}
+                          enter="transition duration-100 ease-out"
+                          enterFrom="transform opacity-0"
+                          enterTo="transform opacity-100"
+                          leave="transition duration-75 ease-out"
+                          leaveFrom="transform opacity-100"
+                          leaveTo="transform opacity-0"
+                          // Not sure why this transition is adding a margin without this here
+                          style={{ margin: '0px' }}
+                        >
+                          <Disclosure.Panel className="w-full rounded-b-md border-b border-l border-r border-gray-700 px-4 pb-2">
+                            <Season
+                              tvId={data.id}
+                              seasonNumber={season.seasonNumber}
+                            />
+                          </Disclosure.Panel>
+                        </Transition>
+                      </>
+                    )}
+                  </Disclosure>
+                );
+              })}
+          </div>
         </div>
         <div className="media-overview-right">
           <div className="media-facts">
@@ -457,30 +744,55 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
               (ratingData?.audienceRating && !!ratingData?.audienceScore)) && (
               <div className="media-ratings">
                 {ratingData?.criticsRating && !!ratingData?.criticsScore && (
-                  <span className="media-rating">
-                    {ratingData.criticsRating === 'Rotten' ? (
-                      <RTRotten className="mr-1 w-6" />
-                    ) : (
-                      <RTFresh className="mr-1 w-6" />
-                    )}
-                    {ratingData.criticsScore}%
-                  </span>
+                  <Tooltip
+                    content={intl.formatMessage(messages.rtcriticsscore)}
+                  >
+                    <a
+                      href={ratingData.url}
+                      className="media-rating"
+                      target="_blank"
+                      rel="noreferrer"
+                    >
+                      {ratingData.criticsRating === 'Rotten' ? (
+                        <RTRotten className="mr-1 w-6" />
+                      ) : (
+                        <RTFresh className="mr-1 w-6" />
+                      )}
+                      <span>{ratingData.criticsScore}%</span>
+                    </a>
+                  </Tooltip>
                 )}
                 {ratingData?.audienceRating && !!ratingData?.audienceScore && (
-                  <span className="media-rating">
-                    {ratingData.audienceRating === 'Spilled' ? (
-                      <RTAudRotten className="mr-1 w-6" />
-                    ) : (
-                      <RTAudFresh className="mr-1 w-6" />
-                    )}
-                    {ratingData.audienceScore}%
-                  </span>
+                  <Tooltip
+                    content={intl.formatMessage(messages.rtaudiencescore)}
+                  >
+                    <a
+                      href={ratingData.url}
+                      className="media-rating"
+                      target="_blank"
+                      rel="noreferrer"
+                    >
+                      {ratingData.audienceRating === 'Spilled' ? (
+                        <RTAudRotten className="mr-1 w-6" />
+                      ) : (
+                        <RTAudFresh className="mr-1 w-6" />
+                      )}
+                      <span>{ratingData.audienceScore}%</span>
+                    </a>
+                  </Tooltip>
                 )}
                 {!!data.voteCount && (
-                  <span className="media-rating">
-                    <TmdbLogo className="mr-2 w-6" />
-                    {data.voteAverage}/10
-                  </span>
+                  <Tooltip content={intl.formatMessage(messages.tmdbuserscore)}>
+                    <a
+                      href={`https://www.themoviedb.org/tv/${data.id}?language=${locale}`}
+                      className="media-rating"
+                      target="_blank"
+                      rel="noreferrer"
+                    >
+                      <TmdbLogo className="mr-1 w-6" />
+                      <span>{Math.round(data.voteAverage * 10)}%</span>
+                    </a>
+                  </Tooltip>
                 )}
               </div>
             )}
diff --git a/src/components/UserList/BulkEditModal.tsx b/src/components/UserList/BulkEditModal.tsx
index 1397afa0..148c9c7b 100644
--- a/src/components/UserList/BulkEditModal.tsx
+++ b/src/components/UserList/BulkEditModal.tsx
@@ -1,12 +1,12 @@
-import { PencilIcon } from '@heroicons/react/solid';
+import Modal from '@app/components/Common/Modal';
+import PermissionEdit from '@app/components/PermissionEdit';
+import type { User } from '@app/hooks/useUser';
+import { useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
 import axios from 'axios';
-import React, { useEffect, useState } from 'react';
+import { useEffect, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
-import { User, useUser } from '../../hooks/useUser';
-import globalMessages from '../../i18n/globalMessages';
-import Modal from '../Common/Modal';
-import PermissionEdit from '../PermissionEdit';
 
 interface BulkEditProps {
   selectedUserIds: number[];
@@ -22,13 +22,13 @@ const messages = defineMessages({
   edituser: 'Edit User Permissions',
 });
 
-const BulkEditModal: React.FC<BulkEditProps> = ({
+const BulkEditModal = ({
   selectedUserIds,
   users,
   onCancel,
   onComplete,
   onSaving,
-}) => {
+}: BulkEditProps) => {
   const { user: currentUser } = useUser();
   const intl = useIntl();
   const { addToast } = useToasts();
@@ -85,7 +85,6 @@ const BulkEditModal: React.FC<BulkEditProps> = ({
   return (
     <Modal
       title={intl.formatMessage(messages.edituser)}
-      iconSvg={<PencilIcon />}
       onOk={() => {
         updateUsers();
       }}
diff --git a/src/components/UserList/PlexImportModal.tsx b/src/components/UserList/PlexImportModal.tsx
index 1afb8773..98a24829 100644
--- a/src/components/UserList/PlexImportModal.tsx
+++ b/src/components/UserList/PlexImportModal.tsx
@@ -1,13 +1,12 @@
-import { InboxInIcon } from '@heroicons/react/solid';
+import Alert from '@app/components/Common/Alert';
+import Modal from '@app/components/Common/Modal';
+import useSettings from '@app/hooks/useSettings';
+import globalMessages from '@app/i18n/globalMessages';
 import axios from 'axios';
-import React, { useState } from 'react';
+import { useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
-import useSettings from '../../hooks/useSettings';
-import globalMessages from '../../i18n/globalMessages';
-import Alert from '../Common/Alert';
-import Modal from '../Common/Modal';
 
 interface PlexImportProps {
   onCancel?: () => void;
@@ -25,10 +24,7 @@ const messages = defineMessages({
     'The <strong>Enable New Plex Sign-In</strong> setting is currently enabled. Plex users with library access do not need to be imported in order to sign in.',
 });
 
-const PlexImportModal: React.FC<PlexImportProps> = ({
-  onCancel,
-  onComplete,
-}) => {
+const PlexImportModal = ({ onCancel, onComplete }: PlexImportProps) => {
   const intl = useIntl();
   const settings = useSettings();
   const { addToast } = useToasts();
@@ -62,9 +58,7 @@ const PlexImportModal: React.FC<PlexImportProps> = ({
       addToast(
         intl.formatMessage(messages.importedfromplex, {
           userCount: createdUsers.length,
-          strong: function strong(msg) {
-            return <strong>{msg}</strong>;
-          },
+          strong: (msg: React.ReactNode) => <strong>{msg}</strong>,
         }),
         {
           autoDismiss: true,
@@ -110,7 +104,6 @@ const PlexImportModal: React.FC<PlexImportProps> = ({
     <Modal
       loading={!data && !error}
       title={intl.formatMessage(messages.importfromplex)}
-      iconSvg={<InboxInIcon />}
       onOk={() => {
         importUsers();
       }}
@@ -125,11 +118,9 @@ const PlexImportModal: React.FC<PlexImportProps> = ({
           {settings.currentSettings.newPlexLogin && (
             <Alert
               title={intl.formatMessage(messages.newplexsigninenabled, {
-                strong: function strong(msg) {
-                  return (
-                    <strong className="font-semibold text-white">{msg}</strong>
-                  );
-                },
+                strong: (msg: React.ReactNode) => (
+                  <strong className="font-semibold text-white">{msg}</strong>
+                ),
               })}
               type="info"
             />
diff --git a/src/components/UserList/index.tsx b/src/components/UserList/index.tsx
index d6243aa2..dfc0c2c2 100644
--- a/src/components/UserList/index.tsx
+++ b/src/components/UserList/index.tsx
@@ -1,4 +1,20 @@
-import { TrashIcon } from '@heroicons/react/outline';
+import Alert from '@app/components/Common/Alert';
+import Badge from '@app/components/Common/Badge';
+import Button from '@app/components/Common/Button';
+import Header from '@app/components/Common/Header';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import Modal from '@app/components/Common/Modal';
+import PageTitle from '@app/components/Common/PageTitle';
+import SensitiveInput from '@app/components/Common/SensitiveInput';
+import Table from '@app/components/Common/Table';
+import BulkEditModal from '@app/components/UserList/BulkEditModal';
+import PlexImportModal from '@app/components/UserList/PlexImportModal';
+import useSettings from '@app/hooks/useSettings';
+import { useUpdateQueryParams } from '@app/hooks/useUpdateQueryParams';
+import type { User } from '@app/hooks/useUser';
+import { Permission, UserType, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import { Transition } from '@headlessui/react';
 import {
   ChevronLeftIcon,
   ChevronRightIcon,
@@ -7,33 +23,17 @@ import {
   SortDescendingIcon,
   UserAddIcon,
 } from '@heroicons/react/solid';
+import type { UserResultsResponse } from '@server/interfaces/api/userInterfaces';
+import { hasPermission } from '@server/lib/permissions';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
 import Link from 'next/link';
 import { useRouter } from 'next/router';
-import React, { useEffect, useState } from 'react';
+import { useEffect, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import type { UserResultsResponse } from '../../../server/interfaces/api/userInterfaces';
-import { hasPermission } from '../../../server/lib/permissions';
-import useSettings from '../../hooks/useSettings';
-import { useUpdateQueryParams } from '../../hooks/useUpdateQueryParams';
-import { Permission, User, UserType, useUser } from '../../hooks/useUser';
-import globalMessages from '../../i18n/globalMessages';
-import Alert from '../Common/Alert';
-import Badge from '../Common/Badge';
-import Button from '../Common/Button';
-import Header from '../Common/Header';
-import LoadingSpinner from '../Common/LoadingSpinner';
-import Modal from '../Common/Modal';
-import PageTitle from '../Common/PageTitle';
-import SensitiveInput from '../Common/SensitiveInput';
-import Table from '../Common/Table';
-import Transition from '../Transition';
-import BulkEditModal from './BulkEditModal';
-import PlexImportModal from './PlexImportModal';
 
 const messages = defineMessages({
   users: 'Users',
@@ -80,7 +80,7 @@ const messages = defineMessages({
 
 type Sort = 'created' | 'updated' | 'requests' | 'displayname';
 
-const UserList: React.FC = () => {
+const UserList = () => {
   const intl = useIntl();
   const router = useRouter();
   const settings = useSettings();
@@ -182,7 +182,7 @@ const UserList: React.FC = () => {
         autoDismiss: true,
         appearance: 'success',
       });
-      setDeleteModal({ isOpen: false });
+      setDeleteModal({ isOpen: false, user: deleteModal.user });
     } catch (e) {
       addToast(intl.formatMessage(messages.userdeleteerror), {
         autoDismiss: true,
@@ -227,6 +227,7 @@ const UserList: React.FC = () => {
     <>
       <PageTitle title={intl.formatMessage(messages.users)} />
       <Transition
+        as="div"
         enter="opacity-0 transition duration-300"
         enterFrom="opacity-0"
         enterTo="opacity-100"
@@ -244,15 +245,18 @@ const UserList: React.FC = () => {
           }
           okDisabled={isDeleting}
           okButtonType="danger"
-          onCancel={() => setDeleteModal({ isOpen: false })}
+          onCancel={() =>
+            setDeleteModal({ isOpen: false, user: deleteModal.user })
+          }
           title={intl.formatMessage(messages.deleteuser)}
-          iconSvg={<TrashIcon />}
+          subTitle={deleteModal.user?.displayName}
         >
           {intl.formatMessage(messages.deleteconfirm)}
         </Modal>
       </Transition>
 
       <Transition
+        as="div"
         enter="opacity-0 transition duration-300"
         enterFrom="opacity-0"
         enterTo="opacity-100"
@@ -310,7 +314,6 @@ const UserList: React.FC = () => {
             return (
               <Modal
                 title={intl.formatMessage(messages.createlocaluser)}
-                iconSvg={<UserAddIcon />}
                 onOk={() => handleSubmit()}
                 okText={
                   isSubmitting
@@ -324,18 +327,16 @@ const UserList: React.FC = () => {
                 {!settings.currentSettings.localLogin && (
                   <Alert
                     title={intl.formatMessage(messages.localLoginDisabled, {
-                      strong: function strong(msg) {
-                        return (
-                          <strong className="font-semibold text-white">
-                            {msg}
-                          </strong>
-                        );
-                      },
+                      strong: (msg: React.ReactNode) => (
+                        <strong className="font-semibold text-white">
+                          {msg}
+                        </strong>
+                      ),
                     })}
                     type="warning"
                   />
                 )}
-                {currentHasPermission(Permission.MANAGE_SETTINGS) &&
+                {currentHasPermission(Permission.ADMIN) &&
                   !passwordGenerationEnabled && (
                     <Alert
                       title={intl.formatMessage(
@@ -373,9 +374,11 @@ const UserList: React.FC = () => {
                           inputMode="email"
                         />
                       </div>
-                      {errors.email && touched.email && (
-                        <div className="error">{errors.email}</div>
-                      )}
+                      {errors.email &&
+                        touched.email &&
+                        typeof errors.email === 'string' && (
+                          <div className="error">{errors.email}</div>
+                        )}
                     </div>
                   </div>
                   <div
@@ -421,9 +424,11 @@ const UserList: React.FC = () => {
                           disabled={values.genpassword}
                         />
                       </div>
-                      {errors.password && touched.password && (
-                        <div className="error">{errors.password}</div>
-                      )}
+                      {errors.password &&
+                        touched.password &&
+                        typeof errors.password === 'string' && (
+                          <div className="error">{errors.password}</div>
+                        )}
                     </div>
                   </div>
                 </Form>
@@ -434,6 +439,7 @@ const UserList: React.FC = () => {
       </Transition>
 
       <Transition
+        as="div"
         enter="opacity-0 transition duration-300"
         enterFrom="opacity-0"
         enterTo="opacity-100"
@@ -454,6 +460,7 @@ const UserList: React.FC = () => {
       </Transition>
 
       <Transition
+        as="div"
         enter="opacity-0 transition duration-300"
         enterFrom="opacity-0"
         enterTo="opacity-100"
@@ -556,7 +563,7 @@ const UserList: React.FC = () => {
         </thead>
         <Table.TBody>
           {data?.results.map((user) => (
-            <tr key={`user-list-${user.id}`}>
+            <tr key={`user-list-${user.id}`} data-testid="user-list-row">
               <Table.TD>
                 {isUserPermsEditable(user.id) && (
                   <input
@@ -575,7 +582,7 @@ const UserList: React.FC = () => {
                   <Link href={`/users/${user.id}`}>
                     <a className="h-10 w-10 flex-shrink-0">
                       <img
-                        className="h-10 w-10 rounded-full"
+                        className="h-10 w-10 rounded-full object-cover"
                         src={user.avatar}
                         alt=""
                       />
@@ -583,7 +590,10 @@ const UserList: React.FC = () => {
                   </Link>
                   <div className="ml-4">
                     <Link href={`/users/${user.id}`}>
-                      <a className="text-base font-bold leading-5 transition duration-300 hover:underline">
+                      <a
+                        className="text-base font-bold leading-5 transition duration-300 hover:underline"
+                        data-testid="user-list-username-link"
+                      >
                         {user.displayName}
                       </a>
                     </Link>
@@ -679,9 +689,9 @@ const UserList: React.FC = () => {
                             ? pageIndex * currentPageSize + data.results.length
                             : (pageIndex + 1) * currentPageSize,
                         total: data.pageInfo.results,
-                        strong: function strong(msg) {
-                          return <span className="font-medium">{msg}</span>;
-                        },
+                        strong: (msg: React.ReactNode) => (
+                          <span className="font-medium">{msg}</span>
+                        ),
                       })}
                   </p>
                 </div>
diff --git a/src/components/UserProfile/ProfileHeader/index.tsx b/src/components/UserProfile/ProfileHeader/index.tsx
index f677a008..456b5601 100644
--- a/src/components/UserProfile/ProfileHeader/index.tsx
+++ b/src/components/UserProfile/ProfileHeader/index.tsx
@@ -1,9 +1,9 @@
+import Button from '@app/components/Common/Button';
+import type { User } from '@app/hooks/useUser';
+import { Permission, useUser } from '@app/hooks/useUser';
 import { CogIcon, UserIcon } from '@heroicons/react/solid';
 import Link from 'next/link';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
-import { Permission, User, useUser } from '../../../hooks/useUser';
-import Button from '../../Common/Button';
 
 const messages = defineMessages({
   settings: 'Edit Settings',
@@ -17,10 +17,7 @@ interface ProfileHeaderProps {
   isSettingsPage?: boolean;
 }
 
-const ProfileHeader: React.FC<ProfileHeaderProps> = ({
-  user,
-  isSettingsPage,
-}) => {
+const ProfileHeader = ({ user, isSettingsPage }: ProfileHeaderProps) => {
   const intl = useIntl();
   const { user: loggedInUser, hasPermission } = useUser();
 
@@ -44,7 +41,7 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = ({
         <div className="flex-shrink-0">
           <div className="relative">
             <img
-              className="h-24 w-24 rounded-full bg-gray-600 ring-1 ring-gray-700"
+              className="h-24 w-24 rounded-full bg-gray-600 object-cover ring-1 ring-gray-700"
               src={user.avatar}
               alt=""
             />
@@ -61,7 +58,7 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = ({
                 user.id === loggedInUser?.id ? '/profile' : `/users/${user.id}`
               }
             >
-              <a className="bg-gradient-to-br from-indigo-400 to-purple-400 bg-clip-text text-lg font-bold text-transparent hover:to-purple-200 sm:text-2xl">
+              <a className="text-overseerr text-lg font-bold hover:to-purple-200 sm:text-2xl">
                 {user.displayName}
               </a>
             </Link>
diff --git a/src/components/UserProfile/UserSettings/UserGeneralSettings/index.tsx b/src/components/UserProfile/UserSettings/UserGeneralSettings/index.tsx
index 5f563ee9..fe768b28 100644
--- a/src/components/UserProfile/UserSettings/UserGeneralSettings/index.tsx
+++ b/src/components/UserProfile/UserSettings/UserGeneralSettings/index.tsx
@@ -1,29 +1,27 @@
+import Badge from '@app/components/Common/Badge';
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import LanguageSelector from '@app/components/LanguageSelector';
+import QuotaSelector from '@app/components/QuotaSelector';
+import RegionSelector from '@app/components/RegionSelector';
+import type { AvailableLocale } from '@app/context/LanguageContext';
+import { availableLanguages } from '@app/context/LanguageContext';
+import useLocale from '@app/hooks/useLocale';
+import useSettings from '@app/hooks/useSettings';
+import { Permission, UserType, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import Error from '@app/pages/_error';
 import { SaveIcon } from '@heroicons/react/outline';
+import type { UserSettingsGeneralResponse } from '@server/interfaces/api/userSettingsInterfaces';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
 import { useRouter } from 'next/router';
-import React, { useEffect, useState } from 'react';
+import { useEffect, useState } from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import { UserSettingsGeneralResponse } from '../../../../../server/interfaces/api/userSettingsInterfaces';
-import {
-  availableLanguages,
-  AvailableLocale,
-} from '../../../../context/LanguageContext';
-import useLocale from '../../../../hooks/useLocale';
-import useSettings from '../../../../hooks/useSettings';
-import { Permission, UserType, useUser } from '../../../../hooks/useUser';
-import globalMessages from '../../../../i18n/globalMessages';
-import Error from '../../../../pages/_error';
-import Badge from '../../../Common/Badge';
-import Button from '../../../Common/Button';
-import LoadingSpinner from '../../../Common/LoadingSpinner';
-import PageTitle from '../../../Common/PageTitle';
-import LanguageSelector from '../../../LanguageSelector';
-import QuotaSelector from '../../../QuotaSelector';
-import RegionSelector from '../../../RegionSelector';
 
 const messages = defineMessages({
   general: 'General',
@@ -51,9 +49,15 @@ const messages = defineMessages({
   discordIdTip:
     'The <FindDiscordIdLink>multi-digit ID number</FindDiscordIdLink> associated with your Discord user account',
   validationDiscordId: 'You must provide a valid Discord user ID',
+  plexwatchlistsyncmovies: 'Auto-Request Movies',
+  plexwatchlistsyncmoviestip:
+    'Automatically request movies on your <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink>',
+  plexwatchlistsyncseries: 'Auto-Request Series',
+  plexwatchlistsyncseriestip:
+    'Automatically request series on your <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink>',
 });
 
-const UserGeneralSettings: React.FC = () => {
+const UserGeneralSettings = () => {
   const intl = useIntl();
   const { addToast } = useToasts();
   const { locale, setLocale } = useLocale();
@@ -80,7 +84,7 @@ const UserGeneralSettings: React.FC = () => {
   const UserGeneralSettingsSchema = Yup.object().shape({
     discordId: Yup.string()
       .nullable()
-      .matches(/^\d{17,18}$/, intl.formatMessage(messages.validationDiscordId)),
+      .matches(/^\d{17,19}$/, intl.formatMessage(messages.validationDiscordId)),
   });
 
   useEffect(() => {
@@ -124,6 +128,8 @@ const UserGeneralSettings: React.FC = () => {
           movieQuotaDays: data?.movieQuotaDays,
           tvQuotaLimit: data?.tvQuotaLimit,
           tvQuotaDays: data?.tvQuotaDays,
+          watchlistSyncMovies: data?.watchlistSyncMovies,
+          watchlistSyncTv: data?.watchlistSyncTv,
         }}
         validationSchema={UserGeneralSettingsSchema}
         enableReinitialize
@@ -141,6 +147,8 @@ const UserGeneralSettings: React.FC = () => {
               movieQuotaDays: movieQuotaEnabled ? values.movieQuotaDays : null,
               tvQuotaLimit: tvQuotaEnabled ? values.tvQuotaLimit : null,
               tvQuotaDays: tvQuotaEnabled ? values.tvQuotaDays : null,
+              watchlistSyncMovies: values.watchlistSyncMovies,
+              watchlistSyncTv: values.watchlistSyncTv,
             });
 
             if (currentUser?.id === user?.id && setLocale) {
@@ -223,9 +231,11 @@ const UserGeneralSettings: React.FC = () => {
                       }
                     />
                   </div>
-                  {errors.displayName && touched.displayName && (
-                    <div className="error">{errors.displayName}</div>
-                  )}
+                  {errors.displayName &&
+                    touched.displayName &&
+                    typeof errors.displayName === 'string' && (
+                      <div className="error">{errors.displayName}</div>
+                    )}
                 </div>
               </div>
               <div className="form-row">
@@ -234,17 +244,15 @@ const UserGeneralSettings: React.FC = () => {
                   {currentUser?.id === user?.id && (
                     <span className="label-tip">
                       {intl.formatMessage(messages.discordIdTip, {
-                        FindDiscordIdLink: function FindDiscordIdLink(msg) {
-                          return (
-                            <a
-                              href="https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-"
-                              target="_blank"
-                              rel="noreferrer"
-                            >
-                              {msg}
-                            </a>
-                          );
-                        },
+                        FindDiscordIdLink: (msg: React.ReactNode) => (
+                          <a
+                            href="https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-"
+                            target="_blank"
+                            rel="noreferrer"
+                          >
+                            {msg}
+                          </a>
+                        ),
                       })}
                     </span>
                   )}
@@ -253,9 +261,11 @@ const UserGeneralSettings: React.FC = () => {
                   <div className="form-input-field">
                     <Field id="discordId" name="discordId" type="text" />
                   </div>
-                  {errors.discordId && touched.discordId && (
-                    <div className="error">{errors.discordId}</div>
-                  )}
+                  {errors.discordId &&
+                    touched.discordId &&
+                    typeof errors.discordId === 'string' && (
+                      <div className="error">{errors.discordId}</div>
+                    )}
                 </div>
               </div>
               <div className="form-row">
@@ -409,6 +419,99 @@ const UserGeneralSettings: React.FC = () => {
                     </div>
                   </>
                 )}
+              {hasPermission(
+                [Permission.AUTO_REQUEST, Permission.AUTO_REQUEST_MOVIE],
+                { type: 'or' }
+              ) &&
+                user?.userType === UserType.PLEX && (
+                  <div className="form-row">
+                    <label
+                      htmlFor="watchlistSyncMovies"
+                      className="checkbox-label"
+                    >
+                      <span>
+                        {intl.formatMessage(messages.plexwatchlistsyncmovies)}
+                      </span>
+                      <span className="label-tip">
+                        {intl.formatMessage(
+                          messages.plexwatchlistsyncmoviestip,
+                          {
+                            PlexWatchlistSupportLink: (
+                              msg: React.ReactNode
+                            ) => (
+                              <a
+                                href="https://support.plex.tv/articles/universal-watchlist/"
+                                className="text-white transition duration-300 hover:underline"
+                                target="_blank"
+                                rel="noreferrer"
+                              >
+                                {msg}
+                              </a>
+                            ),
+                          }
+                        )}
+                      </span>
+                    </label>
+                    <div className="form-input-area">
+                      <Field
+                        type="checkbox"
+                        id="watchlistSyncMovies"
+                        name="watchlistSyncMovies"
+                        onChange={() => {
+                          setFieldValue(
+                            'watchlistSyncMovies',
+                            !values.watchlistSyncMovies
+                          );
+                        }}
+                      />
+                    </div>
+                  </div>
+                )}
+              {hasPermission(
+                [Permission.AUTO_REQUEST, Permission.AUTO_REQUEST_TV],
+                { type: 'or' }
+              ) &&
+                user?.userType === UserType.PLEX && (
+                  <div className="form-row">
+                    <label htmlFor="watchlistSyncTv" className="checkbox-label">
+                      <span>
+                        {intl.formatMessage(messages.plexwatchlistsyncseries)}
+                      </span>
+                      <span className="label-tip">
+                        {intl.formatMessage(
+                          messages.plexwatchlistsyncseriestip,
+                          {
+                            PlexWatchlistSupportLink: (
+                              msg: React.ReactNode
+                            ) => (
+                              <a
+                                href="https://support.plex.tv/articles/universal-watchlist/"
+                                className="text-white transition duration-300 hover:underline"
+                                target="_blank"
+                                rel="noreferrer"
+                              >
+                                {msg}
+                              </a>
+                            ),
+                          }
+                        )}
+                      </span>
+                    </label>
+                    <div className="form-input-area">
+                      <Field
+                        type="checkbox"
+                        id="watchlistSyncTv"
+                        name="watchlistSyncTv"
+                        onChange={() => {
+                          setFieldValue(
+                            'watchlistSyncTv',
+                            !values.watchlistSyncTv
+                          );
+                        }}
+                      />
+                    </div>
+                  </div>
+                )}
               <div className="actions">
                 <div className="flex justify-end">
                   <span className="ml-3 inline-flex rounded-md shadow-sm">
diff --git a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsDiscord.tsx b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsDiscord.tsx
index b88f69e6..121018fc 100644
--- a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsDiscord.tsx
+++ b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsDiscord.tsx
@@ -1,18 +1,17 @@
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
+import { useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
 import { SaveIcon } from '@heroicons/react/outline';
+import type { UserSettingsNotificationsResponse } from '@server/interfaces/api/userSettingsInterfaces';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
 import { useRouter } from 'next/router';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import { UserSettingsNotificationsResponse } from '../../../../../server/interfaces/api/userSettingsInterfaces';
-import { useUser } from '../../../../hooks/useUser';
-import globalMessages from '../../../../i18n/globalMessages';
-import Button from '../../../Common/Button';
-import LoadingSpinner from '../../../Common/LoadingSpinner';
-import NotificationTypeSelector from '../../../NotificationTypeSelector';
 
 const messages = defineMessages({
   discordsettingssaved: 'Discord notification settings saved successfully!',
@@ -23,7 +22,7 @@ const messages = defineMessages({
   validationDiscordId: 'You must provide a valid user ID',
 });
 
-const UserNotificationsDiscord: React.FC = () => {
+const UserNotificationsDiscord = () => {
   const intl = useIntl();
   const { addToast } = useToasts();
   const router = useRouter();
@@ -46,7 +45,7 @@ const UserNotificationsDiscord: React.FC = () => {
           .required(intl.formatMessage(messages.validationDiscordId)),
         otherwise: Yup.string().nullable(),
       })
-      .matches(/^\d{17,18}$/, intl.formatMessage(messages.validationDiscordId)),
+      .matches(/^\d{17,19}$/, intl.formatMessage(messages.validationDiscordId)),
   });
 
   if (!data && !error) {
@@ -111,17 +110,15 @@ const UserNotificationsDiscord: React.FC = () => {
                 {currentUser?.id === user?.id && (
                   <span className="label-tip">
                     {intl.formatMessage(messages.discordIdTip, {
-                      FindDiscordIdLink: function FindDiscordIdLink(msg) {
-                        return (
-                          <a
-                            href="https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-"
-                            target="_blank"
-                            rel="noreferrer"
-                          >
-                            {msg}
-                          </a>
-                        );
-                      },
+                      FindDiscordIdLink: (msg: React.ReactNode) => (
+                        <a
+                          href="https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-"
+                          target="_blank"
+                          rel="noreferrer"
+                        >
+                          {msg}
+                        </a>
+                      ),
                     })}
                   </span>
                 )}
@@ -130,9 +127,11 @@ const UserNotificationsDiscord: React.FC = () => {
                 <div className="form-input-field">
                   <Field id="discordId" name="discordId" type="text" />
                 </div>
-                {errors.discordId && touched.discordId && (
-                  <div className="error">{errors.discordId}</div>
-                )}
+                {errors.discordId &&
+                  touched.discordId &&
+                  typeof errors.discordId === 'string' && (
+                    <div className="error">{errors.discordId}</div>
+                  )}
               </div>
             </div>
             <NotificationTypeSelector
diff --git a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsEmail.tsx b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsEmail.tsx
index b61507b3..942ea707 100644
--- a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsEmail.tsx
+++ b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsEmail.tsx
@@ -1,23 +1,22 @@
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import SensitiveInput from '@app/components/Common/SensitiveInput';
+import NotificationTypeSelector, {
+  ALL_NOTIFICATIONS,
+} from '@app/components/NotificationTypeSelector';
+import { OpenPgpLink } from '@app/components/Settings/Notifications/NotificationsEmail';
+import SettingsBadge from '@app/components/Settings/SettingsBadge';
+import { useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
 import { SaveIcon } from '@heroicons/react/outline';
+import type { UserSettingsNotificationsResponse } from '@server/interfaces/api/userSettingsInterfaces';
 import axios from 'axios';
 import { Form, Formik } from 'formik';
 import { useRouter } from 'next/router';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import { UserSettingsNotificationsResponse } from '../../../../../server/interfaces/api/userSettingsInterfaces';
-import { useUser } from '../../../../hooks/useUser';
-import globalMessages from '../../../../i18n/globalMessages';
-import Badge from '../../../Common/Badge';
-import Button from '../../../Common/Button';
-import LoadingSpinner from '../../../Common/LoadingSpinner';
-import SensitiveInput from '../../../Common/SensitiveInput';
-import NotificationTypeSelector, {
-  ALL_NOTIFICATIONS,
-} from '../../../NotificationTypeSelector';
-import { OpenPgpLink } from '../../../Settings/Notifications/NotificationsEmail';
 
 const messages = defineMessages({
   emailsettingssaved: 'Email notification settings saved successfully!',
@@ -28,7 +27,7 @@ const messages = defineMessages({
   validationPgpPublicKey: 'You must provide a valid PGP public key',
 });
 
-const UserEmailSettings: React.FC = () => {
+const UserEmailSettings = () => {
   const intl = useIntl();
   const { addToast } = useToasts();
   const router = useRouter();
@@ -106,9 +105,7 @@ const UserEmailSettings: React.FC = () => {
                 <span className="mr-2">
                   {intl.formatMessage(messages.pgpPublicKey)}
                 </span>
-                <Badge badgeType="danger">
-                  {intl.formatMessage(globalMessages.advanced)}
-                </Badge>
+                <SettingsBadge badgeType="advanced" />
                 <span className="label-tip">
                   {intl.formatMessage(messages.pgpPublicKeyTip, {
                     OpenPgpLink: OpenPgpLink,
@@ -126,9 +123,11 @@ const UserEmailSettings: React.FC = () => {
                     className="font-mono text-xs"
                   />
                 </div>
-                {errors.pgpKey && touched.pgpKey && (
-                  <div className="error">{errors.pgpKey}</div>
-                )}
+                {errors.pgpKey &&
+                  touched.pgpKey &&
+                  typeof errors.pgpKey === 'string' && (
+                    <div className="error">{errors.pgpKey}</div>
+                  )}
               </div>
             </div>
             <NotificationTypeSelector
diff --git a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushbullet.tsx b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushbullet.tsx
index 0cefb015..feadd1ac 100644
--- a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushbullet.tsx
+++ b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushbullet.tsx
@@ -1,18 +1,17 @@
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import SensitiveInput from '@app/components/Common/SensitiveInput';
+import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
+import { useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import type { UserSettingsNotificationsResponse } from '@server/interfaces/api/userSettingsInterfaces';
 import axios from 'axios';
 import { Form, Formik } from 'formik';
 import { useRouter } from 'next/router';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import { UserSettingsNotificationsResponse } from '../../../../../server/interfaces/api/userSettingsInterfaces';
-import { useUser } from '../../../../hooks/useUser';
-import globalMessages from '../../../../i18n/globalMessages';
-import Button from '../../../Common/Button';
-import LoadingSpinner from '../../../Common/LoadingSpinner';
-import SensitiveInput from '../../../Common/SensitiveInput';
-import NotificationTypeSelector from '../../../NotificationTypeSelector';
 
 const messages = defineMessages({
   pushbulletsettingssaved:
@@ -24,7 +23,7 @@ const messages = defineMessages({
   validationPushbulletAccessToken: 'You must provide an access token',
 });
 
-const UserPushbulletSettings: React.FC = () => {
+const UserPushbulletSettings = () => {
   const intl = useIntl();
   const { addToast } = useToasts();
   const router = useRouter();
@@ -105,20 +104,16 @@ const UserPushbulletSettings: React.FC = () => {
                 {data?.pushbulletAccessToken && (
                   <span className="label-tip">
                     {intl.formatMessage(messages.pushbulletAccessTokenTip, {
-                      PushbulletSettingsLink: function PushbulletSettingsLink(
-                        msg
-                      ) {
-                        return (
-                          <a
-                            href="https://www.pushbullet.com/#settings/account"
-                            className="text-white transition duration-300 hover:underline"
-                            target="_blank"
-                            rel="noreferrer"
-                          >
-                            {msg}
-                          </a>
-                        );
-                      },
+                      PushbulletSettingsLink: (msg: React.ReactNode) => (
+                        <a
+                          href="https://www.pushbullet.com/#settings/account"
+                          className="text-white transition duration-300 hover:underline"
+                          target="_blank"
+                          rel="noreferrer"
+                        >
+                          {msg}
+                        </a>
+                      ),
                     })}
                   </span>
                 )}
diff --git a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushover.tsx b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushover.tsx
index ecdc96e7..47b3df51 100644
--- a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushover.tsx
+++ b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushover.tsx
@@ -1,18 +1,17 @@
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
+import useSettings from '@app/hooks/useSettings';
+import { useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import type { UserSettingsNotificationsResponse } from '@server/interfaces/api/userSettingsInterfaces';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
 import { useRouter } from 'next/router';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import { UserSettingsNotificationsResponse } from '../../../../../server/interfaces/api/userSettingsInterfaces';
-import useSettings from '../../../../hooks/useSettings';
-import { useUser } from '../../../../hooks/useUser';
-import globalMessages from '../../../../i18n/globalMessages';
-import Button from '../../../Common/Button';
-import LoadingSpinner from '../../../Common/LoadingSpinner';
-import NotificationTypeSelector from '../../../NotificationTypeSelector';
 
 const messages = defineMessages({
   pushoversettingssaved: 'Pushover notification settings saved successfully!',
@@ -28,7 +27,7 @@ const messages = defineMessages({
   validationPushoverUserKey: 'You must provide a valid user or group key',
 });
 
-const UserPushoverSettings: React.FC = () => {
+const UserPushoverSettings = () => {
   const intl = useIntl();
   const settings = useSettings();
   const { addToast } = useToasts();
@@ -129,19 +128,16 @@ const UserPushoverSettings: React.FC = () => {
                 <span className="label-required">*</span>
                 <span className="label-tip">
                   {intl.formatMessage(messages.pushoverApplicationTokenTip, {
-                    ApplicationRegistrationLink:
-                      function ApplicationRegistrationLink(msg) {
-                        return (
-                          <a
-                            href="https://pushover.net/api#registration"
-                            className="text-white transition duration-300 hover:underline"
-                            target="_blank"
-                            rel="noreferrer"
-                          >
-                            {msg}
-                          </a>
-                        );
-                      },
+                    ApplicationRegistrationLink: (msg: React.ReactNode) => (
+                      <a
+                        href="https://pushover.net/api#registration"
+                        className="text-white transition duration-300 hover:underline"
+                        target="_blank"
+                        rel="noreferrer"
+                      >
+                        {msg}
+                      </a>
+                    ),
                     applicationTitle: settings.currentSettings.applicationTitle,
                   })}
                 </span>
@@ -167,18 +163,16 @@ const UserPushoverSettings: React.FC = () => {
                 {intl.formatMessage(messages.pushoverUserKey)}
                 <span className="label-tip">
                   {intl.formatMessage(messages.pushoverUserKeyTip, {
-                    UsersGroupsLink: function UsersGroupsLink(msg) {
-                      return (
-                        <a
-                          href="https://pushover.net/api#identifiers"
-                          className="text-white transition duration-300 hover:underline"
-                          target="_blank"
-                          rel="noreferrer"
-                        >
-                          {msg}
-                        </a>
-                      );
-                    },
+                    UsersGroupsLink: (msg: React.ReactNode) => (
+                      <a
+                        href="https://pushover.net/api#identifiers"
+                        className="text-white transition duration-300 hover:underline"
+                        target="_blank"
+                        rel="noreferrer"
+                      >
+                        {msg}
+                      </a>
+                    ),
                   })}
                 </span>
               </label>
@@ -190,9 +184,11 @@ const UserPushoverSettings: React.FC = () => {
                     type="text"
                   />
                 </div>
-                {errors.pushoverUserKey && touched.pushoverUserKey && (
-                  <div className="error">{errors.pushoverUserKey}</div>
-                )}
+                {errors.pushoverUserKey &&
+                  touched.pushoverUserKey &&
+                  typeof errors.pushoverUserKey === 'string' && (
+                    <div className="error">{errors.pushoverUserKey}</div>
+                  )}
               </div>
             </div>
             <NotificationTypeSelector
diff --git a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsTelegram.tsx b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsTelegram.tsx
index a5303b0e..5f665fa6 100644
--- a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsTelegram.tsx
+++ b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsTelegram.tsx
@@ -1,18 +1,17 @@
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import NotificationTypeSelector from '@app/components/NotificationTypeSelector';
+import { useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
 import { SaveIcon } from '@heroicons/react/outline';
+import type { UserSettingsNotificationsResponse } from '@server/interfaces/api/userSettingsInterfaces';
 import axios from 'axios';
 import { Field, Form, Formik } from 'formik';
 import { useRouter } from 'next/router';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import { UserSettingsNotificationsResponse } from '../../../../../server/interfaces/api/userSettingsInterfaces';
-import { useUser } from '../../../../hooks/useUser';
-import globalMessages from '../../../../i18n/globalMessages';
-import Button from '../../../Common/Button';
-import LoadingSpinner from '../../../Common/LoadingSpinner';
-import NotificationTypeSelector from '../../../NotificationTypeSelector';
 
 const messages = defineMessages({
   telegramsettingssaved: 'Telegram notification settings saved successfully!',
@@ -25,7 +24,7 @@ const messages = defineMessages({
   validationTelegramChatId: 'You must provide a valid chat ID',
 });
 
-const UserTelegramSettings: React.FC = () => {
+const UserTelegramSettings = () => {
   const intl = useIntl();
   const { addToast } = useToasts();
   const router = useRouter();
@@ -112,31 +111,25 @@ const UserTelegramSettings: React.FC = () => {
                 {data?.telegramBotUsername && (
                   <span className="label-tip">
                     {intl.formatMessage(messages.telegramChatIdTipLong, {
-                      TelegramBotLink: function TelegramBotLink(msg) {
-                        return (
-                          <a
-                            href={`https://telegram.me/${data.telegramBotUsername}`}
-                            target="_blank"
-                            rel="noreferrer"
-                          >
-                            {msg}
-                          </a>
-                        );
-                      },
-                      GetIdBotLink: function GetIdBotLink(msg) {
-                        return (
-                          <a
-                            href="https://telegram.me/get_id_bot"
-                            target="_blank"
-                            rel="noreferrer"
-                          >
-                            {msg}
-                          </a>
-                        );
-                      },
-                      code: function code(msg) {
-                        return <code>{msg}</code>;
-                      },
+                      TelegramBotLink: (msg: React.ReactNode) => (
+                        <a
+                          href={`https://telegram.me/${data.telegramBotUsername}`}
+                          target="_blank"
+                          rel="noreferrer"
+                        >
+                          {msg}
+                        </a>
+                      ),
+                      GetIdBotLink: (msg: React.ReactNode) => (
+                        <a
+                          href="https://telegram.me/get_id_bot"
+                          target="_blank"
+                          rel="noreferrer"
+                        >
+                          {msg}
+                        </a>
+                      ),
+                      code: (msg: React.ReactNode) => <code>{msg}</code>,
                     })}
                   </span>
                 )}
@@ -149,9 +142,11 @@ const UserTelegramSettings: React.FC = () => {
                     type="text"
                   />
                 </div>
-                {errors.telegramChatId && touched.telegramChatId && (
-                  <div className="error">{errors.telegramChatId}</div>
-                )}
+                {errors.telegramChatId &&
+                  touched.telegramChatId &&
+                  typeof errors.telegramChatId === 'string' && (
+                    <div className="error">{errors.telegramChatId}</div>
+                  )}
               </div>
             </div>
             <div className="form-row">
diff --git a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsWebPush.tsx b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsWebPush.tsx
index 4a932cb9..80a0ec72 100644
--- a/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsWebPush.tsx
+++ b/src/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsWebPush.tsx
@@ -1,26 +1,25 @@
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import NotificationTypeSelector, {
+  ALL_NOTIFICATIONS,
+} from '@app/components/NotificationTypeSelector';
+import { useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
 import { SaveIcon } from '@heroicons/react/outline';
+import type { UserSettingsNotificationsResponse } from '@server/interfaces/api/userSettingsInterfaces';
 import axios from 'axios';
 import { Form, Formik } from 'formik';
 import { useRouter } from 'next/router';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR, { mutate } from 'swr';
-import { UserSettingsNotificationsResponse } from '../../../../../server/interfaces/api/userSettingsInterfaces';
-import { useUser } from '../../../../hooks/useUser';
-import globalMessages from '../../../../i18n/globalMessages';
-import Button from '../../../Common/Button';
-import LoadingSpinner from '../../../Common/LoadingSpinner';
-import NotificationTypeSelector, {
-  ALL_NOTIFICATIONS,
-} from '../../../NotificationTypeSelector';
 
 const messages = defineMessages({
   webpushsettingssaved: 'Web push notification settings saved successfully!',
   webpushsettingsfailed: 'Web push notification settings failed to save.',
 });
 
-const UserWebPushSettings: React.FC = () => {
+const UserWebPushSettings = () => {
   const intl = useIntl();
   const { addToast } = useToasts();
   const router = useRouter();
diff --git a/src/components/UserProfile/UserSettings/UserNotificationSettings/index.tsx b/src/components/UserProfile/UserSettings/UserNotificationSettings/index.tsx
index ff6c149c..97f12369 100644
--- a/src/components/UserProfile/UserSettings/UserNotificationSettings/index.tsx
+++ b/src/components/UserProfile/UserSettings/UserNotificationSettings/index.tsx
@@ -1,19 +1,19 @@
+import DiscordLogo from '@app/assets/extlogos/discord.svg';
+import PushbulletLogo from '@app/assets/extlogos/pushbullet.svg';
+import PushoverLogo from '@app/assets/extlogos/pushover.svg';
+import TelegramLogo from '@app/assets/extlogos/telegram.svg';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import type { SettingsRoute } from '@app/components/Common/SettingsTabs';
+import SettingsTabs from '@app/components/Common/SettingsTabs';
+import { useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import Error from '@app/pages/_error';
 import { CloudIcon, MailIcon } from '@heroicons/react/solid';
+import type { UserSettingsNotificationsResponse } from '@server/interfaces/api/userSettingsInterfaces';
 import { useRouter } from 'next/router';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import { UserSettingsNotificationsResponse } from '../../../../../server/interfaces/api/userSettingsInterfaces';
-import DiscordLogo from '../../../../assets/extlogos/discord.svg';
-import PushbulletLogo from '../../../../assets/extlogos/pushbullet.svg';
-import PushoverLogo from '../../../../assets/extlogos/pushover.svg';
-import TelegramLogo from '../../../../assets/extlogos/telegram.svg';
-import { useUser } from '../../../../hooks/useUser';
-import globalMessages from '../../../../i18n/globalMessages';
-import Error from '../../../../pages/_error';
-import LoadingSpinner from '../../../Common/LoadingSpinner';
-import PageTitle from '../../../Common/PageTitle';
-import SettingsTabs, { SettingsRoute } from '../../../Common/SettingsTabs';
 
 const messages = defineMessages({
   notifications: 'Notifications',
@@ -22,7 +22,13 @@ const messages = defineMessages({
   webpush: 'Web Push',
 });
 
-const UserNotificationSettings: React.FC = ({ children }) => {
+type UserNotificationSettingsProps = {
+  children: React.ReactNode;
+};
+
+const UserNotificationSettings = ({
+  children,
+}: UserNotificationSettingsProps) => {
   const intl = useIntl();
   const router = useRouter();
   const { user } = useUser({ id: Number(router.query.userId) });
diff --git a/src/components/UserProfile/UserSettings/UserPasswordChange/index.tsx b/src/components/UserProfile/UserSettings/UserPasswordChange/index.tsx
index 6288f064..aea79f72 100644
--- a/src/components/UserProfile/UserSettings/UserPasswordChange/index.tsx
+++ b/src/components/UserProfile/UserSettings/UserPasswordChange/index.tsx
@@ -1,20 +1,19 @@
+import Alert from '@app/components/Common/Alert';
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import SensitiveInput from '@app/components/Common/SensitiveInput';
+import { Permission, useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import Error from '@app/pages/_error';
 import { SaveIcon } from '@heroicons/react/outline';
 import axios from 'axios';
 import { Form, Formik } from 'formik';
 import { useRouter } from 'next/router';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
 import * as Yup from 'yup';
-import { Permission, useUser } from '../../../../hooks/useUser';
-import globalMessages from '../../../../i18n/globalMessages';
-import Error from '../../../../pages/_error';
-import Alert from '../../../Common/Alert';
-import Button from '../../../Common/Button';
-import LoadingSpinner from '../../../Common/LoadingSpinner';
-import PageTitle from '../../../Common/PageTitle';
-import SensitiveInput from '../../../Common/SensitiveInput';
 
 const messages = defineMessages({
   password: 'Password',
@@ -39,7 +38,7 @@ const messages = defineMessages({
     "You do not have permission to modify this user's password.",
 });
 
-const UserPasswordChange: React.FC = () => {
+const UserPasswordChange = () => {
   const intl = useIntl();
   const { addToast } = useToasts();
   const router = useRouter();
@@ -176,9 +175,11 @@ const UserPasswordChange: React.FC = () => {
                         autoComplete="current-password"
                       />
                     </div>
-                    {errors.currentPassword && touched.currentPassword && (
-                      <div className="error">{errors.currentPassword}</div>
-                    )}
+                    {errors.currentPassword &&
+                      touched.currentPassword &&
+                      typeof errors.currentPassword === 'string' && (
+                        <div className="error">{errors.currentPassword}</div>
+                      )}
                   </div>
                 </div>
               )}
@@ -196,9 +197,11 @@ const UserPasswordChange: React.FC = () => {
                       autoComplete="new-password"
                     />
                   </div>
-                  {errors.newPassword && touched.newPassword && (
-                    <div className="error">{errors.newPassword}</div>
-                  )}
+                  {errors.newPassword &&
+                    touched.newPassword &&
+                    typeof errors.newPassword === 'string' && (
+                      <div className="error">{errors.newPassword}</div>
+                    )}
                 </div>
               </div>
               <div className="form-row">
@@ -215,9 +218,11 @@ const UserPasswordChange: React.FC = () => {
                       autoComplete="new-password"
                     />
                   </div>
-                  {errors.confirmPassword && touched.confirmPassword && (
-                    <div className="error">{errors.confirmPassword}</div>
-                  )}
+                  {errors.confirmPassword &&
+                    touched.confirmPassword &&
+                    typeof errors.confirmPassword === 'string' && (
+                      <div className="error">{errors.confirmPassword}</div>
+                    )}
                 </div>
               </div>
               <div className="actions">
diff --git a/src/components/UserProfile/UserSettings/UserPermissions/index.tsx b/src/components/UserProfile/UserSettings/UserPermissions/index.tsx
index 1d9fe22d..84b671b5 100644
--- a/src/components/UserProfile/UserSettings/UserPermissions/index.tsx
+++ b/src/components/UserProfile/UserSettings/UserPermissions/index.tsx
@@ -1,19 +1,18 @@
+import Alert from '@app/components/Common/Alert';
+import Button from '@app/components/Common/Button';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import PermissionEdit from '@app/components/PermissionEdit';
+import { useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import Error from '@app/pages/_error';
 import { SaveIcon } from '@heroicons/react/outline';
 import axios from 'axios';
 import { Form, Formik } from 'formik';
 import { useRouter } from 'next/router';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import { useToasts } from 'react-toast-notifications';
 import useSWR from 'swr';
-import { useUser } from '../../../../hooks/useUser';
-import globalMessages from '../../../../i18n/globalMessages';
-import Error from '../../../../pages/_error';
-import Alert from '../../../Common/Alert';
-import Button from '../../../Common/Button';
-import LoadingSpinner from '../../../Common/LoadingSpinner';
-import PageTitle from '../../../Common/PageTitle';
-import PermissionEdit from '../../../PermissionEdit';
 
 const messages = defineMessages({
   toastSettingsSuccess: 'Permissions saved successfully!',
@@ -22,7 +21,7 @@ const messages = defineMessages({
   unauthorizedDescription: 'You cannot modify your own permissions.',
 });
 
-const UserPermissions: React.FC = () => {
+const UserPermissions = () => {
   const intl = useIntl();
   const { addToast } = useToasts();
   const router = useRouter();
diff --git a/src/components/UserProfile/UserSettings/index.tsx b/src/components/UserProfile/UserSettings/index.tsx
index 7e2e4321..eb162807 100644
--- a/src/components/UserProfile/UserSettings/index.tsx
+++ b/src/components/UserProfile/UserSettings/index.tsx
@@ -1,18 +1,18 @@
+import Alert from '@app/components/Common/Alert';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import type { SettingsRoute } from '@app/components/Common/SettingsTabs';
+import SettingsTabs from '@app/components/Common/SettingsTabs';
+import ProfileHeader from '@app/components/UserProfile/ProfileHeader';
+import useSettings from '@app/hooks/useSettings';
+import { useUser } from '@app/hooks/useUser';
+import globalMessages from '@app/i18n/globalMessages';
+import Error from '@app/pages/_error';
+import type { UserSettingsNotificationsResponse } from '@server/interfaces/api/userSettingsInterfaces';
+import { hasPermission, Permission } from '@server/lib/permissions';
 import { useRouter } from 'next/router';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
 import useSWR from 'swr';
-import { UserSettingsNotificationsResponse } from '../../../../server/interfaces/api/userSettingsInterfaces';
-import { hasPermission, Permission } from '../../../../server/lib/permissions';
-import useSettings from '../../../hooks/useSettings';
-import { useUser } from '../../../hooks/useUser';
-import globalMessages from '../../../i18n/globalMessages';
-import Error from '../../../pages/_error';
-import Alert from '../../Common/Alert';
-import LoadingSpinner from '../../Common/LoadingSpinner';
-import PageTitle from '../../Common/PageTitle';
-import SettingsTabs, { SettingsRoute } from '../../Common/SettingsTabs';
-import ProfileHeader from '../ProfileHeader';
 
 const messages = defineMessages({
   menuGeneralSettings: 'General',
@@ -23,7 +23,11 @@ const messages = defineMessages({
     "You do not have permission to modify this user's settings.",
 });
 
-const UserSettings: React.FC = ({ children }) => {
+type UserSettingsProps = {
+  children: React.ReactNode;
+};
+
+const UserSettings = ({ children }: UserSettingsProps) => {
   const router = useRouter();
   const settings = useSettings();
   const { user: currentUser } = useUser();
@@ -53,10 +57,7 @@ const UserSettings: React.FC = ({ children }) => {
       regex: /\/settings\/password/,
       hidden:
         (!settings.currentSettings.localLogin &&
-          !hasPermission(
-            Permission.MANAGE_SETTINGS,
-            currentUser?.permissions ?? 0
-          )) ||
+          !hasPermission(Permission.ADMIN, currentUser?.permissions ?? 0)) ||
         (currentUser?.id !== 1 &&
           currentUser?.id !== user?.id &&
           hasPermission(Permission.ADMIN, user?.permissions ?? 0)),
diff --git a/src/components/UserProfile/index.tsx b/src/components/UserProfile/index.tsx
index c6c016db..c8bf3b2a 100644
--- a/src/components/UserProfile/index.tsx
+++ b/src/components/UserProfile/index.tsx
@@ -1,30 +1,30 @@
+import ImageFader from '@app/components/Common/ImageFader';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
+import PageTitle from '@app/components/Common/PageTitle';
+import ProgressCircle from '@app/components/Common/ProgressCircle';
+import RequestCard from '@app/components/RequestCard';
+import Slider from '@app/components/Slider';
+import TmdbTitleCard from '@app/components/TitleCard/TmdbTitleCard';
+import ProfileHeader from '@app/components/UserProfile/ProfileHeader';
+import { Permission, UserType, useUser } from '@app/hooks/useUser';
+import Error from '@app/pages/_error';
 import { ArrowCircleRightIcon } from '@heroicons/react/outline';
-import Link from 'next/link';
-import { useRouter } from 'next/router';
-import React, { useCallback, useEffect, useState } from 'react';
-import { defineMessages, FormattedNumber, useIntl } from 'react-intl';
-import useSWR from 'swr';
-import {
+import type { WatchlistResponse } from '@server/interfaces/api/discoverInterfaces';
+import type {
   QuotaResponse,
   UserRequestsResponse,
   UserWatchDataResponse,
-} from '../../../server/interfaces/api/userInterfaces';
-import { MovieDetails } from '../../../server/models/Movie';
-import { TvDetails } from '../../../server/models/Tv';
-import { Permission, UserType, useUser } from '../../hooks/useUser';
-import Error from '../../pages/_error';
-import ImageFader from '../Common/ImageFader';
-import LoadingSpinner from '../Common/LoadingSpinner';
-import PageTitle from '../Common/PageTitle';
-import ProgressCircle from '../Common/ProgressCircle';
-import RequestCard from '../RequestCard';
-import Slider from '../Slider';
-import TmdbTitleCard from '../TitleCard/TmdbTitleCard';
-import ProfileHeader from './ProfileHeader';
+} from '@server/interfaces/api/userInterfaces';
+import type { MovieDetails } from '@server/models/Movie';
+import type { TvDetails } from '@server/models/Tv';
+import Link from 'next/link';
+import { useRouter } from 'next/router';
+import { useCallback, useEffect, useState } from 'react';
+import { defineMessages, useIntl } from 'react-intl';
+import useSWR from 'swr';
 
 const messages = defineMessages({
   recentrequests: 'Recent Requests',
-  norequests: 'No requests.',
   limit: '{remaining} of {limit}',
   requestsperdays: '{limit} remaining',
   unlimited: 'Unlimited',
@@ -33,11 +33,14 @@ const messages = defineMessages({
   movierequests: 'Movie Requests',
   seriesrequest: 'Series Requests',
   recentlywatched: 'Recently Watched',
+  plexwatchlist: 'Plex Watchlist',
+  emptywatchlist:
+    'Media added to your <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink> will appear here.',
 });
 
 type MediaTitle = MovieDetails | TvDetails;
 
-const UserProfile: React.FC = () => {
+const UserProfile = () => {
   const intl = useIntl();
   const router = useRouter();
   const { user, error } = useUser({
@@ -68,12 +71,29 @@ const UserProfile: React.FC = () => {
       ? `/api/v1/user/${user.id}/quota`
       : null
   );
-  const { data: watchData } = useSWR<UserWatchDataResponse>(
-    user?.userType === UserType.PLEX &&
-      (user.id === currentUser?.id || currentHasPermission(Permission.ADMIN))
-      ? `/api/v1/user/${user.id}/watch_data`
-      : null
-  );
+  const { data: watchData, error: watchDataError } =
+    useSWR<UserWatchDataResponse>(
+      user?.userType === UserType.PLEX &&
+        (user.id === currentUser?.id || currentHasPermission(Permission.ADMIN))
+        ? `/api/v1/user/${user.id}/watch_data`
+        : null
+    );
+  const { data: watchlistItems, error: watchlistError } =
+    useSWR<WatchlistResponse>(
+      user?.userType === UserType.PLEX &&
+        (user.id === currentUser?.id ||
+          currentHasPermission(
+            [Permission.MANAGE_REQUESTS, Permission.WATCHLIST_VIEW],
+            {
+              type: 'or',
+            }
+          ))
+        ? `/api/v1/user/${user.id}/watchlist`
+        : null,
+      {
+        revalidateOnMount: true,
+      }
+    );
 
   const updateAvailableTitles = useCallback(
     (requestId: number, mediaTitle: MediaTitle) => {
@@ -129,7 +149,15 @@ const UserProfile: React.FC = () => {
                   {intl.formatMessage(messages.totalrequests)}
                 </dt>
                 <dd className="mt-1 text-3xl font-semibold text-white">
-                  <FormattedNumber value={user.requestCount} />
+                  <Link
+                    href={
+                      user.id === currentUser?.id
+                        ? '/profile/requests?filter=all'
+                        : `/users/${user?.id}/requests?filter=all`
+                    }
+                  >
+                    <a>{intl.formatNumber(user.requestCount)}</a>
+                  </Link>
                 </dd>
               </div>
               <div
@@ -249,37 +277,97 @@ const UserProfile: React.FC = () => {
         currentHasPermission(
           [Permission.MANAGE_REQUESTS, Permission.REQUEST_VIEW],
           { type: 'or' }
-        )) && (
-        <>
-          <div className="slider-header">
-            <Link href={`/users/${user?.id}/requests?filter=all`}>
-              <a className="slider-title">
-                <span>{intl.formatMessage(messages.recentrequests)}</span>
-                <ArrowCircleRightIcon />
-              </a>
-            </Link>
-          </div>
-          <Slider
-            sliderKey="requests"
-            isLoading={!requests && !requestError}
-            isEmpty={
-              !!requests && !requestError && requests.results.length === 0
-            }
-            items={(requests?.results ?? []).map((request) => (
-              <RequestCard
-                key={`request-slider-item-${request.id}`}
-                request={request}
-                onTitleData={updateAvailableTitles}
-              />
-            ))}
-            placeholder={<RequestCard.Placeholder />}
-            emptyMessage={intl.formatMessage(messages.norequests)}
-          />
-        </>
-      )}
-      {(user.id === currentUser?.id ||
-        currentHasPermission(Permission.ADMIN)) &&
-        !!watchData?.recentlyWatched.length && (
+        )) &&
+        (!requests || !!requests.results.length) &&
+        !requestError && (
+          <>
+            <div className="slider-header">
+              <Link
+                href={
+                  user.id === currentUser?.id
+                    ? '/profile/requests?filter=all'
+                    : `/users/${user?.id}/requests?filter=all`
+                }
+              >
+                <a className="slider-title">
+                  <span>{intl.formatMessage(messages.recentrequests)}</span>
+                  <ArrowCircleRightIcon />
+                </a>
+              </Link>
+            </div>
+            <Slider
+              sliderKey="requests"
+              isLoading={!requests}
+              items={(requests?.results ?? []).map((request) => (
+                <RequestCard
+                  key={`request-slider-item-${request.id}`}
+                  request={request}
+                  onTitleData={updateAvailableTitles}
+                />
+              ))}
+              placeholder={<RequestCard.Placeholder />}
+            />
+          </>
+        )}
+      {user.userType === UserType.PLEX &&
+        (user.id === currentUser?.id ||
+          currentHasPermission(
+            [Permission.MANAGE_REQUESTS, Permission.WATCHLIST_VIEW],
+            { type: 'or' }
+          )) &&
+        (!watchlistItems ||
+          !!watchlistItems.results.length ||
+          (user.id === currentUser?.id &&
+            (user.settings?.watchlistSyncMovies ||
+              user.settings?.watchlistSyncTv))) &&
+        !watchlistError && (
+          <>
+            <div className="slider-header">
+              <Link
+                href={
+                  user.id === currentUser?.id
+                    ? '/profile/watchlist'
+                    : `/users/${user?.id}/watchlist`
+                }
+              >
+                <a className="slider-title">
+                  <span>{intl.formatMessage(messages.plexwatchlist)}</span>
+                  <ArrowCircleRightIcon />
+                </a>
+              </Link>
+            </div>
+            <Slider
+              sliderKey="watchlist"
+              isLoading={!watchlistItems}
+              isEmpty={!!watchlistItems && watchlistItems.results.length === 0}
+              emptyMessage={intl.formatMessage(messages.emptywatchlist, {
+                PlexWatchlistSupportLink: (msg: React.ReactNode) => (
+                  <a
+                    href="https://support.plex.tv/articles/universal-watchlist/"
+                    className="text-white transition duration-300 hover:underline"
+                    target="_blank"
+                    rel="noreferrer"
+                  >
+                    {msg}
+                  </a>
+                ),
+              })}
+              items={watchlistItems?.results.map((item) => (
+                <TmdbTitleCard
+                  id={item.tmdbId}
+                  key={`watchlist-slider-item-${item.ratingKey}`}
+                  tmdbId={item.tmdbId}
+                  type={item.mediaType}
+                />
+              ))}
+            />
+          </>
+        )}
+      {user.userType === UserType.PLEX &&
+        (user.id === currentUser?.id ||
+          currentHasPermission(Permission.ADMIN)) &&
+        (!watchData || !!watchData.recentlyWatched.length) &&
+        !watchDataError && (
           <>
             <div className="slider-header">
               <div className="slider-title">
@@ -289,11 +377,12 @@ const UserProfile: React.FC = () => {
             <Slider
               sliderKey="media"
               isLoading={!watchData}
-              isEmpty={!watchData?.recentlyWatched.length}
-              items={watchData.recentlyWatched.map((item) => (
+              items={watchData?.recentlyWatched.map((item) => (
                 <TmdbTitleCard
                   key={`media-slider-item-${item.id}`}
+                  id={item.id}
                   tmdbId={item.tmdbId}
+                  tvdbId={item.tvdbId}
                   type={item.mediaType}
                 />
               ))}
diff --git a/src/context/InteractionContext.tsx b/src/context/InteractionContext.tsx
index 0a78cdac..09bdc30d 100644
--- a/src/context/InteractionContext.tsx
+++ b/src/context/InteractionContext.tsx
@@ -1,15 +1,16 @@
+import useInteraction from '@app/hooks/useInteraction';
 import React from 'react';
-import useInteraction from '../hooks/useInteraction';
 
 interface InteractionContextProps {
-  isTouch: boolean;
+  isTouch?: boolean;
+  children?: React.ReactNode;
 }
 
 export const InteractionContext = React.createContext<InteractionContextProps>({
   isTouch: false,
 });
 
-export const InteractionProvider: React.FC = ({ children }) => {
+export const InteractionProvider = ({ children }: InteractionContextProps) => {
   const isTouch = useInteraction();
 
   return (
diff --git a/src/context/LanguageContext.tsx b/src/context/LanguageContext.tsx
index 44d3baaa..0cf4d7d7 100644
--- a/src/context/LanguageContext.tsx
+++ b/src/context/LanguageContext.tsx
@@ -1,6 +1,7 @@
-import React, { ReactNode } from 'react';
+import React from 'react';
 
 export type AvailableLocale =
+  | 'ar'
   | 'ca'
   | 'cs'
   | 'da'
@@ -8,10 +9,11 @@ export type AvailableLocale =
   | 'en'
   | 'el'
   | 'es'
-  | 'it'
-  | 'ja'
   | 'fr'
   | 'hu'
+  | 'it'
+  | 'ja'
+  | 'lt'
   | 'nb-NO'
   | 'nl'
   | 'pl'
@@ -62,6 +64,10 @@ export const availableLanguages: AvailableLanguageObject = {
     code: 'it',
     display: 'Italiano',
   },
+  lt: {
+    code: 'lt',
+    display: 'Lietuvių',
+  },
   hu: {
     code: 'hu',
     display: 'Magyar',
@@ -106,6 +112,10 @@ export const availableLanguages: AvailableLanguageObject = {
     code: 'sr',
     display: 'српски језик',
   },
+  ar: {
+    code: 'ar',
+    display: 'العربية',
+  },
   ja: {
     code: 'ja',
     display: '日本語',
@@ -122,7 +132,7 @@ export const availableLanguages: AvailableLanguageObject = {
 
 export interface LanguageContextProps {
   locale: AvailableLocale;
-  children: (locale: string) => ReactNode;
+  children: (locale: string) => React.ReactNode;
   setLocale?: React.Dispatch<React.SetStateAction<AvailableLocale>>;
 }
 
diff --git a/src/context/SettingsContext.tsx b/src/context/SettingsContext.tsx
index 211d4060..d50add4d 100644
--- a/src/context/SettingsContext.tsx
+++ b/src/context/SettingsContext.tsx
@@ -1,9 +1,10 @@
+import type { PublicSettingsResponse } from '@server/interfaces/api/settingsInterfaces';
 import React from 'react';
 import useSWR from 'swr';
-import { PublicSettingsResponse } from '../../server/interfaces/api/settingsInterfaces';
 
 export interface SettingsContextProps {
   currentSettings: PublicSettingsResponse;
+  children?: React.ReactNode;
 }
 
 const defaultSettings = {
@@ -29,10 +30,10 @@ export const SettingsContext = React.createContext<SettingsContextProps>({
   currentSettings: defaultSettings,
 });
 
-export const SettingsProvider: React.FC<SettingsContextProps> = ({
+export const SettingsProvider = ({
   children,
   currentSettings,
-}) => {
+}: SettingsContextProps) => {
   const { data, error } = useSWR<PublicSettingsResponse>(
     '/api/v1/settings/public',
     { fallbackData: currentSettings }
diff --git a/src/context/UserContext.tsx b/src/context/UserContext.tsx
index 09440d23..bd07989b 100644
--- a/src/context/UserContext.tsx
+++ b/src/context/UserContext.tsx
@@ -1,9 +1,11 @@
+import type { User } from '@app/hooks/useUser';
+import { useUser } from '@app/hooks/useUser';
 import { useRouter } from 'next/dist/client/router';
-import React, { useEffect, useRef } from 'react';
-import { User, useUser } from '../hooks/useUser';
+import { useEffect, useRef } from 'react';
 
 interface UserContextProps {
   initialUser: User;
+  children?: React.ReactNode;
 }
 
 /**
@@ -11,10 +13,7 @@ interface UserContextProps {
  * cache on server side render. It also will handle redirecting the user to
  * the login page if their session ever becomes invalid.
  */
-export const UserContext: React.FC<UserContextProps> = ({
-  initialUser,
-  children,
-}) => {
+export const UserContext = ({ initialUser, children }: UserContextProps) => {
   const { user, error, revalidate } = useUser({ initialData: initialUser });
   const router = useRouter();
   const routing = useRef(false);
diff --git a/src/hooks/useDebouncedState.ts b/src/hooks/useDebouncedState.ts
index a73e3a06..144fd42f 100644
--- a/src/hooks/useDebouncedState.ts
+++ b/src/hooks/useDebouncedState.ts
@@ -1,4 +1,5 @@
-import { useState, useEffect, Dispatch, SetStateAction } from 'react';
+import type { Dispatch, SetStateAction } from 'react';
+import { useEffect, useState } from 'react';
 
 /**
  * A hook to help with debouncing state
diff --git a/src/hooks/useDiscover.ts b/src/hooks/useDiscover.ts
index 24ba47c1..96ea9cc7 100644
--- a/src/hooks/useDiscover.ts
+++ b/src/hooks/useDiscover.ts
@@ -1,5 +1,5 @@
+import { MediaStatus } from '@server/constants/media';
 import useSWRInfinite from 'swr/infinite';
-import { MediaStatus } from '../../server/constants/media';
 import useSettings from './useSettings';
 
 export interface BaseSearchResult<T> {
@@ -82,7 +82,9 @@ const useDiscover = <T extends BaseMedia, S = Record<string, never>>(
 
   const isEmpty = !isLoadingInitialData && titles?.length === 0;
   const isReachingEnd =
-    isEmpty || (!!data && (data[data?.length - 1]?.results.length ?? 0) < 20);
+    isEmpty ||
+    (!!data && (data[data?.length - 1]?.results.length ?? 0) < 20) ||
+    (!!data && (data[data?.length - 1]?.totalResults ?? 0) < 41);
 
   return {
     isLoadingInitialData,
diff --git a/src/hooks/useInteraction.ts b/src/hooks/useInteraction.ts
index 61d4f99f..59ee28a2 100644
--- a/src/hooks/useInteraction.ts
+++ b/src/hooks/useInteraction.ts
@@ -1,4 +1,4 @@
-import { useState, useEffect } from 'react';
+import { useEffect, useState } from 'react';
 
 export const INTERACTION_TYPE = {
   MOUSE: 'mouse',
diff --git a/src/hooks/useIsTouch.ts b/src/hooks/useIsTouch.ts
index 2f5ac983..67bd4ca6 100644
--- a/src/hooks/useIsTouch.ts
+++ b/src/hooks/useIsTouch.ts
@@ -1,7 +1,7 @@
+import { InteractionContext } from '@app/context/InteractionContext';
 import { useContext } from 'react';
-import { InteractionContext } from '../context/InteractionContext';
 
 export const useIsTouch = (): boolean => {
   const { isTouch } = useContext(InteractionContext);
-  return isTouch;
+  return isTouch ?? false;
 };
diff --git a/src/hooks/useLocale.ts b/src/hooks/useLocale.ts
index a0281e7e..59d4d056 100644
--- a/src/hooks/useLocale.ts
+++ b/src/hooks/useLocale.ts
@@ -1,8 +1,6 @@
+import type { LanguageContextProps } from '@app/context/LanguageContext';
+import { LanguageContext } from '@app/context/LanguageContext';
 import { useContext } from 'react';
-import {
-  LanguageContext,
-  LanguageContextProps,
-} from '../context/LanguageContext';
 
 const useLocale = (): Omit<LanguageContextProps, 'children'> => {
   const languageContext = useContext(LanguageContext);
diff --git a/src/hooks/useRequestOverride.ts b/src/hooks/useRequestOverride.ts
index ba791f99..03336363 100644
--- a/src/hooks/useRequestOverride.ts
+++ b/src/hooks/useRequestOverride.ts
@@ -1,45 +1,61 @@
+import type { MediaRequest } from '@server/entity/MediaRequest';
+import type {
+  ServiceCommonServer,
+  ServiceCommonServerWithDetails,
+} from '@server/interfaces/api/serviceInterfaces';
 import useSWR from 'swr';
-import { MediaRequest } from '../../server/entity/MediaRequest';
-import { ServiceCommonServer } from '../../server/interfaces/api/serviceInterfaces';
 
 interface OverrideStatus {
-  server: string | null;
-  profile: number | null;
-  rootFolder: string | null;
+  server?: string;
+  profile?: string;
+  rootFolder?: string;
+  languageProfile?: string;
 }
 
 const useRequestOverride = (request: MediaRequest): OverrideStatus => {
-  const { data } = useSWR<ServiceCommonServer[]>(
+  const { data: allServers } = useSWR<ServiceCommonServer[]>(
     `/api/v1/service/${request.type === 'movie' ? 'radarr' : 'sonarr'}`
   );
 
-  if (!data) {
-    return {
-      server: null,
-      profile: null,
-      rootFolder: null,
-    };
+  const { data } = useSWR<ServiceCommonServerWithDetails>(
+    `/api/v1/service/${request.type === 'movie' ? 'radarr' : 'sonarr'}/${
+      request.serverId
+    }`
+  );
+
+  if (!data || !allServers) {
+    return {};
   }
 
-  const defaultServer = data.find(
+  const defaultServer = allServers.find(
     (server) => server.is4k === request.is4k && server.isDefault
   );
 
-  const activeServer = data.find((server) => server.id === request.serverId);
+  const activeServer = allServers.find(
+    (server) => server.id === request.serverId
+  );
 
   return {
     server:
       activeServer && request.serverId !== defaultServer?.id
         ? activeServer.name
-        : null,
+        : undefined,
     profile:
       defaultServer?.activeProfileId !== request.profileId
-        ? request.profileId
-        : null,
+        ? data.profiles.find((profile) => profile.id === request.profileId)
+            ?.name
+        : undefined,
     rootFolder:
       defaultServer?.activeDirectory !== request.rootFolder
         ? request.rootFolder
-        : null,
+        : undefined,
+    languageProfile:
+      request.type === 'tv' &&
+      defaultServer?.activeLanguageProfileId !== request.languageProfileId
+        ? data.languageProfiles?.find(
+            (profile) => profile.id === request.languageProfileId
+          )?.name
+        : undefined,
   };
 };
 
diff --git a/src/hooks/useRouteGuard.ts b/src/hooks/useRouteGuard.ts
index fb6e0209..dbf68490 100644
--- a/src/hooks/useRouteGuard.ts
+++ b/src/hooks/useRouteGuard.ts
@@ -1,6 +1,7 @@
 import { useRouter } from 'next/router';
 import { useEffect } from 'react';
-import { Permission, PermissionCheckOptions, useUser } from './useUser';
+import type { Permission, PermissionCheckOptions } from './useUser';
+import { useUser } from './useUser';
 
 const useRouteGuard = (
   permission: Permission | Permission[],
diff --git a/src/hooks/useSearchInput.ts b/src/hooks/useSearchInput.ts
index 8e879279..54876357 100644
--- a/src/hooks/useSearchInput.ts
+++ b/src/hooks/useSearchInput.ts
@@ -1,9 +1,10 @@
 /* eslint-disable react-hooks/exhaustive-deps */
+import type { Nullable } from '@app/utils/typeHelpers';
+import { useRouter } from 'next/router';
+import type { Dispatch, SetStateAction } from 'react';
+import { useEffect, useState } from 'react';
 import type { UrlObject } from 'url';
-import { useEffect, useState, Dispatch, SetStateAction } from 'react';
 import useDebouncedState from './useDebouncedState';
-import { useRouter } from 'next/router';
-import type { Nullable } from '../utils/typeHelpers';
 
 type Url = string | UrlObject;
 
@@ -48,7 +49,7 @@ const useSearchInput = (): SearchObject => {
    * in a new route. If we are, then we only replace the history.
    */
   useEffect(() => {
-    if (debouncedValue !== '') {
+    if (debouncedValue !== '' && searchOpen) {
       if (router.pathname.startsWith('/search')) {
         router.replace({
           pathname: router.pathname,
diff --git a/src/hooks/useSettings.ts b/src/hooks/useSettings.ts
index 0fb7d7e9..2c881e65 100644
--- a/src/hooks/useSettings.ts
+++ b/src/hooks/useSettings.ts
@@ -1,8 +1,6 @@
+import type { SettingsContextProps } from '@app/context/SettingsContext';
+import { SettingsContext } from '@app/context/SettingsContext';
 import { useContext } from 'react';
-import {
-  SettingsContext,
-  SettingsContextProps,
-} from '../context/SettingsContext';
 
 const useSettings = (): SettingsContextProps => {
   const settings = useContext(SettingsContext);
diff --git a/src/hooks/useUpdateQueryParams.ts b/src/hooks/useUpdateQueryParams.ts
index 645d1d9d..e2ef801d 100644
--- a/src/hooks/useUpdateQueryParams.ts
+++ b/src/hooks/useUpdateQueryParams.ts
@@ -1,5 +1,6 @@
-import { NextRouter, useRouter } from 'next/router';
-import { ParsedUrlQuery } from 'querystring';
+import type { NextRouter } from 'next/router';
+import { useRouter } from 'next/router';
+import type { ParsedUrlQuery } from 'querystring';
 import { useCallback } from 'react';
 
 type UseQueryParamReturnedFunction = (
diff --git a/src/hooks/useUser.ts b/src/hooks/useUser.ts
index 223cea32..4dfcf090 100644
--- a/src/hooks/useUser.ts
+++ b/src/hooks/useUser.ts
@@ -1,12 +1,9 @@
+import { UserType } from '@server/constants/user';
+import type { PermissionCheckOptions } from '@server/lib/permissions';
+import { hasPermission, Permission } from '@server/lib/permissions';
+import type { NotificationAgentKey } from '@server/lib/settings';
 import useSWR from 'swr';
-import { MutatorCallback } from 'swr/dist/types';
-import { UserType } from '../../server/constants/user';
-import {
-  hasPermission,
-  Permission,
-  PermissionCheckOptions,
-} from '../../server/lib/permissions';
-import { NotificationAgentKey } from '../../server/lib/settings';
+import type { MutatorCallback } from 'swr/dist/types';
 
 export { Permission, UserType };
 export type { PermissionCheckOptions };
@@ -34,6 +31,8 @@ export interface UserSettings {
   originalLanguage?: string;
   locale?: string;
   notificationTypes: Partial<NotificationAgentTypes>;
+  watchlistSyncMovies?: boolean;
+  watchlistSyncTv?: boolean;
 }
 
 interface UserHookResponse {
diff --git a/src/hooks/useVerticalScroll.ts b/src/hooks/useVerticalScroll.ts
index cb80fe5b..5e6514a1 100644
--- a/src/hooks/useVerticalScroll.ts
+++ b/src/hooks/useVerticalScroll.ts
@@ -1,5 +1,6 @@
-import { useState, useEffect, useRef, MutableRefObject } from 'react';
 import { debounce } from 'lodash';
+import type { MutableRefObject } from 'react';
+import { useEffect, useRef, useState } from 'react';
 
 const IS_SCROLLING_CHECK_THROTTLE = 200;
 const BUFFER_HEIGHT = 200;
diff --git a/src/i18n/globalMessages.ts b/src/i18n/globalMessages.ts
index fff3a228..076312a1 100644
--- a/src/i18n/globalMessages.ts
+++ b/src/i18n/globalMessages.ts
@@ -43,6 +43,7 @@ const globalMessages = defineMessages({
   all: 'All',
   experimental: 'Experimental',
   advanced: 'Advanced',
+  restartRequired: 'Restart Required',
   loading: 'Loading…',
   settings: 'Settings',
   usersettings: 'User Settings',
diff --git a/src/i18n/locale/ar.json b/src/i18n/locale/ar.json
new file mode 100644
index 00000000..e6d6c815
--- /dev/null
+++ b/src/i18n/locale/ar.json
@@ -0,0 +1,1034 @@
+{
+  "components.AppDataWarning.dockerVolumeMissingDescription": "<code>{appDataPath}</code>مجلد التثبيت لم يتم إعداده بشكل صحيح سيتم تنظيف جميع البيانات عند إيقاف او إعادة تشغيل حاوي التطبيق.",
+  "components.NotificationTypeSelector.mediarequestedDescription": "إرسال تنبيهات في حالة وصول طلبات جديدة تتطلب الموافقة.",
+  "components.NotificationTypeSelector.notificationTypes": "نوع التنبيه",
+  "components.NotificationTypeSelector.usermediaapprovedDescription": "تلقي تنبيهات عندما يتم الموافقة على طلبات المحتوى.",
+  "components.NotificationTypeSelector.usermediadeclinedDescription": "تلقي تنبيهات عندما يتم رفض الطلبات.",
+  "components.PermissionEdit.createissuesDescription": "إعطاء صلاحية للإبلاغ عن مشاكل.",
+  "components.PermissionEdit.managerequestsDescription": "إعطاء صلاحية بإدارة الطلبات. كل الطلبات المقدمة من قبل مستخدم يحمل هذا الإذن سيتم الموافقة عليها بشكل تلقائي.",
+  "components.PermissionEdit.autoapproveDescription": "موافقة تلقائية لكل طلبات المحتوى باستثناء جودة الفور كي.",
+  "components.PermissionEdit.request4kMoviesDescription": "إعطاء صلاحية بطلب أفلام بجودة ٤ك.",
+  "components.PermissionEdit.requestDescription": "إعطاء اصلاحية بطلب محتوى ليس بجودة ٤ك.",
+  "components.RequestModal.QuotaDisplay.notenoughseasonrequests": "تم إستهلاك الحد الأقصى المسموح لك بطلب المواسم",
+  "components.RequestModal.AdvancedRequester.selecttags": "إختيار علامات \"Tags\"",
+  "components.RequestModal.AdvancedRequester.tags": "علامات\"Tags\"",
+  "components.RequestModal.QuotaDisplay.quotaLink": "يمكنك الإطلاع على ملخص الحد الأقصى لطلباتك في <ProfileLink>صفحة ملف التعريف</ProfileLink>.",
+  "components.RequestModal.QuotaDisplay.requiredquota": "تحتاج على الأقل ان تملك <strong>{seasons}</strong> {seasons, plural, one {طلب موسم} other {طلبات مواسم}} متبقية/متبقّي من حدك الأقصى لتتمكن من طلب هذا المسلسل.",
+  "components.Discover.NetworkSlider.networks": "شبكات البث",
+  "components.Discover.upcomingmovies": "أفلام قادمة",
+  "components.Discover.upcomingtv": "مسلسلات قادمة",
+  "components.IssueDetails.season": "موسم {seasonNumber}",
+  "components.IssueModal.issueVideo": "الفديو",
+  "components.ManageSlideOver.manageModalMedia": "المحتوى",
+  "components.Login.loginerror": "حدث خطأ ما أثناء محاولة تسجيل الدخول.",
+  "components.ManageSlideOver.manageModalNoRequests": "لا يوجد طلبات.",
+  "components.Layout.VersionStatus.streamstable": "نسخة مستقرة من \"أوفرسيرر\"",
+  "components.Login.forgotpassword": "نسيت كلمة السر؟",
+  "components.Login.signingin": "جاري تسجيل الدخول…",
+  "components.Login.signinheader": "سجل دخول للمتابعة",
+  "components.Layout.VersionStatus.streamdevelop": "نسخة التطوير من \"أوفرسيرر\"",
+  "components.Login.password": "كلمة السر",
+  "components.Login.signin": "تسجيل دخول",
+  "components.Login.signinwithplex": "إستخدم حساب بليكس",
+  "components.Login.signinwithoverseerr": "إستخدم حسابك في {applicationTitle}",
+  "components.ManageSlideOver.manageModalClearMedia": "محو البيانات",
+  "components.Login.validationemailrequired": "يجب عليك تزويد بريد إلكتروني صحيح",
+  "components.Login.validationpasswordrequired": "يجب عليك إدخال كلمة سر",
+  "components.ManageSlideOver.alltime": "جميع الأوقات",
+  "components.ManageSlideOver.downloadstatus": "التنزيلات",
+  "components.ManageSlideOver.manageModalAdvanced": "متقدم",
+  "components.ManageSlideOver.manageModalClearMediaWarning": "* سيتم حذف جميع البيانات بشكل نهائي لـ {mediaType},متضمنا جميع الطلبات.إذا كان هذا المحتوى متوفر في مكتبة بليكس، سيتم إعادة تفاصيل المحتوى في عملية الفحص القادمة.",
+  "components.ManageSlideOver.manageModalRequests": "الطلبات",
+  "components.ManageSlideOver.manageModalTitle": "إدارة {mediaType}",
+  "components.ManageSlideOver.manageModalIssues": "المشاكل المفتوحة",
+  "components.MovieDetails.budget": "الميزانية",
+  "components.ManageSlideOver.manageModalMedia4k": "محتوى جودة الفور كي",
+  "components.ManageSlideOver.playedby": "تم تشغيله بواسطة",
+  "components.ManageSlideOver.plays": "<strong>{playCount, number}</strong> {playCount, plural, one {تشغيل} other {تشغيل}}",
+  "components.ManageSlideOver.tvshow": "مسلسلات",
+  "components.MediaSlider.ShowMoreCard.seemore": "رؤية المزيد",
+  "components.MovieDetails.MovieCast.fullcast": "طاقم التمثيل",
+  "components.MovieDetails.MovieCrew.fullcrew": "طاقم العمل",
+  "components.MovieDetails.cast": "الطاقم",
+  "components.NotificationTypeSelector.mediarequested": "الطلب معلق للموافقة",
+  "components.NotificationTypeSelector.mediaAutoApprovedDescription": "إرسال تنبيهات عند طلب المستخدمين لمحتوى تمت الموافقة عليه بشكل تلقائي.",
+  "components.NotificationTypeSelector.mediadeclinedDescription": "إرسال تنبيهات في حالة رفض الطلبات.",
+  "components.CollectionDetails.numberofmovies": "{count} أفلام",
+  "components.CollectionDetails.overview": "نظرة عامة",
+  "components.CollectionDetails.requestcollection": "طلب تجميعة",
+  "components.CollectionDetails.requestcollection4k": "طلب تجميعة بجودة فور كي",
+  "components.Discover.DiscoverMovieGenre.genreMovies": "{genre} أفلام",
+  "components.Discover.DiscoverMovieLanguage.languageMovies": "{language} أفلام",
+  "components.Discover.DiscoverNetwork.networkSeries": "{network} مسلسلات",
+  "components.Discover.DiscoverStudio.studioMovies": "{studio} أفلام",
+  "components.Discover.DiscoverTvGenre.genreSeries": "{genre} مسلسلات",
+  "components.Discover.DiscoverTvLanguage.languageSeries": "{language} مسلسلات",
+  "components.Discover.MovieGenreList.moviegenres": "نوع الفيلم",
+  "components.Discover.MovieGenreSlider.moviegenres": "نوع الفيلم",
+  "components.Discover.StudioSlider.studios": "استديوهات الإنتاج",
+  "components.Discover.TvGenreList.seriesgenres": "نوع المسلسل",
+  "components.Discover.TvGenreSlider.tvgenres": "نوع المسلسل",
+  "components.Discover.discover": "إكتشف",
+  "components.Discover.discovermovies": "أفلام ذات شعبية",
+  "components.Discover.discovertv": "مسلسلات ذات شعبية",
+  "components.Discover.popularmovies": "أفلام ذات شعبية",
+  "components.Discover.populartv": "مسلسلات ذات شعبية",
+  "components.Discover.recentlyAdded": "أضيف مؤخرا",
+  "components.Discover.recentrequests": "الطلبات الحديثة",
+  "components.Discover.trending": "الأكثر شيوعاً",
+  "components.Discover.upcoming": "أفلام قادمة",
+  "components.DownloadBlock.estimatedtime": "الزمن المتوقّع {time}",
+  "components.IssueDetails.IssueComment.areyousuredelete": "هل أنت متأكد من حذف هذا التعليق ؟",
+  "components.IssueDetails.IssueComment.delete": "حذف التعليق",
+  "components.IssueDetails.IssueComment.edit": "تعديل التعليق",
+  "components.IssueDetails.IssueComment.postedby": "علّق {relativeTime} بواسطة {username}",
+  "components.IssueDetails.IssueComment.postedbyedited": "علّق {relativeTime} بواسطة {username} (تم تعديله)",
+  "components.IssueDetails.IssueComment.validationComment": "يجب عليك كتابه رسالة",
+  "components.IssueDetails.IssueDescription.deleteissue": "مسح المشكلة",
+  "components.IssueDetails.IssueDescription.description": "الوصف",
+  "components.IssueDetails.IssueDescription.edit": "تعديل الوصف",
+  "components.IssueDetails.allepisodes": "جميع الحلقات",
+  "components.IssueDetails.allseasons": "جميع المواسم",
+  "components.IssueDetails.closeissue": "إغلاق المشكلة",
+  "components.IssueDetails.closeissueandcomment": "إغلاق مع كتابة تعليق",
+  "components.IssueDetails.commentplaceholder": "إضافة تعليق…",
+  "components.IssueDetails.comments": "تعليقات",
+  "components.IssueDetails.deleteissue": "حذف المشكلة",
+  "components.IssueDetails.deleteissueconfirm": "هل أنت متأكد من حذف هذه المشكلة ؟",
+  "components.IssueDetails.episode": "حلقة {episodeNumber}",
+  "components.IssueDetails.issuepagetitle": "مشكلة",
+  "components.IssueDetails.issuetype": "نوع",
+  "components.IssueDetails.lastupdated": "أخر تحديث",
+  "components.IssueDetails.leavecomment": "تعليق",
+  "components.IssueDetails.nocomments": "لا تعليقات.",
+  "components.IssueDetails.openedby": "#{issueId} تم فتح {relativeTime} من قبل {username}",
+  "components.IssueDetails.openin4karr": "فتح بجودة فور كي في {arr}",
+  "components.IssueDetails.openinarr": "فتح في {arr}",
+  "components.IssueDetails.play4konplex": "تشغيل بجودة فور كي في بليكس",
+  "components.IssueDetails.playonplex": "تشغيل في بليكس",
+  "components.IssueDetails.problemepisode": "الحلقة المعنيّة",
+  "components.IssueDetails.problemseason": "الموسم المعني",
+  "components.IssueDetails.reopenissue": "إعادة فتح المشكلة",
+  "components.IssueDetails.reopenissueandcomment": "إعادة فتح مع ترك تعليق",
+  "components.IssueDetails.toasteditdescriptionfailed": "حدث خطأ ما أثناء تعديل وصف المشكلة.",
+  "components.IssueDetails.toasteditdescriptionsuccess": "تم تعديل وصف المشكلة بنجاح!",
+  "components.IssueDetails.toaststatusupdated": "تم تعديل حالة المشكلة بنجاح!",
+  "components.IssueDetails.toaststatusupdatefailed": "حدث خطأ ما أثناء تحديث حالة المشكلة.",
+  "components.IssueDetails.unknownissuetype": "غير معروف",
+  "components.IssueList.IssueItem.episodes": "{episodeCount, plural, one {حلقة} other {حلقات}}",
+  "components.IssueList.IssueItem.issuestatus": "الحالة",
+  "components.IssueList.IssueItem.issuetype": "النوع",
+  "components.IssueList.IssueItem.opened": "مفتوحة",
+  "components.IssueDetails.toastissuedeleted": "تم حذف المشكلة بنجاح!",
+  "components.IssueDetails.toastissuedeletefailed": "حدث خطأ أثناء حذف المشكلة.",
+  "components.IssueList.IssueItem.openeduserdate": "{date} بواسطة {user}",
+  "components.IssueList.IssueItem.problemepisode": "الحلقة المعنيّة",
+  "components.IssueList.IssueItem.seasons": "{seasonCount, plural, one {موسم} other {مواسم}}",
+  "components.IssueList.IssueItem.unknownissuetype": "غير معروف",
+  "components.IssueList.IssueItem.viewissue": "الإطلاع على المشكلة",
+  "components.IssueList.issues": "المشاكل",
+  "components.IssueList.showallissues": "رؤية جميع المشاكل",
+  "components.IssueList.sortAdded": "الأحدث",
+  "components.IssueList.sortModified": "أخر تعديل",
+  "components.IssueModal.CreateIssueModal.allepisodes": "جميع الحلقات",
+  "components.IssueModal.CreateIssueModal.allseasons": "جميع المواسم",
+  "components.IssueModal.CreateIssueModal.episode": "حلقة {episodeNumber}",
+  "components.IssueModal.CreateIssueModal.extras": "الإضافات",
+  "components.IssueModal.CreateIssueModal.problemepisode": "الحلقة المعنيّة",
+  "components.IssueModal.CreateIssueModal.problemseason": "الموسم المعني",
+  "components.IssueModal.CreateIssueModal.providedetail": "رجاءا قم بتزويد شرح مفصل للمشكلة التي صادفتها.",
+  "components.IssueModal.CreateIssueModal.reportissue": "الإبلاغ عن مشكلة",
+  "components.IssueModal.CreateIssueModal.season": "موسم {seasonNumber}",
+  "components.IssueModal.CreateIssueModal.submitissue": "تأكيد المشكلة",
+  "components.IssueModal.CreateIssueModal.toastFailedCreate": "حدث خطأ ما أثناء تأكيد المشكلة.",
+  "components.IssueModal.CreateIssueModal.toastSuccessCreate": "تقرير المشكلة عن <strong>{title}</strong> تم تأكيده بنجاح!",
+  "components.IssueModal.CreateIssueModal.toastviewissue": "رؤية المشكلة",
+  "components.IssueModal.CreateIssueModal.validationMessageRequired": "يجب عليك ذكر وصف",
+  "components.IssueModal.CreateIssueModal.whatswrong": "ماهي المشكلة؟",
+  "components.IssueModal.issueAudio": "الصوت",
+  "components.IssueModal.issueOther": "أخرى",
+  "components.IssueModal.issueSubtitles": "الترجمة",
+  "components.LanguageSelector.languageServerDefault": "الإفتراضي ({language})",
+  "components.LanguageSelector.originalLanguageDefault": "كل اللغات",
+  "components.Layout.LanguagePicker.displaylanguage": "لغة العرض",
+  "components.Layout.SearchInput.searchPlaceholder": "بحث عن فيلم أو مسلسل",
+  "components.Layout.Sidebar.dashboard": "إكتشف",
+  "components.Layout.Sidebar.issues": "المشاكل",
+  "components.Layout.Sidebar.requests": "الطلبات",
+  "components.Layout.Sidebar.settings": "الإعدادات",
+  "components.Layout.Sidebar.users": "المستخدمين",
+  "components.Layout.UserDropdown.myprofile": "ملف التعريف",
+  "components.Layout.UserDropdown.settings": "الإعدادات",
+  "components.Layout.UserDropdown.signout": "تسجيل خروج",
+  "components.Layout.VersionStatus.commitsbehind": "{commitsBehind} {commitsBehind, plural, one {تأكيد} other {تأكيد}} behind",
+  "components.Layout.VersionStatus.outofdate": "غير محدّث",
+  "components.Login.email": "عنوان البريد الإلكتروني",
+  "components.ManageSlideOver.markavailable": "الإشارة بأنه متوفر",
+  "components.ManageSlideOver.movie": "فيلم",
+  "components.ManageSlideOver.openarr": "فتح في {arr}",
+  "components.ManageSlideOver.mark4kavailable": "الإشارة بتوفّره بجودة فور كي",
+  "components.ManageSlideOver.markallseasons4kavailable": "الإشارة بأن كل المواسم متوفرة بجودة فور كي",
+  "components.ManageSlideOver.markallseasonsavailable": "الإشارة بتوفر جميع المواسم",
+  "components.ManageSlideOver.openarr4k": "فتح بجودة فور كي في {arr}",
+  "components.ManageSlideOver.opentautulli": "فتح في تطبيق تاتولي (Tautulli)",
+  "components.ManageSlideOver.pastdays": "مضى من الأيام {days, number}",
+  "components.MovieDetails.mark4kavailable": "الإشارة بأنه متوفر بجودة فور كي",
+  "components.MovieDetails.markavailable": "الإشارة بالتوفر",
+  "components.MovieDetails.originallanguage": "اللغة الأصلية",
+  "components.MovieDetails.originaltitle": "الإسم الأصلي",
+  "components.MovieDetails.overviewunavailable": "النظرة العامة غير متوفرة.",
+  "components.MovieDetails.play4konplex": "تشغيل بجودة فور كي في بليكس",
+  "components.MovieDetails.playonplex": "تشغيل في بليكس",
+  "components.MovieDetails.productioncountries": "الإنتاج {countryCount, plural, one {الدولة} other {الدول}}",
+  "components.MovieDetails.recommendations": "توصيات",
+  "components.MovieDetails.releasedate": "{releaseCount, plural, one {تاريخ الاصدار other {تواريخ الاصدار}}",
+  "components.MovieDetails.revenue": "العائد / الربح",
+  "components.MovieDetails.runtime": "{minutes} دقيقة",
+  "components.MovieDetails.showless": "رؤية تفاصيل أقل",
+  "components.MovieDetails.showmore": "رؤية المزيد",
+  "components.MovieDetails.similar": "عناوين مشابهه",
+  "components.MovieDetails.overview": "نظرة عامة",
+  "components.MovieDetails.streamingproviders": "يعرض حاليا على",
+  "components.MovieDetails.studio": "{studioCount, plural, one {استديو} other {استديوهات}}",
+  "components.MovieDetails.viewfullcrew": "رؤية طاقم العمل",
+  "components.MovieDetails.watchtrailer": "شاهد الإعلان",
+  "components.NotificationTypeSelector.adminissuecommentDescription": "الحصول على تنبيهات عند تعليق المستخدمين على المشاكل.",
+  "components.NotificationTypeSelector.adminissuereopenedDescription": "الحصول على تنبيهات عند إعادة فتح المشاكل من قبل المستخدمين.",
+  "components.NotificationTypeSelector.adminissueresolvedDescription": "الحصول على تنبيهات في حالة حل المشاكل من قبل المستخدمين.",
+  "components.NotificationTypeSelector.issuecomment": "تعليق على المشكلة",
+  "components.NotificationTypeSelector.issuecommentDescription": "إرسال تنبيهات في حالة وجود تعليقات جديدة على المشاكل.",
+  "components.NotificationTypeSelector.issuecreated": "تم التبليغ عن المشكلة",
+  "components.NotificationTypeSelector.issuecreatedDescription": "إرسال تنبيهات في حالة التبليغ عن مشاكل.",
+  "components.NotificationTypeSelector.issuereopened": "تم إعادة فتح المشكلة",
+  "components.NotificationTypeSelector.issuereopenedDescription": "إرسال تنبيهات عند إعادة فتح المشاكل.",
+  "components.NotificationTypeSelector.issueresolved": "تم حل المشكلة",
+  "components.NotificationTypeSelector.issueresolvedDescription": "إرسال تنبيهات عند حل المشاكل.",
+  "components.NotificationTypeSelector.mediaAutoApproved": "تم الموافقة على الطلب بشكل تلقائي",
+  "components.NotificationTypeSelector.mediaapproved": "تمت الموافقة على الطلب",
+  "components.NotificationTypeSelector.mediaapprovedDescription": "إرسال تنبيهات عند الموافقة على الطلبات بشكل يدوي.",
+  "components.NotificationTypeSelector.mediaavailable": "الطلب متاح",
+  "components.NotificationTypeSelector.mediaavailableDescription": "إرسال تنبيهات عندما يتوفر المحتوى المطلوب.",
+  "components.NotificationTypeSelector.mediadeclined": "تم رفض الطلب",
+  "components.NotificationTypeSelector.mediafailed": "فشل إنشاء الطلب",
+  "components.NotificationTypeSelector.mediafailedDescription": "تلقي تنبيهات في حالة فشل إرسال الطلبات الى رادار أو سونار.",
+  "components.NotificationTypeSelector.userissuecommentDescription": "تلقي تنبيهات في حالة وصول تعليقات جديدة على مشاكل تم فتحها بواسطتك.",
+  "components.NotificationTypeSelector.userissuecreatedDescription": "تلقي تنبيهات في حالة قيام المستخدمين بالتبليغ عن مشاكل.",
+  "components.NotificationTypeSelector.userissuereopenedDescription": "تلقي تنبيهات عندما يتم إعادة فتح مشكلة تم الإبلاغ عنها بواسطتك.",
+  "components.NotificationTypeSelector.userissueresolvedDescription": "تلقي تنبيهات في حالة الإشارة بحل مشكلة تم الابلاغ عنها بواسطتك.",
+  "components.NotificationTypeSelector.usermediaAutoApprovedDescription": "تلقي تنبيهات في حالة الموافقة بشكل تلقائي على طلب محتوى جديد من قبل المستخدمين.",
+  "components.NotificationTypeSelector.usermediaavailableDescription": "تلقي تنبيهات عندما تصبح الطلبات متوفرة.",
+  "components.NotificationTypeSelector.usermediafailedDescription": "تلقي تنبيهات في حالة فشل إرسال الطلبات الى رادار أو سونار.",
+  "components.NotificationTypeSelector.usermediarequestedDescription": "تلقي تنبيهات عندما يتم طلب محتوى جديد يتطلب الموافقة عليه.",
+  "components.PermissionEdit.admin": "مسؤول",
+  "components.PermissionEdit.adminDescription": "ولوج إداري كامل لا يتطلب أي أذونات.",
+  "components.PermissionEdit.advancedrequest": "طلبات متقدمة",
+  "components.PermissionEdit.advancedrequestDescription": "إعطاء صلاحية تعديل الخيارات المتقدمة لطلب المحتوى.",
+  "components.PermissionEdit.autoapprove": "موافقة تلقائية",
+  "components.PermissionEdit.autoapprove4k": "موافقة تلقائية لجودة الفور كي",
+  "components.PermissionEdit.autoapprove4kDescription": "إعطاء موافقة تلقائية لكل طلبات المحتوى بجودة الفور كي.",
+  "components.PermissionEdit.autoapprove4kMovies": "موافقة تلقائية للأفلام بجودة فور كي",
+  "components.PermissionEdit.autoapprove4kMoviesDescription": "إعطاء موافقة تلقائية لكل طلبات الأفلام بجودة فور كي.",
+  "components.PermissionEdit.autoapprove4kSeries": "موافقة تلقائية للمسلسلات بجودة فور كي",
+  "components.PermissionEdit.autoapprove4kSeriesDescription": "موافقة تلقائية لطلبات المسلسلات بجودة فور كي.",
+  "components.PermissionEdit.autoapproveMovies": "موافقة تلقائية للأفلام",
+  "components.PermissionEdit.autoapproveMoviesDescription": "موافقة تلقائية لكل طلبات الأفلام باستثناء جودة الفور كي.",
+  "components.PermissionEdit.autoapproveSeries": "موافقة تلقائية للمسلسلات",
+  "components.PermissionEdit.autoapproveSeriesDescription": "موافقة تلقائية لكل طلبات المسلسلات باستثناء جودة الفور كي.",
+  "components.PermissionEdit.createissues": "الإبلاغ عن مشكلة",
+  "components.PermissionEdit.manageissues": "إدارة المشاكل",
+  "components.PermissionEdit.manageissuesDescription": "إعطاء صلاحية بإدارة المشاكل.",
+  "components.PermissionEdit.managerequests": "إدارة الطلبات",
+  "components.PermissionEdit.request": "طلب",
+  "components.PermissionEdit.request4k": "طلب بجودة ٤ك",
+  "components.PermissionEdit.request4kDescription": "اعطاء صلاحية بطلب محتوى بجودة ٤ك.",
+  "components.PermissionEdit.request4kMovies": "طلب أفلام بجودة ٤ك",
+  "components.PermissionEdit.request4kTv": "طلب مسلسلات بجودة ٤ك",
+  "components.PermissionEdit.request4kTvDescription": "إعطاء صلاحية بطلب مسلسلات بجودة ٤ك.",
+  "components.PermissionEdit.requestMovies": "طلب أفلام",
+  "components.PermissionEdit.requestMoviesDescription": "إعطاء صلاحية بطلب أفلام ليست بجودة ٤ك.",
+  "components.PermissionEdit.requestTv": "طلب مسلسلات",
+  "components.PermissionEdit.requestTvDescription": "إعطاء إذن بطلب مسلسلات ليست بجودة ٤ك.",
+  "components.PermissionEdit.users": "إدارة المستخدمين",
+  "components.PermissionEdit.usersDescription": "إعطاء الإذن بإدارة المستخدمين. الذين يملكون هذه الصلاحية لا يستطيعون تعديل أي مستخدم مسؤول أو إعطاء صلاحية مسوؤل.",
+  "components.PermissionEdit.viewissues": "الإطلاع على المشاكل",
+  "components.PermissionEdit.viewissuesDescription": "إعطاء صلاحية برؤية كل المشاكل المبلغ عنها من قبل المستخدمين.",
+  "components.PermissionEdit.viewrequests": "الإطلاع على الطلبات",
+  "components.PermissionEdit.viewrequestsDescription": "إعطاء صلاحية بالإطلاع على جميع الطلبات المقدمة من قبل المستخدمين.",
+  "components.PersonDetails.alsoknownas": "أيضا معروف بـ: {names}",
+  "components.PersonDetails.appearsin": "المظهر",
+  "components.PersonDetails.ascharacter": "بـ {character}",
+  "components.PersonDetails.birthdate": "ولد في {birthdate}",
+  "components.PersonDetails.crewmember": "عضو",
+  "components.PersonDetails.lifespan": "{birthdate} - {deathdate}",
+  "components.PlexLoginButton.signingin": "تسجيل دخول…",
+  "components.PlexLoginButton.signinwithplex": "تسجيل دخول",
+  "components.QuotaSelector.days": "{count, plural, one {يوم} other {أيام}}",
+  "components.QuotaSelector.movieRequests": "{quotaLimit} <quotaUnits>{movies} كل {quotaDays} {days}</quotaUnits>",
+  "components.QuotaSelector.movies": "{count, plural, one {فيلم} other {أفلام}}",
+  "components.QuotaSelector.seasons": "{count, plural, one {موسم} other {مواسم}}",
+  "components.QuotaSelector.tvRequests": "{quotaLimit} <quotaUnits>{seasons} كل {quotaDays} {days}</quotaUnits>",
+  "components.QuotaSelector.unlimited": "غير محدود",
+  "components.RegionSelector.regionDefault": "كل المناطق",
+  "components.RegionSelector.regionServerDefault": "الإفتراضي ({region})",
+  "components.RequestBlock.profilechanged": "ملف تعريف الجودة",
+  "components.RequestBlock.requestoverrides": "تغيير اعدادات الطلب الافتراضية",
+  "components.RequestBlock.rootfolder": "مجلّد الحفظ",
+  "components.RequestBlock.seasons": "{seasonCount, plural, one {موسم} other {مواسم}}",
+  "components.RequestBlock.server": "وجهه السيرفر",
+  "components.RequestButton.approve4krequests": "الموافقة على {requestCount, plural, one {طلبات ٤ك} other {{requestCount} طلبات ٤ك}}",
+  "components.RequestButton.approverequest": "الموافقة على الطلب",
+  "components.RequestButton.approverequest4k": "الموافقة على طلب ٤ك",
+  "components.RequestButton.approverequests": "الموافقة على {requestCount, plural, one {طلب} other {{requestCount} طلبات}}",
+  "components.RequestButton.decline4krequests": "رفض {requestCount, plural, one {طلب الفور كي} other {{requestCount} طلبات الفور كي}}",
+  "components.RequestButton.declinerequest": "رفض الطلب",
+  "components.RequestButton.declinerequest4k": "رفض طلب الفور كي",
+  "components.RequestButton.declinerequests": "رفض {requestCount, plural, one {طلب} other {{requestCount} طلبات}}",
+  "components.RequestButton.requestmore": "طلب المزيد",
+  "components.RequestButton.requestmore4k": "طلب المزيد بجودة فور كي",
+  "components.RequestButton.viewrequest": "رؤية تفاصيل الطلب",
+  "components.RequestButton.viewrequest4k": "رؤية تفاصيل طلب الفور كي",
+  "components.RequestCard.deleterequest": "حذف الطلب",
+  "components.RequestCard.failedretry": "حدث خطأ ما أثناء محاولة إعادة الطلب.",
+  "components.RequestCard.mediaerror": "العنوان المتعلق بهذا الطلب لم يعد متوفراً.",
+  "components.RequestCard.seasons": "{seasonCount, plural, one {موسم} other {مواسم}}",
+  "components.RequestList.RequestItem.cancelRequest": "إلغاء الطلب",
+  "components.RequestList.RequestItem.deleterequest": "حذف الطلب",
+  "components.RequestList.RequestItem.editrequest": "تعديل الطلب",
+  "components.RequestList.RequestItem.failedretry": "حدث خطأ ما أثناء محاولة إعادة الطلب.",
+  "components.RequestList.RequestItem.mediaerror": "العنوان المتعلق بهذا الطلب لم يعد متوفرًا.",
+  "components.RequestList.RequestItem.modified": "تم تعديله",
+  "components.RequestList.RequestItem.modifieduserdate": "{date} من قبل {user}",
+  "components.RequestList.RequestItem.requested": "تم طلبه",
+  "components.RequestList.RequestItem.requesteddate": "تم طلبه",
+  "components.RequestList.RequestItem.seasons": "{seasonCount, plural, one {موسم} other {مواسم}}",
+  "components.RequestList.requests": "الطلبات",
+  "components.RequestList.showallrequests": "رؤية جميع الطلبات",
+  "components.RequestList.sortAdded": "الأحدث",
+  "components.RequestList.sortModified": "أخر تعديل",
+  "components.RequestModal.AdvancedRequester.advancedoptions": "متقدم",
+  "components.RequestModal.AdvancedRequester.animenote": "*هذا المحتوى بتصنيف \" إنمي \".",
+  "components.RequestModal.AdvancedRequester.default": "{name} (إفتراضي)",
+  "components.RequestModal.AdvancedRequester.destinationserver": "وجهه السيرفر",
+  "components.RequestModal.AdvancedRequester.folder": "{path} ({space})'",
+  "components.RequestModal.AdvancedRequester.languageprofile": "ملف تعريف اللغة",
+  "components.RequestModal.AdvancedRequester.notagoptions": "لا يوجد علامات\"Tags\".",
+  "components.RequestModal.AdvancedRequester.qualityprofile": "ملف تعريف الجودة",
+  "components.RequestModal.AdvancedRequester.requestas": "تقديم الطلب بإسم",
+  "components.RequestModal.AdvancedRequester.rootfolder": "مجلد الحفظ",
+  "components.RequestModal.QuotaDisplay.allowedRequests": "مسموح لك بطلب <strong>{limit}</strong> {type} كل <strong>{days}</strong> أيام.",
+  "components.RequestModal.QuotaDisplay.allowedRequestsUser": "هذا المستخدم مسموح له بطلب <strong>{limit}</strong> {type} كل <strong>{days}</strong> أيام.",
+  "components.RequestModal.QuotaDisplay.movie": "فيلم",
+  "components.RequestModal.QuotaDisplay.movielimit": "{limit, plural, one {فيلم} other {أفلام}}",
+  "components.RequestModal.QuotaDisplay.quotaLinkUser": "يمكنك الإطلاع على ملخص الحد الاقصى لطلبات هذا المستخدم في <ProfileLink>صفحة ملف التعريف</ProfileLink>.",
+  "components.RequestModal.QuotaDisplay.requestsremaining": "{متبقي, plural, =0 {No} other {<strong>#</strong>}} {type} {متبقي, plural, one {طلب} other {طلبات}} متبقية",
+  "components.RequestModal.QuotaDisplay.season": "موسم",
+  "components.RequestModal.QuotaDisplay.seasonlimit": "{limit, plural, one {موسم} other {مواسم}}",
+  "components.RequestModal.QuotaDisplay.requiredquotaUser": "هذا المستخدم يحتاج أن يملك على الاقل <strong>{seasons}</strong> {seasons, plural, one {طلب موسم} other {طلبات مواسم}} متبقية/متبقي ليتمكن من طلب هذا المسلسل.",
+  "components.RequestModal.SearchByNameModal.notvdbiddescription": "لم نتمكن من مطابقة طلبك بشكل تلقائي. الرجاء إختيار العنوان المراد من القائمة بالإسفل.",
+  "components.RequestModal.alreadyrequested": "تم طلبه مُسبقاً",
+  "components.RequestModal.approve": "الموافقة على الطلب",
+  "components.RequestModal.autoapproval": "موافقة تلقائية",
+  "components.RequestModal.cancel": "إلغاء الطلب",
+  "components.RequestModal.edit": "تعديل الطلب",
+  "components.RequestModal.errorediting": "حدث خطأ ما أثناء محاولة تعديل الطلب.",
+  "components.RequestModal.extras": "إضافات",
+  "components.RequestModal.numberofepisodes": "# حلقات",
+  "components.RequestModal.pending4krequest": "",
+  "components.RequestModal.pendingapproval": "طلبك معلق بانتظار الموافقة.",
+  "components.RequestModal.pendingrequest": "",
+  "components.ResetPassword.validationpasswordmatch": "يجب مطابقة كلمة السر مع تأكيدها",
+  "components.RequestModal.requestmovies": "طلب {count} {count, plural, one {فيلم} other {أفلام}}",
+  "components.ResetPassword.email": "البريد الإلكتروني",
+  "components.RequestModal.requestseasons4k": "طلب {seasonCount} {seasonCount, plural, one {موسم} other {مواسم}} بجودة فور كي",
+  "components.ResetPassword.emailresetlink": "رابط إستعادة البريد الإلكتروني",
+  "components.ResetPassword.passwordreset": "إعادة تعيين كلمة السر",
+  "components.ResetPassword.password": "كلمة السر",
+  "components.ResetPassword.validationemailrequired": "يجب عليك تزويد بريد إلكتروني صحيح",
+  "components.RequestModal.requestApproved": "طلبك لـ <strong>{title}</strong> تمت الموافقة عليه!",
+  "components.RequestModal.requestCancel": "طلبك لـ <strong>{title}</strong> تم إلغاءه.",
+  "components.RequestModal.requestSuccess": "<strong>{title}</strong> تم الطلب بنجاح!",
+  "components.RequestModal.requestadmin": "هذا الطلب سيتم الموافقة عليه بشكل تلقائي.",
+  "components.RequestModal.requestcancelled": "الطلب لـ <strong>{title}</strong> تم إلغاءه.",
+  "components.RequestModal.requestedited": "الطلب لـ <strong>{title}</strong> تم تعديله بنجاح!",
+  "components.RequestModal.requesterror": "حدث خطأ ما أثناء تأكيد الطلب.",
+  "components.RequestModal.requestfrom": "{username} طلب هذا المستخدم معلق بانتظار الموافقة.",
+  "components.RequestModal.requestmovies4k": "طلب {count} {count, plural, one {فيلم} other {أفلام}} بجودة فور كي",
+  "components.RequestModal.requestseasons": "طلب {seasonCount} {seasonCount, plural, one {موسم} other {مواسم}}",
+  "components.RequestModal.season": "موسم",
+  "components.RequestModal.seasonnumber": "موسم {number}",
+  "components.RequestModal.selectmovies": "إختيار فيلم /أفلام",
+  "components.RequestModal.selectseason": "إختيار موسم/مواسم",
+  "components.ResetPassword.confirmpassword": "تأكيد كلمة السر",
+  "components.ResetPassword.gobacklogin": "العودة لصفحة تسجيل الدخول",
+  "components.ResetPassword.requestresetlinksuccessmessage": "رابط إستعادة كلمة السر سيتم إرساله للبريد الإلكتروني المذكور إذا كان مرتبطا بمستخدم صحيح.",
+  "components.ResetPassword.resetpassword": "إعادة تعيين كلمة السر",
+  "components.ResetPassword.resetpasswordsuccessmessage": "تم تغيير كلمة السر بنجاح!",
+  "components.ResetPassword.validationpasswordminchars": "كلمة السر قصيرة جدا؛ الحد الأدنى ثمانية خانات",
+  "components.ResetPassword.validationpasswordrequired": "يجب عليك كتابة كلمة سر",
+  "components.Search.search": "بحث",
+  "components.Search.searchresults": "نتائج البحث",
+  "components.Settings.Notifications.NotificationsGotify.agentenabled": "تفعيل الخدمة",
+  "components.Settings.Notifications.NotificationsGotify.gotifysettingsfailed": "فشل حفظ إعدادات تنبيه خدمه قونتفاي.",
+  "components.Settings.Notifications.NotificationsGotify.gotifysettingssaved": "تم حفظ اعدادات خدمة تنبيه قونتفاي بنجاح!",
+  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestFailed": "فشل إرسال تنبيه تجريبي لخدمة قونتفاي.",
+  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestSending": "إرسال تنبيه تجريبي لقونتفاي…",
+  "components.Settings.Notifications.NotificationsGotify.token": "مفتاح التطبيق (Token)",
+  "components.Settings.Notifications.NotificationsGotify.url": "عنوان السيرفر",
+  "components.Settings.Notifications.NotificationsGotify.validationTokenRequired": "يجب عليك كتابة مفتاح التطبيق",
+  "components.Settings.Notifications.NotificationsGotify.validationTypes": "يجب عليك إختيار نوع تنبيه واحد على الأقل",
+  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestSuccess": "تم إرسال تنبيه تجريبي لقونتفاي!",
+  "components.Settings.Notifications.NotificationsGotify.validationUrlRequired": "يجب عليك كتابة رابط صحيح",
+  "components.Settings.Notifications.NotificationsLunaSea.settingsSaved": "تم حفظ اعدادات تنبيه لوناسي بنجاح!",
+  "components.Settings.Notifications.NotificationsGotify.validationUrlTrailingSlash": "الرابط يجب أن لا ينتهي بعلامة السلاش /",
+  "components.Settings.Notifications.NotificationsLunaSea.agentenabled": "تفعيل الخدمة",
+  "components.Settings.Notifications.NotificationsLunaSea.profileName": "إسم ملف التعريف",
+  "components.Settings.Notifications.NotificationsLunaSea.profileNameTip": "مطلوب فقط في حالة عدم إستخدام ملف التعريف الإفتراضي <code>default</code>",
+  "components.Settings.Notifications.NotificationsLunaSea.settingsFailed": "فشل في حفظ اعدادات تنبيه تطبيق لونا سي.",
+  "components.Settings.Notifications.NotificationsLunaSea.toastLunaSeaTestFailed": "فشل في ارسال التنبيه التجريبي الى لوناسي.",
+  "components.Settings.Notifications.NotificationsLunaSea.toastLunaSeaTestSending": "جاري إرسال تنبيه تجريبي الى لوناسي…",
+  "components.Settings.Notifications.NotificationsLunaSea.toastLunaSeaTestSuccess": "تم ارسال التنبيه!",
+  "components.Settings.Notifications.NotificationsLunaSea.validationTypes": "يجب عليك اختيار نوع تنبيه واحد على الاقل",
+  "components.Settings.Notifications.NotificationsLunaSea.validationWebhookUrl": "يجب عليك تزويد رابط صحيح",
+  "components.Settings.Notifications.NotificationsLunaSea.webhookUrl": "رابط webhook",
+  "components.Settings.Notifications.NotificationsLunaSea.webhookUrlTip": "رابط المستخدم أو الجهاز <LunaSeaLink>notification webhook URL</LunaSeaLink>",
+  "components.Settings.Notifications.NotificationsPushbullet.accessToken": "مفتاح الدخول Token",
+  "components.Settings.Notifications.NotificationsWebPush.toastWebPushTestSending": "جاري ارسال التنبيه…",
+  "components.Settings.Notifications.NotificationsPushbullet.toastPushbulletTestFailed": "فشل إرسال تنبيه تجريبي Pushbullet.",
+  "components.Settings.Notifications.NotificationsPushbullet.toastPushbulletTestSuccess": "تم الإرسال!",
+  "components.Settings.Notifications.NotificationsPushbullet.validationTypes": "يجب إختيار نوع تنبيه واحد على الأقل",
+  "components.Settings.Notifications.NotificationsPushover.toastPushoverTestSuccess": "تم الإرسال!",
+  "components.Settings.Notifications.NotificationsPushover.validationAccessTokenRequired": "يجب ذكر application Token صحيح",
+  "components.Settings.Notifications.NotificationsPushbullet.validationAccessTokenRequired": "يجب ذكر Access Token",
+  "components.Settings.Notifications.NotificationsPushover.userTokenTip": "الثلاثين خانة الخاصة بـ <UsersGroupsLink>بمعرف المستخدم او المجموعة </UsersGroupsLink>",
+  "components.Settings.Notifications.NotificationsWebhook.resetPayload": "اعادة تعيين",
+  "components.Settings.Notifications.NotificationsWebhook.toastWebhookTestSuccess": "تم ارسال تنبيه تجريبي بنجاح!",
+  "components.Settings.Notifications.NotificationsWebhook.webhooksettingsfailed": "فشل حفظ الاعدادات.",
+  "components.Settings.Notifications.NotificationsWebhook.webhooksettingssaved": "تم حفظ الاعدادات!",
+  "components.Settings.Notifications.agentenabled": "تفعيل الخدمة",
+  "components.Settings.Notifications.NotificationsPushbullet.accessTokenTip": "عمل مفتاح من <PushbulletSettingsLink>اعدادات الحساب</PushbulletSettingsLink>",
+  "components.Settings.Notifications.NotificationsPushbullet.agentEnabled": "تفعيل الخدمة",
+  "components.Settings.Notifications.NotificationsPushbullet.channelTag": "علامة القناة",
+  "components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsFailed": "فشل حفظ إعدادات تنبيه Pushbullet.",
+  "components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsSaved": "تم حفظ إعدادات تنبيه pushb6 بنجاح!",
+  "components.Settings.Notifications.NotificationsPushbullet.toastPushbulletTestSending": "جاري الإرسال…",
+  "components.Settings.Notifications.NotificationsPushover.accessToken": "مفتاح التطبيق API",
+  "components.Settings.Notifications.NotificationsPushover.accessTokenTip": "<ApplicationRegistrationLink>تسجيل تطبيق</ApplicationRegistrationLink> لاستخدامه مع اوفرسيرر",
+  "components.Settings.Notifications.NotificationsPushover.agentenabled": "تفعيل الخدمة",
+  "components.Settings.Notifications.NotificationsPushover.pushoversettingsfailed": "فشل حفظ إعدادات تنبيه Pushover.",
+  "components.Settings.Notifications.NotificationsPushover.pushoversettingssaved": "تم حفظ إعدادات تنبيه Pushover!",
+  "components.Settings.Notifications.NotificationsPushover.toastPushoverTestFailed": "فشل إرسال تنبيه تجريبي.",
+  "components.Settings.Notifications.NotificationsPushover.toastPushoverTestSending": "جاري الإرسال…",
+  "components.Settings.Notifications.NotificationsPushover.userToken": "مفتاح مستخدم أو مجموعة",
+  "components.Settings.Notifications.NotificationsPushover.validationTypes": "يجب عليك اختيار نوع تنبيه واحد على الاقل",
+  "components.Settings.Notifications.NotificationsPushover.validationUserTokenRequired": "يجب ذكر مفتاح مستخدم أو مجموعة صحيح",
+  "components.Settings.Notifications.NotificationsSlack.agentenabled": "تفعيل الخدمة",
+  "components.Settings.Notifications.NotificationsSlack.slacksettingsfailed": "فشل حفظ الاعدادات.",
+  "components.Settings.Notifications.NotificationsSlack.slacksettingssaved": "تم حفظ الاعدادات بنجاح!",
+  "components.Settings.Notifications.NotificationsSlack.toastSlackTestFailed": "فشل ارسال تنبيه تجريبي.",
+  "components.Settings.Notifications.NotificationsSlack.toastSlackTestSending": "جاري ارسال تنبيه تجريبي…",
+  "components.Settings.Notifications.NotificationsSlack.toastSlackTestSuccess": "تم ارسال تنبيه تجريبي!",
+  "components.Settings.Notifications.NotificationsSlack.validationTypes": "يجب عليك اختيار نوع تنبيه",
+  "components.Settings.Notifications.NotificationsSlack.validationWebhookUrl": "الرجاء تزويد رابط صحيح",
+  "components.Settings.Notifications.NotificationsSlack.webhookUrl": "رابط webhook",
+  "components.Settings.Notifications.NotificationsSlack.webhookUrlTip": "إنشاء <WebhookLink>Incoming Webhook</WebhookLink> integration",
+  "components.Settings.Notifications.NotificationsWebPush.agentenabled": "تفعيل الخدمة",
+  "components.Settings.Notifications.NotificationsWebPush.httpsRequirement": "لاستقبال تنبيهات بواسطة push , اوفرسيرر يجب ان يكون يعمل من خلال HTTPS.",
+  "components.Settings.Notifications.NotificationsWebPush.toastWebPushTestFailed": "فشل ارسال التنبيه.",
+  "components.Settings.Notifications.NotificationsWebPush.toastWebPushTestSuccess": "تم الارسال!",
+  "components.Settings.Notifications.NotificationsWebPush.webpushsettingsfailed": "فشل حفظ الاعدادات.",
+  "components.Settings.Notifications.NotificationsWebPush.webpushsettingssaved": "تم حفظ الاعدادات بنجاح!",
+  "components.Settings.Notifications.NotificationsWebhook.agentenabled": "تفعيل الخدمة",
+  "components.Settings.Notifications.NotificationsWebhook.authheader": "صلاحيات Header",
+  "components.Settings.Notifications.NotificationsWebhook.customJson": "JSON Payload جيسون",
+  "components.Settings.Notifications.NotificationsWebhook.resetPayloadSuccess": "تم اعادة تعيين JSON payload بنجاح!",
+  "components.Settings.Notifications.NotificationsWebhook.templatevariablehelp": "\"Template Variable Help\"",
+  "components.Settings.Notifications.NotificationsWebhook.toastWebhookTestFailed": "فشل ارسال تنبيه تجريبي.",
+  "components.Settings.Notifications.NotificationsWebhook.toastWebhookTestSending": "جاري ارسال تنبيه تجريبي…",
+  "components.Settings.Notifications.NotificationsWebhook.validationJsonPayloadRequired": "يجب عليك كتابة رابط صحيح",
+  "components.Settings.Notifications.NotificationsWebhook.validationTypes": "يجب عليك اختيار نوع تنبيه واحد على الاقل",
+  "components.Settings.Notifications.NotificationsWebhook.validationWebhookUrl": "يجب عليك كتابة رابط صحيح",
+  "components.Settings.Notifications.NotificationsWebhook.webhookUrl": "رابط \"Webhook URL",
+  "components.Settings.Notifications.allowselfsigned": "السماح بالشهادة الشخصية الموقعة",
+  "components.Settings.Notifications.authPass": "SMTP كلمة سر",
+  "components.Settings.Notifications.authUser": "اسم مستخدم SMPT",
+  "components.Settings.Notifications.botAPI": "مفتاح تصريح البوت token",
+  "components.Settings.Notifications.botApiTip": "<CreateBotLink>انشاء بوت</CreateBotLink> لاستخدامه مع اوفرسيرر",
+  "components.Settings.Notifications.botAvatarUrl": "رابط صورة البوت",
+  "components.Settings.Notifications.botUsername": "اسم البوت",
+  "components.Settings.Notifications.botUsernameTip": "اسمح للمستخدمين ببدء محادثة مع بوتك الخاص وضبط اعدادات التنبيه الخاصة بهم",
+  "components.Settings.Notifications.chatId": "عنوان المحادثة",
+  "components.Settings.Notifications.discordsettingssaved": "تم حفظ الاعدادات بنجاح!",
+  "components.Settings.Notifications.emailsettingssaved": "تم حفظ اعدادات تنبيه الايميل بنجاح!",
+  "components.Settings.Notifications.encryptionDefault": "استخدم STARTTLS اذا كان متاحا",
+  "components.Settings.Notifications.chatIdTip": "ابدأ محادثة مع البوت، أضف<GetIdBotLink>@get_id_bot</GetIdBotLink>, and و أعط <code>/my_id</code> الأمر",
+  "components.Settings.Notifications.discordsettingsfailed": "فشل حفظ اعدادات تنبيه الديسكورد.",
+  "components.Settings.Notifications.emailsender": "عنوان المرسل",
+  "components.Settings.Notifications.emailsettingsfailed": "فشل حفظ اعدادات تنبيه الايميل.",
+  "components.Settings.Notifications.enableMentions": "تفعيل التخصيص \"Mention\"",
+  "components.Settings.Notifications.encryption": "وضع التشفير",
+  "components.Settings.Notifications.encryptionOpportunisticTls": "استخدم STARTTLS دائما",
+  "components.Settings.Notifications.encryptionTip": "في معظم الحالات، يستخدم Implicit TLS منفذ 465 و STARTTLS يستخدم منفذ 587",
+  "components.Settings.Notifications.pgpPasswordTip": "سجل رسائل الايميل المشفرة باستخدام<OpenPgpLink>OpenPGP</OpenPgpLink>",
+  "components.Settings.Notifications.sendSilently": "أرسل بشكل صامت",
+  "components.Settings.Notifications.senderName": "اسم المرسل",
+  "components.Settings.Notifications.pgpPassword": "كلمة سر PGP",
+  "components.Settings.Notifications.pgpPrivateKey": "رمز PGP الخاص",
+  "components.Settings.Notifications.sendSilentlyTip": "أرسل التنبيهات بدون صوت",
+  "components.Settings.Notifications.pgpPrivateKeyTip": "سجل رسائل الايميل المشفرة باستخدام<OpenPgpLink>OpenPGP</OpenPgpLink>",
+  "components.Settings.Notifications.smtpPort": "منفذ SMTP",
+  "components.Settings.Notifications.smtpHost": "مضيف SMPT",
+  "components.Settings.Notifications.telegramsettingsfailed": "فشل حفظ اعدادات تنبيه التليقرام.",
+  "components.Settings.Notifications.telegramsettingssaved": "تم حفظ إعدادات التليقرام بنجاح!",
+  "components.Settings.Notifications.toastDiscordTestFailed": "فشل ارسال تنبيه الديسكورد التجريبي.",
+  "components.Settings.Notifications.toastTelegramTestFailed": "فشل ارسال التنبيه التجريبي للتليقرام.",
+  "components.Settings.Notifications.toastTelegramTestSuccess": "تم ارسال التنبيه!",
+  "components.Settings.Notifications.toastDiscordTestSending": "جاري ارسال تنبيه تجريبي للديسكورد…",
+  "components.Settings.Notifications.toastDiscordTestSuccess": "تم ارسال التنبيه!",
+  "components.Settings.Notifications.toastEmailTestFailed": "فشل ارسال تنبيه تجريبي للإيميل.",
+  "components.Settings.Notifications.toastEmailTestSending": "جاري ارسال تنبيه تجريبي للايميل…",
+  "components.Settings.Notifications.toastEmailTestSuccess": "تم ارسال التنبيه!",
+  "components.Settings.Notifications.toastTelegramTestSending": "جاري ارسال تنبيه تجريبي للتليقرام…",
+  "components.Settings.Notifications.validationBotAPIRequired": "يجب عليك ذكر مفتاح تصريح البوت \"Token\"",
+  "components.Settings.Notifications.validationChatIdRequired": "يجب عليك ذكر عنوان دردشة صحيح",
+  "components.Settings.Notifications.validationPgpPassword": "يجب عليك كتابة كلمة سر PGP",
+  "components.Settings.Notifications.validationEmail": "يجب عليك كتابة عنوان بريد صحيح",
+  "components.Settings.Notifications.validationSmtpHostRequired": "يجب ذكر عنوان مضيف أو أي بي صحيح",
+  "components.Settings.Notifications.validationTypes": "يجب اختيار نوع تنبيه واحد على الأقل",
+  "components.Settings.Notifications.webhookUrl": "رابط WEbhook",
+  "components.Settings.Notifications.validationPgpPrivateKey": "يجب عليك كتابة المفتاح الخاص الصحيح ب PGP",
+  "components.Settings.RadarrModal.add": "إضافة سيرفر",
+  "components.Settings.Notifications.validationSmtpPortRequired": "يجب ذكر رقم منفذ صحيح",
+  "components.Settings.Notifications.validationUrl": "يجب ذكر عنوان URL صحيح",
+  "components.Settings.Notifications.webhookUrlTip": "إنشاء <DiscordWebhookLink>webhook integration</DiscordWebhookLink> للسيرفر الخاص بك",
+  "components.Settings.RadarrModal.announced": "تم الإعلان عنه",
+  "components.Settings.RadarrModal.apiKey": "مفتاح API",
+  "components.Settings.Notifications.encryptionImplicitTls": "استخدم Implicit TLS",
+  "components.Settings.Notifications.encryptionNone": "غير محدد",
+  "components.Settings.RadarrModal.defaultserver": "السيرفر الافتراضي",
+  "components.Settings.RadarrModal.enableSearch": "تفعيل البحث التلقائي",
+  "components.Settings.RadarrModal.externalUrl": "عنوان الارتباط الخارجي",
+  "components.Settings.RadarrModal.qualityprofile": "ملف تعريف الجودة",
+  "components.Settings.RadarrModal.loadingrootfolders": "جاري تحميل مجلدات الحفظ…",
+  "components.Settings.RadarrModal.selectRootFolder": "إختار مجلد الحفظ",
+  "components.Settings.RadarrModal.baseUrl": "عنوان الارتباط \"URL \"",
+  "components.Settings.RadarrModal.create4kradarr": "إضافة سيرفر رادار جديد \"خاص بالفور كي\"",
+  "components.Settings.RadarrModal.createradarr": "إضافة سيرفر رادار جديد",
+  "components.Settings.RadarrModal.default4kserver": "سيرفر الفور كي الافتراضي",
+  "components.Settings.RadarrModal.edit4kradarr": "تعديل سيرفر رادار الخاص بالفور كي",
+  "components.Settings.RadarrModal.editradarr": "تعديل سيرفر رادار",
+  "components.Settings.RadarrModal.hostname": "عنوان المضيف أو رقم الأي بي",
+  "components.Settings.RadarrModal.inCinemas": "متوفر بالسينما",
+  "components.Settings.RadarrModal.loadingTags": "جاري تحميل العلامات \"Tags\"…",
+  "components.Settings.RadarrModal.loadingprofiles": "جاري تحميل ملفات تعريف الجودة…",
+  "components.Settings.RadarrModal.notagoptions": "بدون علامات \"Tags\".",
+  "components.Settings.RadarrModal.port": "المنفذ",
+  "components.Settings.RadarrModal.released": "تم إصداره",
+  "components.Settings.RadarrModal.minimumAvailability": "الحالة الأدنى للتوفر",
+  "components.Settings.RadarrModal.rootfolder": "مجلد الحفظ",
+  "components.Settings.RadarrModal.selectMinimumAvailability": "إختار الحالة الأدنى للتوفر",
+  "components.Settings.RadarrModal.selectQualityProfile": "إختار ملف تعريف الجودة",
+  "components.Settings.RadarrModal.selecttags": "إختار علامة \"Tags\"",
+  "components.Settings.RadarrModal.server4k": "سيرفر 4K",
+  "components.Settings.RadarrModal.servername": "اسم السيرفر",
+  "components.Settings.RadarrModal.ssl": "استخدم SSL",
+  "components.Settings.RadarrModal.validationProfileRequired": "يجب اختيار ملف تعريف للجودة",
+  "components.Settings.RadarrModal.validationRootFolderRequired": "يجب اختيار مجلد الحفظ",
+  "components.Settings.SettingsAbout.Releases.currentversion": "الحالي",
+  "components.Settings.SettingsAbout.Releases.latestversion": "الأحدث",
+  "components.Settings.SettingsAbout.Releases.releasedataMissing": "بيانات الاصدار غير متوفرة حاليا.",
+  "components.Settings.SettingsAbout.Releases.releases": "إصدارات",
+  "components.Settings.RadarrModal.syncEnabled": "تفعيل البحث",
+  "components.Settings.RadarrModal.tags": "علامات",
+  "components.Settings.RadarrModal.testFirstQualityProfiles": "اختبار الاتصال لتحميل ملفات تعريف الجودة",
+  "components.Settings.RadarrModal.testFirstRootFolders": "اختبار الاتصال لتحميل مجلدات الحفظ",
+  "components.Settings.RadarrModal.testFirstTags": "اختبار الاتصال لتحميل العلامات",
+  "components.Settings.RadarrModal.toastRadarrTestFailure": "فشل الاتصال برادار.",
+  "components.Settings.RadarrModal.toastRadarrTestSuccess": "تم انشاء الاتصال برادار بنجاح!",
+  "components.Settings.RadarrModal.validationApiKeyRequired": "يجب عليك كتابة مفتاح API صحيح",
+  "components.Settings.RadarrModal.validationApplicationUrl": "يجب عليك كتابة عنوان ارتباط صحيح",
+  "components.Settings.RadarrModal.validationApplicationUrlTrailingSlash": "عنوان الارتباط يجب لا ينتهي بعلامة السلاش /",
+  "components.Settings.RadarrModal.validationBaseUrlTrailingSlash": "يجب لا ينتهي عنوان الارتباط الاساسي بعلامة السلاش",
+  "components.Settings.RadarrModal.validationBaseUrlLeadingSlash": "عنوان الارتباط الاساسي يجب ان يحتوي على علامة سلاش توضيحية \"غالبا بمنتصف كلمتين او بالبداية\"",
+  "components.Settings.RadarrModal.validationHostnameRequired": "يجب كتابة عنوان مضيف أو رقم اي بي صحيح",
+  "components.Settings.RadarrModal.validationMinimumAvailabilityRequired": "يجب اختيار المستوى الادنى للتوفر",
+  "components.Settings.RadarrModal.validationNameRequired": "يجب اختيار اسم سيرفر",
+  "components.Settings.RadarrModal.validationPortRequired": "يجب كتابة رقم منفذ صحيح",
+  "components.Settings.SettingsAbout.Releases.versionChangelog": "{version} سجل التحسينات",
+  "components.Settings.SettingsAbout.Releases.viewchangelog": "الاطلاع على سجل التحسينات",
+  "components.Settings.SettingsAbout.Releases.viewongithub": "رؤية المحتوى على GitHub",
+  "components.Settings.SettingsAbout.about": "حول",
+  "components.Settings.SettingsAbout.appDataPath": "مكان تخزين البيانات",
+  "components.Settings.SettingsAbout.betawarning": "هذا اصدار تجريبي. بعض الخصائص المتقدمة غير مستقرة أو قد لا تعمل. الرجاء الابلاغ عن اي مشاكل على GitHub!",
+  "components.Settings.SettingsAbout.documentation": "الوثائق",
+  "components.Settings.SettingsAbout.gettingsupport": "الحصول على دعم",
+  "components.Settings.SettingsAbout.githubdiscussions": "نقاشات GitHub",
+  "components.Settings.SettingsAbout.helppaycoffee": "ساعدني بدفع حساب القهوة",
+  "components.Settings.SettingsAbout.outofdate": "غير محدث",
+  "components.Settings.SettingsAbout.overseerrinformation": "حول اوفرسيرر",
+  "components.Settings.SettingsAbout.preferredmethod": "مُفضّل",
+  "components.Settings.SettingsJobsCache.cache": "الملفات المؤقتة",
+  "components.Settings.SettingsAbout.totalmedia": "المجموع الكلي للمحتوى",
+  "components.Settings.SettingsAbout.totalrequests": "مجموع الطلبات",
+  "components.Settings.SettingsAbout.version": "النسخة",
+  "components.Settings.SettingsAbout.uptodate": "مُحدّث",
+  "components.Settings.SettingsJobsCache.cacheDescription": "أوفرسيرر يخزن ملفات مؤقته متعلقه بالمفاتيح الخارجية API لتحسين الاداء وتفادي ارسال طلبات اتصال متكررة.",
+  "components.Settings.SettingsJobsCache.cacheflushed": "تم محو الملف المخزّن.",
+  "components.Settings.SettingsJobsCache.cachekeys": "مجموع المفاتيح",
+  "components.Settings.SettingsJobsCache.canceljob": "الغاء الطلب",
+  "components.Settings.SettingsJobsCache.cachename": "اسم ملفات التخزين",
+  "components.Settings.SettingsJobsCache.cachevsize": "الحجم الكلي",
+  "components.Settings.SettingsAbout.runningDevelop": "انت تستخدم نسخة تجريبية <code>develop</code> branch of Overseerr, النسخة مستحسنه فقط للمساهمين بتطوير التطبيق او المساعدين باختبار النسخ التجريبية.",
+  "components.Settings.SettingsAbout.supportoverseerr": "إدعم أوفرسيرر",
+  "components.Settings.SettingsAbout.timezone": "المنطقة الزمنية",
+  "components.Settings.SettingsJobsCache.cachehits": "Hits،",
+  "components.Settings.SettingsJobsCache.cacheksize": "حجم المفاتيح",
+  "components.Settings.SettingsJobsCache.cachemisses": "مفقودات",
+  "components.Settings.SettingsUsers.newPlexLoginTip": "السماح لمستخدمين بليكس بتسجيل الدخول دون الحاجة لدمجهم في أوفرسيرر",
+  "components.Settings.SonarrModal.animeTags": "علامات الإنمي",
+  "components.Settings.SettingsJobsCache.editJobScheduleSelectorMinutes": "كل {jobScheduleMinutes, plural, one {دقيقة} other {{jobScheduleMinutes} دقائق}}",
+  "components.Settings.SettingsJobsCache.jobScheduleEditFailed": "حدث خطأ ما اثناء حفظ المهمة.",
+  "components.Settings.SettingsJobsCache.jobsDescription": "أوفرسيرر يعمل على جدولة بعض مهام الصيانة بشكل دوري ولكن بالإمكان عمل هذه المهام بشكل يدوي من القائمة بالإسفل. عمل اي مهمة بشكل يدوي لن يأثر على جدولتها التلقائية.",
+  "components.Settings.SettingsLogs.message": "الرسائل",
+  "components.Settings.SettingsJobsCache.unknownJob": "مهمة غير معروفه",
+  "components.Settings.SettingsLogs.resumeLogs": "استئناف",
+  "components.Settings.SettingsLogs.showall": "إظهار كل السجلات",
+  "components.Settings.SettingsLogs.logs": "السجلات",
+  "components.Settings.SonarrModal.baseUrl": "عنوان الارتباط URL BASE",
+  "components.Settings.SonarrModal.create4ksonarr": "إضافة سيرفر سونار 4K جديد",
+  "components.Settings.SonarrModal.loadinglanguageprofiles": "جاري تحميل ملفات تعريف اللغة…",
+  "components.Settings.SonarrModal.loadingTags": "جاري تحميل العلامات…",
+  "components.Settings.SonarrModal.loadingprofiles": "جاري تحميل ملفات تعريف الجودة…",
+  "components.Settings.SettingsJobsCache.command": "أمر",
+  "components.Settings.SettingsJobsCache.download-sync": "تحميل الدمج",
+  "components.Settings.SettingsJobsCache.download-sync-reset": "تحميل إعادة تعيين الدمج",
+  "components.Settings.SettingsJobsCache.editJobSchedule": "تعديل المهمة",
+  "components.Settings.SettingsJobsCache.editJobSchedulePrompt": "معدل التكرار",
+  "components.Settings.SettingsJobsCache.editJobScheduleSelectorHours": "كل {jobScheduleHours, plural, one {ساعة} other {{jobScheduleHours} ساعات}}",
+  "components.Settings.SettingsJobsCache.flushcache": "محو الملفات المؤقتة",
+  "components.Settings.SettingsJobsCache.jobScheduleEditSaved": "تم تعديل المهمة بنجاح!",
+  "components.Settings.SettingsJobsCache.jobcancelled": "{jobname} تم إلغاء هذه المهمة.",
+  "components.Settings.SettingsJobsCache.jobname": "إسم المهمة",
+  "components.Settings.SettingsJobsCache.jobs": "المهام",
+  "components.Settings.SettingsJobsCache.jobsandcache": "المهام والملفات المؤقته",
+  "components.Settings.SettingsJobsCache.jobstarted": "{jobname} بدأ عمل هذه المهمة.",
+  "components.Settings.SettingsJobsCache.jobtype": "النوع",
+  "components.Settings.SettingsJobsCache.nextexecution": "وقت التنفيذ التالي",
+  "components.Settings.SettingsJobsCache.plex-full-scan": "الفحص الكلي لمكتبة بليكس",
+  "components.Settings.SettingsJobsCache.plex-recently-added-scan": "فحص المحتويات المضافة مؤخرا على بليكس",
+  "components.Settings.SettingsJobsCache.process": "تنفيذ",
+  "components.Settings.SettingsJobsCache.radarr-scan": "فحص رادار",
+  "components.Settings.SettingsJobsCache.runnow": "تنفيذ \" الآن \"",
+  "components.Settings.SettingsJobsCache.sonarr-scan": "فحص سونار",
+  "components.Settings.SettingsLogs.copiedLogMessage": "نسخ رسائل السجل.",
+  "components.Settings.SettingsLogs.copyToClipboard": "نسخ",
+  "components.Settings.SettingsLogs.extraData": "بيانات إضافية",
+  "components.Settings.SettingsLogs.filterDebug": "متابعة عميقة \" Debug \"",
+  "components.Settings.SettingsLogs.filterError": "خطأ",
+  "components.Settings.SettingsLogs.filterInfo": "معلومات",
+  "components.Settings.SettingsLogs.filterWarn": "تحذير",
+  "components.Settings.SettingsLogs.label": "ملصق",
+  "components.Settings.SettingsLogs.level": "الحدة",
+  "components.Settings.SettingsLogs.logDetails": "تفاصيل السجلات",
+  "components.Settings.SettingsLogs.logsDescription": "تستطيع الإطلاع على هذه السجلات ايضا من خلال <code>stdout</code>, أو في <code>{appDataPath}/logs/overseerr.log</code>.",
+  "components.Settings.SettingsLogs.pauseLogs": "ايقاف مؤقت",
+  "components.Settings.SettingsLogs.time": "الختم الزمني",
+  "components.Settings.SettingsUsers.defaultPermissions": "الاذونات الافتراضية",
+  "components.Settings.SettingsUsers.defaultPermissionsTip": "الإذونات الأساسية للمستخدمين الجدد",
+  "components.Settings.SettingsUsers.localLogin": "تفعيل تسجيل الدخول محليا",
+  "components.Settings.SettingsUsers.localLoginTip": "السماح للمستخدمين بتسجيل الدخول بإستخدام البريد الإلكتروني وكلمة السر بدل التصادق مع بليكس",
+  "components.Settings.SettingsUsers.movieRequestLimitLabel": "الحد الأعلى لطلبات الأفلام ( تعيين عام )",
+  "components.Settings.SettingsUsers.newPlexLogin": "تفعيل تسجيل الدخول لمستخدمين بليكس الجدد",
+  "components.Settings.SettingsUsers.toastSettingsFailure": "حدث خطأ ما أثناء حفظ الإعدادات.",
+  "components.Settings.SettingsUsers.toastSettingsSuccess": "تم حفظ إعدادات المستخدم بنجاح!",
+  "components.Settings.SettingsUsers.tvRequestLimitLabel": "الحد الأعلى لطلبات المسلسلات \"تعيين عام\"",
+  "components.Settings.SettingsUsers.userSettings": "إعدادات المستخدم",
+  "components.Settings.SettingsUsers.userSettingsDescription": "ضبط إعدادت المستخدم العامة والإفتراضية.",
+  "components.Settings.SettingsUsers.users": "المستخدمين",
+  "components.Settings.SonarrModal.add": "إضافة سيرفر",
+  "components.Settings.SonarrModal.animelanguageprofile": "ملف تعريف اللغة للإنمي",
+  "components.Settings.SonarrModal.animequalityprofile": "ملف تعريف الجودة للإنمي",
+  "components.Settings.SonarrModal.animerootfolder": "مجلد حفظ الإنمي",
+  "components.Settings.SonarrModal.apiKey": "مفتاح API",
+  "components.Settings.SonarrModal.createsonarr": "إضافة سيرفر سونار جديد",
+  "components.Settings.SonarrModal.default4kserver": "سيرفر الفور كي الافتراضي",
+  "components.Settings.SonarrModal.defaultserver": "السيرفر الافتراضي",
+  "components.Settings.SonarrModal.edit4ksonarr": "تعديل سيرفر سونار 4K",
+  "components.Settings.SonarrModal.editsonarr": "تعديل سيرفر سونار",
+  "components.Settings.SonarrModal.enableSearch": "تفعيل البحث التلقائي",
+  "components.Settings.SonarrModal.externalUrl": "عنوان الارتباط الخارجي",
+  "components.Settings.SonarrModal.hostname": "إسم المضيف أو رقم الأي بي",
+  "components.Settings.SonarrModal.languageprofile": "ملف تعريف اللغة",
+  "components.Settings.SonarrModal.loadingrootfolders": "جاري تحميل مجلدات الحفظ…",
+  "components.Settings.SonarrModal.notagoptions": "بدون علامات.",
+  "components.Settings.SonarrModal.port": "المنفذ",
+  "components.Settings.SonarrModal.qualityprofile": "ملفات تعريف الجودة",
+  "components.Settings.SonarrModal.rootfolder": "مجلد الحفظ",
+  "components.Settings.SonarrModal.seasonfolders": "مجلدات المواسم",
+  "components.Settings.SonarrModal.selectLanguageProfile": "إختار ملف تعريف اللغة",
+  "components.Settings.SonarrModal.selectQualityProfile": "إختار ملف تعريف الجودة",
+  "components.Settings.SonarrModal.selectRootFolder": "إختار مجلد الحفظ",
+  "components.Settings.SonarrModal.selecttags": "إختار العلامات",
+  "components.Settings.menuGeneralSettings": "عام",
+  "components.Settings.generalsettingsDescription": "ضبط الإعدادات الإفتراضية والأساسية لـ أوفرسيرر.",
+  "components.Settings.locale": "لغة العرض",
+  "components.Settings.manualscanDescription": "عادةً٫ سيتم عمل هذا الفحص مرة واحدة كل 24 ساعة. أوفرسيرر سيفحص المحتوى المضاف مؤخرا في مكتبة بليكس بشكل مكثف. إذا كانت هذه المرة الأولى التي تقوم بها بإعداد بليكس يستحسن أن تقوم بعمل فحص يدوي كامل لمرة واحدة!",
+  "components.Settings.menuAbout": "حول",
+  "components.Settings.plex": "بليكس",
+  "components.Settings.plexlibraries": "مكتبات بليكس",
+  "components.Settings.noDefaultServer": "على الأقل {serverType} سيرفر واحد يجب أن يكون معدا كإفتراضي لإتاحة تنفيذ طلبات الـ {mediaType}.",
+  "components.Settings.plexsettings": "إعدادات بليكس",
+  "components.Settings.serviceSettingsDescription": "قم بإعداد {serverType} سيرفراتك بالإسفل. تستطيع الاتصال بأكثر من سيرفر {serverType} ولكن إثنان فقط يمكن إعدادهما كإفتراضيين واحد لمحتوى الفور كي والاخر لغير الفور كي. الذين يملكون إذونات مسؤول بإمكانهم تجاوز السيرفر المخصص لتنفيذ الطلبات الجديدة قبل الموافقة.",
+  "components.Settings.regionTip": "تصفية المحتوى حسب توفره بالمنطقة",
+  "components.Settings.serverpresetManualMessage": "ضبط يدوي",
+  "components.Settings.sonarrsettings": "إعدادات سونار",
+  "components.Settings.tautulliSettingsDescription": "بشكل إختياري أضبط إعدادات سيرفرك الخاص بـ Tautulli.أوفرسيرر سيقوم بجلب بيانات سجل المشاهدة لمحتوى بليكس من Tautulli.",
+  "components.Settings.webhook": "ويب هوك Webhook",
+  "components.Settings.webpush": "ويب بوش Web Push",
+  "components.Setup.configureplex": "إعداد بليكس",
+  "components.Settings.trustProxyTip": "السماح لأوفرسيرر لتسجيل عناوين الأي بي خلف اتصال بروكسي (يجب إعادة تحميل الصفحة لتطبيق هذا الخيار)",
+  "components.Settings.SonarrModal.server4k": "سيرفر الـ 4K",
+  "components.Settings.SonarrModal.servername": "إسم السيرفر",
+  "components.Settings.SonarrModal.ssl": "إستخدم SSL",
+  "components.Settings.SonarrModal.syncEnabled": "تفعيل الفحص",
+  "components.Settings.SonarrModal.tags": "العلامات",
+  "components.Settings.SonarrModal.testFirstLanguageProfiles": "إختبار الإتصال لتحميل ملفات تعريف اللغة",
+  "components.Settings.SonarrModal.testFirstQualityProfiles": "إختبار الإتصال لتحميل ملفات تعريف الجودة",
+  "components.Settings.SonarrModal.testFirstRootFolders": "إختبار الإتصال لتحميل مجلدات الحفظ",
+  "components.Settings.SonarrModal.testFirstTags": "إختبار الإتصال لتحميل العلامات",
+  "components.Settings.SonarrModal.toastSonarrTestFailure": "فشل الإتصال بـ سونار.",
+  "components.Settings.SonarrModal.toastSonarrTestSuccess": "تم الإتصال بـ سونار بنجاح!",
+  "components.Settings.SonarrModal.validationApiKeyRequired": "يجب ذكر مفتاح API",
+  "components.Settings.SonarrModal.validationApplicationUrl": "يجب ذكر عنوان إرتباط صحيح",
+  "components.Settings.SonarrModal.validationBaseUrlLeadingSlash": "أساس عنوان الإرتباط يجب أن يحتوي على علامة السلاش",
+  "components.Settings.SonarrModal.validationBaseUrlTrailingSlash": "أساس عنوان الإرتباط يجب أن لا يُختتم بعلامة السلاش",
+  "components.Settings.SonarrModal.validationApplicationUrlTrailingSlash": "عنوان الإرتباط يجب أن لا يخُتتم بعلامة السلاش",
+  "components.Settings.SonarrModal.validationHostnameRequired": "يجب كتابة عنوان مضيف أو رقم أي بي صحيح",
+  "components.Settings.SonarrModal.validationLanguageProfileRequired": "يجب إختيار ملف تعريف جودة",
+  "components.Settings.SonarrModal.validationNameRequired": "يجب كتابة إسم السيرفر",
+  "components.Settings.SonarrModal.validationPortRequired": "يجب ذكر رقم منفذ صحيح",
+  "components.Settings.SonarrModal.validationProfileRequired": "يجب إختيار ملف تعريف جودة",
+  "components.Settings.SonarrModal.validationRootFolderRequired": "يجب إختيار مجلد حفظ",
+  "components.Settings.activeProfile": "ملف تعريف نشِط",
+  "components.Settings.addradarr": "إضافة سيرفر رادار",
+  "components.Settings.address": "العناوين",
+  "components.Settings.addsonarr": "إضافة سيرفر سونار",
+  "components.Settings.apikey": "مفتاح API",
+  "components.Settings.applicationTitle": "عنوان التطبيق",
+  "components.Settings.applicationurl": "عنوان إرتباط التطبيق",
+  "components.Settings.cacheImages": "تفعيل التخزين المؤقت للصور",
+  "components.Settings.cacheImagesTip": "موازنة وتخزين كل الصور محليا ( يستهلك مساحة كبيرة من قرص التخزين )",
+  "components.Settings.cancelscan": "إلغاء الفحص",
+  "components.Settings.copied": "نسخ مفتاح الـ API.",
+  "components.Settings.csrfProtection": "تفعيل حماية CSRF",
+  "components.Settings.csrfProtectionHoverTip": "لا تقم بتفعيل هذا الخيار الا اذا كنت مدركا ومطلعا على ماتقوم به!",
+  "components.Settings.csrfProtectionTip": "إعداد مفتاح API خارجي لاعطاء تصريح الاطلاع ( قراءة فقط ) يتطلب إتصال HTTPS وافرسيرر يحتاج لإعاة تحميل الصفحة لتطبيق هذا التغيير",
+  "components.Settings.currentlibrary": "المكتبة الحالية: {name}",
+  "components.Settings.default": "الإفتراضي",
+  "components.Settings.default4k": "فور كي الإفتراضي",
+  "components.Settings.deleteserverconfirm": "هل أنت متأكد من حذف هذا السيرفر؟",
+  "components.Settings.email": "البريد الإلكتروني",
+  "components.Settings.enablessl": "إستخدم SSL",
+  "components.Settings.externalUrl": "عنوان الإرتباط الخارجي",
+  "components.Settings.general": "عام",
+  "components.Settings.generalsettings": "الإعدادات العامة",
+  "components.Settings.hideAvailable": "إخفاء المحتوى المتوفّر",
+  "components.Settings.hostname": "عنوان المضيف أو رقم الأي بي",
+  "components.Settings.is4k": "فور كي",
+  "components.Settings.librariesRemaining": "المكتبات المتبقية: {count}",
+  "components.Settings.manualscan": "فحص يدوي للمكتبة",
+  "components.Settings.mediaTypeMovie": "فيلم",
+  "components.Settings.mediaTypeSeries": "مسلسل",
+  "components.Settings.menuJobs": "المهام والملفات المؤقتة",
+  "components.Settings.menuLogs": "السجلات",
+  "components.Settings.menuNotifications": "التنبيهات",
+  "components.Settings.menuPlexSettings": "بليكس",
+  "components.Settings.menuServices": "الخدمات",
+  "components.Settings.menuUsers": "المستخدمين",
+  "components.Settings.noDefault4kServer": "سيرفر {serverType} مخصص للفور كي يجب أن يكون معدا كإفتراضي لتمكين المستخدمين من طلب محتويات الفور كي لـ {mediaType}.",
+  "components.Settings.noDefaultNon4kServer": "إذا لم يكن لديك سوى سيرفر واحد {serverType} مخصص لكل المحتوى الفور كي وغير الفور كي (أو أنك لا تقوم بتحميل سوى محتوى الفور كي), سيرفرك {serverType} يجب <strong>أن لا</strong> يكون معدا بشكل مخصص لمحتوى الفور كي.",
+  "components.Settings.notificationAgentSettingsDescription": "ضبط وتفعيل خدمات التنبيهات.",
+  "components.Settings.notifications": "التنبيهات",
+  "components.Settings.notificationsettings": "اعدادات التنبيهات",
+  "components.Settings.notrunning": "لا يعمل",
+  "components.Settings.originallanguage": "لغة العرض الخاصة بـ إكتشف المحتوى",
+  "components.Settings.originallanguageTip": "تصفية المحتوى بحسب اللغة الأصلية",
+  "components.Settings.partialRequestsEnabled": "السماح بطلب المسلسلات بشكل جزئي",
+  "components.Settings.plexlibrariesDescription": "المكتبات التي سيقوم أوفرسيرر بفحصها. قم بإعداد وحفظ إعدادات الإتصال ببليكس ثم قم بالضغط على الزر بالإسفل اذا لم تظهر مكتبات بليكس بالقائمة.",
+  "components.Settings.plexsettingsDescription": "ضبط إعدادات سيرفر بليكس. أوفرسيرر سيفحص مكتبات بليكس للتأكد من توفر المحتوى من عدمه.",
+  "components.Settings.port": "المنفذ",
+  "components.Settings.radarrsettings": "إعدادات رادار",
+  "components.Settings.region": "المنطقة الخاصة بـ إكتشاف محتوى جديد",
+  "components.Settings.scan": "دمج المكتبات",
+  "components.Settings.scanning": "جاري الدمج…",
+  "components.Settings.serverLocal": "محلي",
+  "components.Settings.serverRemote": "عن بعد",
+  "components.Settings.serverSecure": "أمن",
+  "components.Settings.serverpreset": "سيرفر",
+  "components.Settings.serverpresetLoad": "اضغط على الزر لتحميل السيرفرات المتاحة",
+  "components.Settings.serverpresetRefreshing": "جاري جلب السيرفرات…",
+  "components.Settings.services": "الخدمات",
+  "components.Settings.settingUpPlexDescription": "لإعداد بليكس٫ تستطيع كتابة التفاصيل بشكل يدوي أو إختيار السيرفر جلب السيرفر منretrieved from <RegisterPlexTVLink>plex.tv</RegisterPlexTVLink>. إضغط على الزر يمين القائمة المنسدلة لجلب قائمة السيرفرات المتاحة.",
+  "components.Settings.ssl": "إتصال SSL",
+  "components.Settings.startscan": "إبدأ الفحص",
+  "components.Settings.tautulliApiKey": "مفتاح API",
+  "components.Settings.tautulliSettings": "إعدادات Tautulli",
+  "components.Settings.toastApiKeyFailure": "حدث خطأ ما أثناء محاولة توريد مفتاح API جديد.",
+  "components.Settings.toastApiKeySuccess": "تم توريد مفتاح API جديد بنجاح!",
+  "components.Settings.toastPlexConnecting": "جاري محاولة الإتصال ببليكس…",
+  "components.Settings.toastPlexConnectingFailure": "فشل الإتصال ببليكس.",
+  "components.Settings.toastPlexConnectingSuccess": "تم الإتصال ببليكس بنجاح!",
+  "components.Settings.toastPlexRefresh": "جاري جلب قائمة السيرفرات من بليكس…",
+  "components.Settings.toastPlexRefreshFailure": "فشل جلب قائمة السيرفرات.",
+  "components.Settings.toastPlexRefreshSuccess": "تم جلب قائمة السيرفرات من بليكس بنجاح!",
+  "components.Settings.toastSettingsFailure": "حدث خطأ ما أثناء حفظ الإعدادات.",
+  "components.Settings.toastSettingsSuccess": "تم حفظ الإعدادات بنجاح!",
+  "components.Settings.toastTautulliSettingsFailure": "حدث خطأ ما أثناء حفظ إعدادات Tautulli.",
+  "components.Settings.toastTautulliSettingsSuccess": "تم حفظ إعدادات Tautulli بنجاح !",
+  "components.Settings.trustProxy": "تفعيل دعم البروكسي",
+  "components.Settings.urlBase": "عنوان الإرتباط الأساسي",
+  "components.Settings.validationApiKey": "يجب كتابة مفتاح API",
+  "components.Settings.validationApplicationTitle": "يجب كتابة عنوان التطبيق",
+  "components.Settings.validationApplicationUrl": "يجب كتابة عنوان إرتباط صحيح",
+  "components.Settings.validationApplicationUrlTrailingSlash": "يجب أن لا ينتهي عنوان الإرتباط بعلامة السلاش",
+  "components.Settings.validationHostnameRequired": "يجب كتابة إسم مضيف أو رقم أي بي صحيح",
+  "components.Settings.validationPortRequired": "يجب كتابة رقم منفذ صحيح",
+  "components.Settings.validationUrl": "يجب كتابة عنوان ارتباط صحيح",
+  "components.Settings.validationUrlBaseLeadingSlash": "عنوان الارتباط الأساسي يجب أن يحتوي على علامة السلاش",
+  "components.Settings.validationUrlBaseTrailingSlash": "عنوان الإرتباط الأساسي يجب أن لا ينتهي بعلامة السلاش",
+  "components.Settings.validationUrlTrailingSlash": "عنوان الإرتباط يجب أن لا ينتهي بعلامة السلاش",
+  "components.Settings.webAppUrl": "<WebAppLink>Web App</WebAppLink> عنوان الارتباط",
+  "components.Settings.webAppUrlTip": "بشكل إختياري توجيه المستخدمين لصفحة ويب التطبيق في سيرفرك بدل صفحة ويب التطبيق المستضاف",
+  "components.Setup.configureservices": "إعداد الخدمات",
+  "components.Setup.continue": "إستمرار",
+  "components.Setup.finish": "إنهاء الإعداد",
+  "components.Setup.finishing": "جاري الإنهاء…",
+  "components.UserList.userdeleted": "تم حذف المستخدم بنجاح!",
+  "components.UserList.users": "المستخدمين",
+  "components.TvDetails.play4konplex": "تشغيل بجودة فور كي في بليكس",
+  "components.TvDetails.seasons": "{seasonCount, plural, one {# موسم} other {# مواسم}}",
+  "components.TvDetails.showtype": "نوع المسلسل",
+  "components.UserList.accounttype": "النوع",
+  "components.UserList.admin": "مسؤول",
+  "components.UserList.displayName": "إسم العرض",
+  "components.TvDetails.cast": "الطاقم",
+  "components.TvDetails.streamingproviders": "يعرض حاليا على",
+  "components.UserList.deleteuser": "حذف المستخدم",
+  "components.UserList.importfromplex": "جلب مستخدمين بليكس",
+  "components.UserList.localuser": "مستخدم محلي",
+  "components.UserList.newplexsigninenabled": "<strong>خاصية تفعيل تسجيل دخول مستخدم جديد من بليكس</strong>مفعلة حاليا. مستخدمين بليكس الذين لديهم صلاحية الإطلاع على مكتبة بليكس لا يحتاجون لان يتم جلبهم ليتمكنوا من تسجيل الدخول.",
+  "components.UserProfile.ProfileHeader.settings": "تعديل الإعدادات",
+  "components.UserProfile.UserSettings.UserGeneralSettings.accounttype": "نوع الحساب",
+  "components.UserProfile.UserSettings.UserGeneralSettings.admin": "مسؤول",
+  "components.UserProfile.UserSettings.UserGeneralSettings.applanguage": "لغة العرض",
+  "components.UserProfile.UserSettings.UserGeneralSettings.regionTip": "تصفية المحتوى بحسب توفره بالمنطقة",
+  "components.UserProfile.UserSettings.UserGeneralSettings.validationDiscordId": "يجب ذكر رقم مستخدم ديسكورد صحيح",
+  "components.UserProfile.UserSettings.UserNotificationSettings.discordsettingssaved": "تم حفظ إعدادات تنيه الديسكورد بنجاح!",
+  "components.UserProfile.UserSettings.UserNotificationSettings.notificationsettings": "إعدادات التنبيه",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletsettingsfailed": "فشل حفظ إعدادات تنبيه Pushbullet.",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoverApplicationTokenTip": "<ApplicationRegistrationLink>تسجيل تطبيق application</ApplicationRegistrationLink> للإستخدام مع {applicationTitle}",
+  "i18n.approve": "موافقة",
+  "components.UserProfile.UserSettings.UserNotificationSettings.validationPgpPublicKey": "يجب ذكر مفتاح عام PGP صحيح",
+  "components.UserProfile.UserSettings.UserNotificationSettings.webpushsettingsfailed": "فشل حفظ إعدادات تنبيه web Push.",
+  "components.UserProfile.UserSettings.UserPasswordChange.newpassword": "كلمة سر جديد",
+  "components.UserProfile.UserSettings.UserPermissions.unauthorizedDescription": "لا تستطيع تعديل صلاحياتك المُعطاة.",
+  "components.UserProfile.UserSettings.UserPasswordChange.noPasswordSet": "حساب هذا المستخدم بدون كلمة سر حاليا. قم بإعداد كلمة سر بالإسفل لإتاحة هذا الحساب من تسجيل الدخول \"كمستخدم محلي.\"",
+  "components.UserProfile.UserSettings.UserPasswordChange.toastSettingsSuccess": "تم حفظ كلمة السر بنجاح!",
+  "components.UserProfile.UserSettings.unauthorizedDescription": "لا تملك الصلاحية لتعديل إعدادات هذا المستخدم.",
+  "components.UserProfile.totalrequests": "مجموع الطلبات",
+  "i18n.deleting": "جاري الحذف…",
+  "i18n.delete": "حذف",
+  "i18n.requesting": "جاري الطلب…",
+  "pages.somethingwentwrong": "حدث خطأ ما",
+  "components.Setup.loginwithplex": "تسجيل دخول بواسطة بليكس",
+  "components.Setup.scanbackground": "الفحص سيستمر بالخلفية. تستطيع إكمال عملية الإعداد في الوقت الحالي.",
+  "components.Setup.setup": "الإعداد",
+  "components.Setup.signinMessage": "إبدأ من خلال تسجيل دخولك بحساب بليكس",
+  "components.Setup.tip": "تلميحات",
+  "components.Setup.welcome": "مرحبا بك في أوفرسيرر",
+  "components.StatusBadge.status": "{status}",
+  "components.StatusBadge.status4k": "4K {status}",
+  "components.TvDetails.TvCast.fullseriescast": "طاقم عمل المسلسل",
+  "components.TvDetails.TvCrew.fullseriescrew": "طاقم فريق المسلسل",
+  "components.TvDetails.anime": "إنمي",
+  "components.TvDetails.episodeRuntime": "مدة عرض الحلقة",
+  "components.TvDetails.episodeRuntimeMinutes": "{runtime} دقيقة",
+  "components.TvDetails.firstAirDate": "تاريخ العرض الأول",
+  "components.TvDetails.network": "{networkCount, plural, one {شبكة بث} other {شبكات بث}}",
+  "components.TvDetails.nextAirDate": "تاريخ العرض التالي",
+  "components.TvDetails.originallanguage": "اللغة الأصلية",
+  "components.TvDetails.originaltitle": "العنوان الأصلي",
+  "components.TvDetails.overview": "نظرة عامة",
+  "components.TvDetails.overviewunavailable": "النظرة العامة غير متاحة.",
+  "components.TvDetails.playonplex": "تشغيل في بليكس",
+  "components.TvDetails.productioncountries": "الإنتاج {countryCount, plural, one {الدولة} other {الدول}}",
+  "components.TvDetails.recommendations": "التوصيات",
+  "components.TvDetails.similar": "مسلسلات مشابهه",
+  "components.TvDetails.viewfullcrew": "رؤية طاقم العمل",
+  "components.TvDetails.watchtrailer": "شاهد الإعلان",
+  "components.UserList.autogeneratepassword": "إنشاء كلمة سر بشكل تلقائي",
+  "components.UserList.autogeneratepasswordTip": "أرسل كلمة السر المنشئة الى إيميل المستخدم",
+  "components.UserList.bulkedit": "تعديل شامل ( للمحدد )",
+  "components.UserList.create": "إنشاء",
+  "components.UserList.created": "مُنضم",
+  "components.UserList.createlocaluser": "إنشاء مستخدم محلي",
+  "components.UserList.creating": "جاري الإنشاء…",
+  "components.UserList.deleteconfirm": "هل أنت متأكد من حذف هذا المستخدم؟ كل الطلبات التي تم إنشاءها من خلاله سيتم حذفها بشكل نهائي.",
+  "components.UserList.edituser": "تعديل صلاحيات المستخدم",
+  "components.UserList.email": "عنوان البريد الإلكتروني",
+  "components.UserList.importedfromplex": "<strong>{userCount}</strong> Plex {userCount, plural, one {مستخدم} other {مستخدمين}} تم جلبهم بنجاح!",
+  "components.UserList.importfromplexerror": "حدث خطأ ما أثناء محاولة جلب المستخدمين.",
+  "components.UserList.localLoginDisabled": "<strong>خاصية تفعيل تسجيل الدخول المحلي</strong> معطلة حاليا.",
+  "components.UserList.nouserstoimport": "لا يوجد مستخدمين بليكس ليتم جلبهم.",
+  "components.UserList.owner": "المالك",
+  "components.UserList.password": "كلمة السر",
+  "components.UserList.passwordinfodescription": "ضبط عنوان إرتباط التطبيق وتفعيل تنبيهات الإيميل للسماح بإنشاء كلمات سر تلقائية.",
+  "components.UserList.plexuser": "مستخدم بليكس",
+  "components.UserList.role": "الدور",
+  "components.UserList.sortCreated": "تاريخ الإنضمام",
+  "components.UserList.sortDisplayName": "إسم العرض",
+  "components.UserList.sortRequests": "عدد الطلبات",
+  "components.UserList.totalrequests": "الطلبات",
+  "components.UserList.user": "المستخدم",
+  "components.UserList.usercreatedfailed": "حدث خطأ ما أثناء إنشاء المستخدم.",
+  "components.UserList.usercreatedfailedexisting": "عنوان البريد الإلكتروني المزوّد مستعمل من قبل مستخدم أخر.",
+  "components.UserList.usercreatedsuccess": "تم إنشاء المستخدم بنجاح!",
+  "components.UserList.userdeleteerror": "حدث خطأ ما أثناء حذف المستخدم.",
+  "components.UserList.userfail": "حدث خطأ ما أثناء حفظ صلاحيات المستخدم.",
+  "components.UserList.userlist": "قائمة المستخدم",
+  "components.UserList.userssaved": "تم حفظ صلاحيات المستخدم بنجاح!",
+  "components.UserList.validationEmail": "يجب عليك ذكر عنوان بريد إلكتروني صحيح",
+  "components.UserList.validationpasswordminchars": "كلمة السر قصيرة جدا؛ الحد الأدنى 8 خانات",
+  "components.UserProfile.ProfileHeader.joindate": "منضم {joindate}",
+  "components.UserProfile.ProfileHeader.profile": "رؤية ملف التعريف",
+  "components.UserProfile.ProfileHeader.userid": "رقم المستخدم: {userid}",
+  "components.UserProfile.UserSettings.UserGeneralSettings.discordId": "رقم ديسكورد المستخدم",
+  "components.UserProfile.UserSettings.UserGeneralSettings.discordIdTip": "<FindDiscordIdLink>رقم متعدد الخانات</FindDiscordIdLink> مرتبط بحساب عضوية الديسكورد",
+  "components.UserProfile.UserSettings.UserGeneralSettings.displayName": "إسم العرض",
+  "components.UserProfile.UserSettings.UserGeneralSettings.enableOverride": "تجاوز الحد العام",
+  "components.UserProfile.UserSettings.UserGeneralSettings.general": "عام",
+  "components.UserProfile.UserSettings.UserGeneralSettings.generalsettings": "الإعدادات العامة",
+  "components.UserProfile.UserSettings.UserGeneralSettings.languageDefault": "الإفتراضي ({language})",
+  "components.UserProfile.UserSettings.UserGeneralSettings.localuser": "مستخدم محلي",
+  "components.UserProfile.UserSettings.UserGeneralSettings.movierequestlimit": "الحد الأقصى لطلبات الأفلام",
+  "components.UserProfile.UserSettings.UserGeneralSettings.originallanguage": "لغة العرض الخاصة بـ إكتشف محتوى جديد",
+  "components.UserProfile.UserSettings.UserGeneralSettings.originallanguageTip": "تصفية المحتوى بحسب اللغة الأصلية",
+  "components.UserProfile.UserSettings.UserGeneralSettings.owner": "المالك",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexuser": "مستخدم بليكس",
+  "components.UserProfile.UserSettings.UserGeneralSettings.region": "المنطقة لـ إكتشف محتوى جديد",
+  "components.UserProfile.UserSettings.UserGeneralSettings.role": "الدور",
+  "components.UserProfile.UserSettings.UserGeneralSettings.seriesrequestlimit": "الحد الأقصى لطلبات المسلسلات",
+  "components.UserProfile.UserSettings.UserGeneralSettings.toastSettingsFailure": "حدث خطأ ما أثناء حفظ الإعدادات.",
+  "components.UserProfile.UserSettings.UserGeneralSettings.toastSettingsSuccess": "تم حفظ الإعدادات بنجاح!",
+  "components.UserProfile.UserSettings.UserGeneralSettings.user": "مستخدم",
+  "components.UserProfile.UserSettings.UserNotificationSettings.discordId": "رقم عضوية المستخدم",
+  "components.UserProfile.UserSettings.UserNotificationSettings.discordIdTip": "ة <FindDiscordIdLink>رقم متعدد الخانات</FindDiscordIdLink> مرتبط بحساب المستخدم",
+  "components.UserProfile.UserSettings.UserNotificationSettings.discordsettingsfailed": "فشل حفظ إعدادات تنبيه الديسكورد.",
+  "components.UserProfile.UserSettings.UserNotificationSettings.email": "البريد الإلكتروني",
+  "components.UserProfile.UserSettings.UserNotificationSettings.emailsettingsfailed": "فشل حفظ إعدادات تنبيه الإيميل.",
+  "components.UserProfile.UserSettings.UserNotificationSettings.emailsettingssaved": "تم حفظ إعدادات تنبيه الإيميل بنجاح!",
+  "components.UserProfile.UserSettings.UserNotificationSettings.notifications": "التنبيهات",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pgpPublicKey": "مفتاح PGP العام",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pgpPublicKeyTip": "رسائل إيميل مشفرة باستخدام <OpenPgpLink>OpenPGP</OpenPgpLink>",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletAccessToken": "مفتاح الدخول Token",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletAccessTokenTip": "إنشاء Token من <PushbulletSettingsLink>إعدادات الحساب </PushbulletSettingsLink>",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletsettingssaved": "تم حفظ إعدادات تنبيه Pushbullet بنجاح!",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoverApplicationToken": "مفتاح التطبيق API Token",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoverUserKey": "مستخدم أو مفتاح مجموعة",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoverUserKeyTip": "الثلاثين خانة الخاصةبـ <UsersGroupsLink>بمعرف المستخدم أو المجموعة </UsersGroupsLink>",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoversettingsfailed": "فشل حفظ إعدادات تنبيه Pushover.",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoversettingssaved": "تم حفظ إعدادات تنبيه Pushover بنجاح!",
+  "components.UserProfile.UserSettings.UserNotificationSettings.telegramChatId": "رقم عضوية المحادثة",
+  "components.UserProfile.UserSettings.UserNotificationSettings.telegramChatIdTipLong": "<TelegramBotLink>إبدأ محادثة مع</TelegramBotLink>, قم بإضافة <GetIdBotLink>@get_id_bot</GetIdBotLink>, قم بإرسال الأمر <code>/my_id</code>",
+  "components.UserProfile.UserSettings.UserNotificationSettings.telegramsettingsfailed": "فشل حفظ إعدادات تنبيه التليقرام.",
+  "components.UserProfile.UserSettings.UserNotificationSettings.telegramsettingssaved": "تم حفظ إعدادات تنبيه التليقرام بنجاح!",
+  "components.UserProfile.UserSettings.UserNotificationSettings.validationDiscordId": "يجب ذكر رقم عضوية مستخدم صحيحة",
+  "components.UserProfile.UserSettings.UserNotificationSettings.sendSilently": "أرسل بصمت",
+  "components.UserProfile.UserSettings.UserNotificationSettings.sendSilentlyDescription": "ارسال التنبيهات بدون صوت",
+  "components.UserProfile.UserSettings.UserNotificationSettings.validationPushbulletAccessToken": "يجب ذكر Access Token",
+  "components.UserProfile.UserSettings.UserNotificationSettings.validationPushoverApplicationToken": "يجب ذكر Access Token صحيح",
+  "components.UserProfile.UserSettings.UserNotificationSettings.validationPushoverUserKey": "يجب ذكر مفتاح مستخدم او مجموعة صحيح",
+  "components.UserProfile.UserSettings.UserNotificationSettings.validationTelegramChatId": "يجب ذكر رقم هوية محادثة صحيحة",
+  "components.UserProfile.UserSettings.UserNotificationSettings.webpush": "ويب بوش Web Push",
+  "components.UserProfile.UserSettings.UserNotificationSettings.webpushsettingssaved": "تم حفظ إعدادات تنبيه Web Push بنجاح!",
+  "components.UserProfile.UserSettings.UserPasswordChange.confirmpassword": "تأكيد كلمة السر",
+  "components.UserProfile.UserSettings.UserPasswordChange.currentpassword": "كلمة السر الحالية",
+  "components.UserProfile.UserSettings.UserPasswordChange.noPasswordSetOwnAccount": "حسابك حاليا بدون كلمة سر. قم بإعداد كلمة سر بالأسفل لإتاحة تسجيل الدخول كـ\"مستخدم محلي\" بإستخدام البريد الإلكتروني.",
+  "components.UserProfile.UserSettings.UserPasswordChange.nopermissionDescription": "ليس لديك الصلاحية لتعديل كلمة سر هذا المستخدم.",
+  "components.UserProfile.UserSettings.UserPasswordChange.password": "كلمة السر",
+  "components.UserProfile.UserSettings.UserPasswordChange.toastSettingsFailure": "حدث خطأ ما أثناء حفظ كلمة السر.",
+  "components.UserProfile.UserSettings.UserPasswordChange.toastSettingsFailureVerifyCurrent": "حدث خطأ ما أثناء حفظ كلمة السر. هل كان إدخالك لكلمة السر صحيحا؟",
+  "components.UserProfile.UserSettings.UserPasswordChange.validationConfirmPassword": "يجب تأكيد كلمة السر الجديدة",
+  "components.UserProfile.UserSettings.UserPasswordChange.validationConfirmPasswordSame": "كلمات السر المُدخله يجب أن تتطابق",
+  "components.UserProfile.UserSettings.UserPasswordChange.validationCurrentPassword": "يجب كتابة كلمة السر الحالية",
+  "components.UserProfile.UserSettings.UserPasswordChange.validationNewPassword": "يجب كتابة كلمة سر جديدة",
+  "components.UserProfile.UserSettings.UserPasswordChange.validationNewPasswordLength": "كلمة السر قصيرة جدا؛ الحد الأدنى ثمانية خانات",
+  "components.UserProfile.UserSettings.UserPermissions.permissions": "الصلاحيات",
+  "components.UserProfile.UserSettings.UserPermissions.toastSettingsFailure": "حدث خطأ ما أثناء حفظ الإعدادات.",
+  "components.UserProfile.UserSettings.UserPermissions.toastSettingsSuccess": "تم حفظ إعدادات الصلاحيات بنجاح!",
+  "components.UserProfile.UserSettings.menuChangePass": "كلمة السر",
+  "components.UserProfile.UserSettings.menuGeneralSettings": "عام",
+  "components.UserProfile.UserSettings.menuNotifications": "التنبيهات",
+  "components.UserProfile.UserSettings.menuPermissions": "الصلاحيات",
+  "components.UserProfile.limit": "{remaining} من {limit}",
+  "components.UserProfile.movierequests": "طلبات الأفلام",
+  "components.UserProfile.pastdays": "{type} (كل {days} أيام/يوم)",
+  "components.UserProfile.recentlywatched": "تم مشاهدتها موخرا",
+  "components.UserProfile.recentrequests": "الطلبات الحديثة",
+  "components.UserProfile.requestsperdays": "{limit} متبقي",
+  "components.UserProfile.seriesrequest": "طلبات المسلسلات",
+  "components.UserProfile.unlimited": "غير محدود",
+  "i18n.advanced": "متقدم",
+  "i18n.all": "الكل",
+  "i18n.approved": "تمت الموافقة عليه",
+  "i18n.areyousure": "هل أنت متأكد؟",
+  "i18n.available": "متوفر",
+  "i18n.back": "عودة",
+  "i18n.cancel": "إلغاء",
+  "i18n.canceling": "جاري الإلغاء…",
+  "i18n.close": "إغلاق",
+  "i18n.decline": "رفض",
+  "i18n.declined": "تم رفضه",
+  "i18n.delimitedlist": "{a}, {b}",
+  "i18n.edit": "تعديل",
+  "i18n.experimental": "تحت التجربة",
+  "i18n.failed": "فشل",
+  "i18n.import": "إستيراد/جلب",
+  "i18n.importing": "جاري الإستيراد…",
+  "i18n.loading": "جاري التحميل…",
+  "i18n.movie": "فيلم",
+  "i18n.movies": "أفلام",
+  "i18n.next": "التالي",
+  "i18n.noresults": "لا يوجد نتائج.",
+  "i18n.notrequested": "لم يتم طلبه",
+  "i18n.open": "مفتوح",
+  "i18n.partiallyavailable": "متوفر بشكل جزئي",
+  "i18n.pending": "معلّق",
+  "i18n.previous": "السابق",
+  "i18n.processing": "تنفيذ",
+  "i18n.request": "طلب",
+  "i18n.request4k": "طلب بجودة فور كي",
+  "i18n.requested": "تم طلبه",
+  "i18n.resolved": "تم الحل",
+  "i18n.resultsperpage": "عرض {pageSize} نتائج بالصفحة الواحدة",
+  "i18n.retry": "إعادة محاولة",
+  "i18n.retrying": "جاري إعادة المحاولة…",
+  "i18n.save": "حفظ التغييرات",
+  "i18n.saving": "جاري الحفظ…",
+  "i18n.settings": "إعدادات",
+  "i18n.showingresults": "عرض <strong>{from}</strong> الى <strong>{to}</strong> من <strong>{total}</strong> نتائج",
+  "i18n.status": "الحالة",
+  "i18n.test": "إختبار",
+  "i18n.testing": "جاري الإختبار…",
+  "i18n.tvshow": "مسلسلات",
+  "i18n.tvshows": "مسلسلات",
+  "i18n.unavailable": "غير متاح",
+  "i18n.usersettings": "إعدادات المستخدم",
+  "i18n.view": "عرض",
+  "pages.errormessagewithcode": "{statusCode} - {error}",
+  "pages.internalservererror": "خطأ سيرفر داخلي",
+  "pages.oops": "أوبسس",
+  "pages.pagenotfound": "الصفحة غير متاحة",
+  "pages.returnHome": "عودة للقائمة الرئيسية",
+  "pages.serviceunavailable": "الخدمة غير متاحة",
+  "components.RequestBlock.languageprofile": "لغة ملف التعريف"
+}
diff --git a/src/i18n/locale/ca.json b/src/i18n/locale/ca.json
index 05c903af..5199a2a5 100644
--- a/src/i18n/locale/ca.json
+++ b/src/i18n/locale/ca.json
@@ -14,16 +14,15 @@
   "components.UserList.accounttype": "Tipus",
   "components.RequestModal.QuotaDisplay.quotaLinkUser": "Podeu veure un resum dels límits de sol·licituds d’aquest usuari a la seva <ProfileLink>pàgina de perfil</ProfileLink>.",
   "components.RequestModal.QuotaDisplay.requiredquota": "Necessites tenir al menys <strong>{seasons}</strong> {seasons, plural, one {petició de temporada} other {peticions de temporades}} restant(s) per a poder enviar una petició per a aquesta sèrie.",
-  "components.RequestModal.pendingrequest": "Sol·licitud pendent de {title}",
-  "components.RequestModal.pending4krequest": "Sol·licitud en 4K pendent per a {title}",
+  "components.RequestModal.pendingrequest": "Sol·licitud pendent",
+  "components.RequestModal.pending4krequest": "Sol·licitud en 4K pendent",
   "components.RequestModal.numberofepisodes": "# d'episodis",
   "components.RequestModal.extras": "Extres",
   "components.RequestModal.errorediting": "S'ha produït un error en editar la sol·licitud.",
   "components.RequestModal.cancel": "Cancel·la la petició",
   "components.RequestModal.autoapproval": "Aprovació automàtica",
   "components.RequestModal.alreadyrequested": "Ja s'ha sol·licitat",
-  "components.RequestModal.SearchByNameModal.notvdbiddescription": "No s'ha pogut emparellat automàticament la vostra sol·licitud. Seleccioneu l'emparellament correcte de la llista següent.",
-  "components.RequestModal.SearchByNameModal.nosummary": "No s'ha trobat cap sinopsi per a aquest títol.",
+  "components.RequestModal.SearchByNameModal.notvdbiddescription": "No s'ha pogut trobar coincidència d'aquesta serie. Seleccioneu l'emparellament correcte de la llista següent.",
   "components.RequestModal.QuotaDisplay.seasonlimit": "{limit, plural, one {temporada} other {temporades}}",
   "components.RequestModal.QuotaDisplay.season": "temporada",
   "components.RequestModal.QuotaDisplay.requiredquotaUser": "Aquest usuari ha de tenir almenys <strong>{seasons}</strong> {seasons, plural, one {sol·licitud de temporada} other {sol·licituds de temporades}} per enviar una sol·licitud per a aquesta sèrie.",
@@ -51,7 +50,7 @@
   "components.PermissionEdit.request": "Sol·licitud",
   "components.RequestBlock.seasons": "{seasonCount, plural, one {Temporada} other {Temporades}}",
   "components.PermissionEdit.usersDescription": "Concedeix permís per gestionar els usuaris d'Overseerr. Els usuaris amb aquest permís no poden modificar els usuaris administrador ni concedir aquest privilegi a altres.",
-  "components.PermissionEdit.request4k": "Sol·licita 4K",
+  "components.PermissionEdit.request4k": "Sol·licitud 4K",
   "components.MovieDetails.revenue": "Recaptació",
   "components.RequestCard.seasons": "{seasonCount, plural, one {Temporada} other {Temporades}}",
   "components.RequestList.requests": "Sol·licituds",
@@ -89,13 +88,11 @@
   "components.PermissionEdit.viewrequestsDescription": "Concedeix permís per veure les sol·licituds de continguts d'altres usuaris.",
   "components.PermissionEdit.viewrequests": "Veure sol·licituds",
   "components.PermissionEdit.users": "Gestiona els usuaris",
-  "components.PermissionEdit.settingsDescription": "Concedeix permís per modificar els paràmetres globals. Un usuari ha de tenir aquest permís per concedir-lo a altres persones.",
-  "components.PermissionEdit.settings": "Gestiona la configuració",
   "components.PermissionEdit.requestDescription": "Concedeix permís per sol·licitar contingut no 4K.",
   "components.PermissionEdit.request4kTvDescription": "Concedeix permís per sol·licitar sèrie en 4K.",
   "components.PermissionEdit.request4kTv": "Sol·licita Sèrie en 4K",
   "components.PermissionEdit.request4kMoviesDescription": "Concedeix permís per sol·licitar pel·lícules en 4K.",
-  "components.PermissionEdit.request4kMovies": "Sol·liciteu pel·lícules en 4K",
+  "components.PermissionEdit.request4kMovies": "Sol·licitud de pel·lícules en 4K",
   "components.PermissionEdit.request4kDescription": "Concedeix permís per sol·licitar contingut en 4K.",
   "components.PermissionEdit.managerequestsDescription": "Concedeix permís per gestionar les sol·licituds de contingut d'Overseerr. Totes les sol·licituds que faci un usuari amb aquest permís s’aprovaran automàticament.",
   "components.PermissionEdit.managerequests": "Gestiona les sol·licituds",
@@ -217,7 +214,6 @@
   "components.RequestModal.requestadmin": "Aquesta sol·licitud s'aprovarà automàticament.",
   "components.RequestModal.requestCancel": "S'ha cancel·lat la sol·licitud de <strong>{title}</strong>.",
   "components.RequestModal.requestSuccess": "<strong>{title}</strong> s'ha sol·licitat correctament!",
-  "components.RequestModal.request4ktitle": "Sol·licita {title} en 4K",
   "components.Settings.Notifications.NotificationsSlack.validationWebhookUrl": "Heu de proporcionar un URL vàlid",
   "components.Settings.Notifications.NotificationsSlack.slacksettingssaved": "La configuració de notificacions Slack s'ha desat correctament!",
   "components.Settings.Notifications.NotificationsSlack.slacksettingsfailed": "No s'ha pogut desar la configuració de notificacions Slack.",
@@ -252,7 +248,6 @@
   "components.RequestModal.selectseason": "Selecciona les temporades",
   "components.RequestModal.seasonnumber": "Temporada {number}",
   "components.RequestModal.season": "Temporada",
-  "components.RequestModal.requesttitle": "Sol·licita {title}",
   "components.RequestModal.requestseasons": "Sol·licita {seasonCount} {seasonCount, plural, one {Temporada} other {Temporades}}",
   "components.Settings.Notifications.discordsettingssaved": "La configuració de les notificacions de Discord s'ha desat correctament!",
   "components.Settings.Notifications.NotificationsWebhook.webhooksettingsfailed": "No s'ha pogut desar la configuració de notificacions del Webhook.",
@@ -335,7 +330,6 @@
   "components.UserProfile.requestsperdays": "{limit} restants",
   "components.UserProfile.recentrequests": "Sol·licituds recents",
   "components.UserProfile.pastdays": "{type} (últims {days} dies)",
-  "components.UserProfile.norequests": "Sense sol·licituds.",
   "components.UserProfile.movierequests": "Sol·licituds de pel·lícules",
   "components.UserProfile.limit": "{remaining} de {limit}",
   "components.UserProfile.UserSettings.unauthorizedDescription": "No teniu permís per modificar la configuració d'aquest usuari.",
@@ -406,7 +400,6 @@
   "components.TvDetails.originallanguage": "Idioma original",
   "components.TvDetails.nextAirDate": "Pròxima data d'emissió",
   "components.TvDetails.network": "{networkCount, plural, one {Plataforma} other {Plataformes}}",
-  "components.StatusChacker.reloadOverseerr": "Torna a Carregar",
   "components.TvDetails.firstAirDate": "Primera data d'emissió",
   "components.TvDetails.episodeRuntimeMinutes": "{runtime} minuts",
   "components.TvDetails.episodeRuntime": "Duració de l'episodi",
@@ -414,8 +407,6 @@
   "components.TvDetails.anime": "Anime",
   "components.TvDetails.TvCrew.fullseriescrew": "Equip complet de la sèrie",
   "components.TvDetails.TvCast.fullseriescast": "Repartiment complet de la sèrie",
-  "components.StatusChacker.newversionavailable": "Actualització de l'aplicació",
-  "components.StatusChacker.newversionDescription": "Overseerr s'ha actualitzat! Feu clic al botó següent per tornar a carregar la pàgina.",
   "components.StatusBadge.status4k": "4K {status}",
   "components.Setup.welcome": "Benvingut a Overseerr",
   "components.Setup.tip": "Consell",
@@ -436,7 +427,7 @@
   "components.Settings.validationApplicationUrlTrailingSlash": "L'URL no pot acabar amb una barra inclinada final",
   "components.Settings.validationApplicationUrl": "Heu de proporcionar un URL vàlid",
   "components.Settings.validationApplicationTitle": "Heu de proporcionar un títol d'aplicació",
-  "components.Settings.trustProxyTip": "Permet a Overseerr registrar correctament les adreces IP del client darrere d’un servidor intermediari (s’ha de tornar a carregar Overseerr perquè els canvis tinguin efecte)",
+  "components.Settings.trustProxyTip": "Permet a Overseerr registrar correctament les adreces IP del client darrere d’un servidor intermediari",
   "components.Settings.toastSettingsSuccess": "La configuració s'ha desat correctament!",
   "components.Settings.toastSettingsFailure": "S'ha produït un error en desar la configuració.",
   "components.Settings.toastPlexRefreshSuccess": "La llista de servidors Plex s'ha recuperat correctament!",
@@ -495,7 +486,7 @@
   "components.Settings.deleteserverconfirm": "Esteu segur que voleu suprimir aquest servidor?",
   "components.Settings.currentlibrary": "Biblioteca actual: {name}",
   "components.Settings.cancelscan": "Cancel·la l'exploració",
-  "components.Settings.cacheImagesTip": "Optimitzeu i emmagatzemeu totes les imatges de forma local (consumeix una quantitat important d'espai en disc)",
+  "components.Settings.cacheImagesTip": "Posa en memòria cau i carrega imatges optimitzades (requereix una quantitat important d'espai en disc)",
   "components.Settings.applicationTitle": "Títol de l'aplicació",
   "components.Settings.addsonarr": "Afegeix un servidor Sonarr",
   "components.Settings.activeProfile": "Perfil actiu",
@@ -503,7 +494,7 @@
   "components.Settings.email": "Adreça electrònica",
   "components.Settings.default4k": "4K predeterminat",
   "components.Settings.default": "Predeterminat",
-  "components.Settings.csrfProtectionTip": "Estableix l'accés a l'API externa de només lectura (requereix HTTPS i s'ha de tornar a carregar Overseerr perquè els canvis tinguin efecte)",
+  "components.Settings.csrfProtectionTip": "Estableix l'accés a l'API externa de només lectura (requereix HTTPS)",
   "components.Settings.csrfProtectionHoverTip": "NO activeu aquesta configuració tret que entengueu el que esteu fent!",
   "components.Settings.csrfProtection": "Activeu la protecció CSRF",
   "components.Settings.copied": "S'ha copiat la clau API al porta-retalls.",
@@ -740,17 +731,16 @@
   "components.Settings.Notifications.validationPgpPassword": "Heu de proporcionar una contrasenya PGP",
   "components.Settings.Notifications.botUsernameTip": "Permetre als usuaris iniciar un xat amb el bot i configurar les seves pròpies notificacions",
   "components.RequestModal.pendingapproval": "La vostra sol·licitud està pendent d'aprovació.",
-  "components.RequestList.RequestItem.mediaerror": "El títol associat per a aquesta sol·licitud ja no està disponible.",
+  "components.RequestList.RequestItem.mediaerror": "No s'ha trobat {mediaType}",
   "components.RequestList.RequestItem.deleterequest": "Suprimeix la sol·licitud",
   "components.RequestList.RequestItem.cancelRequest": "Cancel·la la sol·licitud",
-  "components.RequestCard.mediaerror": "El títol associat per a aquesta sol·licitud ja no està disponible.",
+  "components.RequestCard.mediaerror": "No s'ha trobat {mediaType}",
   "components.RequestCard.deleterequest": "Suprimeix la sol·licitud",
   "components.NotificationTypeSelector.notificationTypes": "Tipus de notificacions",
   "components.Layout.VersionStatus.streamstable": "Overseer (Estable)",
   "components.Layout.VersionStatus.streamdevelop": "Overseerr (Desenvolupament)",
   "components.Layout.VersionStatus.outofdate": "No està actualitzat",
   "components.Layout.VersionStatus.commitsbehind": "{commitsBehind} {commitsBehind, plural, one {canvi} other {canvis}} posterior(s)",
-  "components.Discover.noRequests": "No hi ha cap sol·licitud.",
   "components.UserList.usercreatedfailedexisting": "Un altre usuari ja utilitza l'adreça electrònica proporcionada.",
   "components.Settings.SonarrModal.enableSearch": "Activa la cerca automàtica",
   "components.Settings.RadarrModal.enableSearch": "Activa la cerca automàtica",
@@ -919,7 +909,6 @@
   "components.IssueModal.CreateIssueModal.toastSuccessCreate": "L'informe de la incidència per a <strong>{title}</strong> s'ha enviat correctament!",
   "components.IssueModal.CreateIssueModal.problemseason": "Temporada afectada",
   "components.IssueModal.CreateIssueModal.episode": "Episodi {episodeNumber}",
-  "components.IssueModal.CreateIssueModal.issomethingwrong": "Hi ha algun problema amb {title}?",
   "components.IssueList.sortModified": "Última modificació",
   "components.IssueList.sortAdded": "Més recent",
   "components.NotificationTypeSelector.issuecommentDescription": "Envia notificacions quan les incidències rebin comentaris nous.",
@@ -930,7 +919,7 @@
   "components.NotificationTypeSelector.adminissuecommentDescription": "Notifica'm quan altres usuaris facin comentaris sobre incidències.",
   "components.ManageSlideOver.tvshow": "sèries",
   "components.Settings.SettingsJobsCache.editJobSchedule": "Modifica la tasca programada",
-  "components.Settings.SettingsJobsCache.editJobSchedulePrompt": "Freqüència",
+  "components.Settings.SettingsJobsCache.editJobSchedulePrompt": "Freqüència nova",
   "components.Settings.SettingsJobsCache.editJobScheduleSelectorHours": "Cada {jobScheduleHours, plural, one {hora} other {{jobScheduleHours} hores}}",
   "components.Settings.SettingsJobsCache.editJobScheduleSelectorMinutes": "Cada {jobScheduleMinutes, plural, one {minut} other {{jobScheduleMinutes} minuts}}",
   "components.UserProfile.UserSettings.UserNotificationSettings.pushoverApplicationTokenTip": "<ApplicationRegistrationLink>Registreu una aplicació</ApplicationRegistrationLink> per utilitzar-la amb {applicationTitle}",
@@ -960,8 +949,8 @@
   "components.ManageSlideOver.openarr": "Obre a {arr}",
   "components.ManageSlideOver.openarr4k": "Obre en 4K {arr}",
   "components.NotificationTypeSelector.issueresolved": "Incidència resolta",
-  "components.PermissionEdit.createissues": "Incidències informades",
-  "components.PermissionEdit.viewissues": "Veure incidències",
+  "components.PermissionEdit.createissues": "Informa d'incidències",
+  "components.PermissionEdit.viewissues": "Veure altres incidències",
   "components.PermissionEdit.viewissuesDescription": "Doneu permís per veure incidències de continguts informats per altres usuaris.",
   "components.PermissionEdit.createissuesDescription": "Doneu permís per informar incidències en continguts.",
   "components.PermissionEdit.manageissues": "Gestiona les incidències",
@@ -1000,7 +989,7 @@
   "components.Settings.RadarrModal.released": "Alliberat",
   "components.Settings.Notifications.NotificationsGotify.agentenabled": "Activa l'agent",
   "components.Settings.Notifications.NotificationsGotify.gotifysettingsfailed": "La configuració de notificacions de Gotify no s'ha pogut desar.",
-  "components.Settings.Notifications.NotificationsGotify.gotifysettingssaved": "La configuració de notificacions de Gotify s'ha desat correctament.",
+  "components.Settings.Notifications.NotificationsGotify.gotifysettingssaved": "La configuració de notificacions de Gotify s'ha desat correctament!",
   "components.Settings.Notifications.NotificationsGotify.validationTokenRequired": "Heu de proporcionar un testimoni d'aplicació",
   "components.UserProfile.UserSettings.UserGeneralSettings.discordIdTip": "El <FindDiscordIdLink>número d'ID de diversos dígits</FindDiscordIdLink> associat al vostre compte d'usuari de Discord",
   "components.ManageSlideOver.manageModalAdvanced": "Avançat",
@@ -1040,5 +1029,93 @@
   "components.Settings.SettingsAbout.appDataPath": "Directori de dades",
   "components.UserProfile.UserSettings.UserGeneralSettings.discordId": "Identificador d'usuari de Discord",
   "components.UserProfile.UserSettings.UserGeneralSettings.validationDiscordId": "Heu de proporcionar un identificador d'usuari de Discord vàlid",
-  "i18n.importing": "S'està important…"
+  "i18n.importing": "S'està important…",
+  "components.RequestBlock.languageprofile": "Perfil d'idioma",
+  "components.AirDateBadge.airedrelative": "Emès {relativeTime}",
+  "components.MovieDetails.digitalrelease": "Llançament digital",
+  "components.MovieDetails.physicalrelease": "Alliberament físic",
+  "components.PermissionEdit.viewrecent": "Veure afegits recentment",
+  "components.PermissionEdit.viewrecentDescription": "Concediu permís per veure la llista de mitjans afegits recentment.",
+  "components.Settings.deleteServer": "Suprimeix el servidor {serverType}",
+  "components.StatusChecker.reloadApp": "Torna a carregar {applicationTitle}",
+  "components.TitleCard.cleardata": "Esborra les dades",
+  "i18n.restartRequired": "Cal reiniciar",
+  "components.RequestList.RequestItem.tvdbid": "Identificador de TheTVDB",
+  "components.TitleCard.tvdbid": "Identificador de TheTVDB",
+  "components.RequestList.RequestItem.tmdbid": "Identificador TMDB",
+  "components.Discover.DiscoverWatchlist.discoverwatchlist": "La vostra llista de seguiment de Plex",
+  "components.Discover.plexwatchlist": "La vostra llista de seguiment de Plex",
+  "components.PermissionEdit.autorequest": "Sol·licitud automàtica",
+  "components.NotificationTypeSelector.mediaautorequested": "Sol·licitud enviada automàticament",
+  "components.NotificationTypeSelector.mediaautorequestedDescription": "Rep notificacions quan s'enviïn automàticament sol·licituds de contingut multimèdia nous per als elements de la teva llista de seguiment de Plex.",
+  "components.RequestCard.tmdbid": "Identificador TMDB",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmoviestip": "Sol·liciteu automàticament pel·lícules de la vostra <PlexWatchlistSupportLink>Llista de seguiment de Plex</PlexWatchlistSupportLink>",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmovies": "Sol·licitud automàtica de pel·lícules",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseries": "Sol·licitud automàtica de sèries",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseriestip": "Sol·liciteu sèries automàticament de la vostra <PlexWatchlistSupportLink>Llista de seguiment de Plex</PlexWatchlistSupportLink>",
+  "components.PermissionEdit.autorequestSeries": "Sol·licitud automàtica de sèrie",
+  "components.PermissionEdit.autorequestMovies": "Sol·licitud automàtica de pel·lícules",
+  "components.PermissionEdit.autorequestMoviesDescription": "Concediu permís per enviar automàticament sol·licituds de pel·lícules que no siguin 4K mitjançant Plex Watchlist.",
+  "components.PermissionEdit.autorequestSeriesDescription": "Concediu permís per enviar automàticament sol·licituds de sèries que no siguin 4K mitjançant Plex Watchlist.",
+  "components.Settings.SettingsLogs.viewdetails": "Veure detalls",
+  "components.TitleCard.tmdbid": "Identificador TMDB",
+  "components.Discover.DiscoverWatchlist.watchlist": "Llista de seguiment de Plex",
+  "components.MovieDetails.managemovie": "Gestiona la pel·lícula",
+  "components.MovieDetails.theatricalrelease": "Estrena en cines",
+  "components.PermissionEdit.autorequestDescription": "Concediu permís per enviar automàticament sol·licituds de mitjans que no siguin 4K mitjançant llistes de seguiment de Plex.",
+  "components.PermissionEdit.viewwatchlists": "Veure les llistes de seguiment de Plex",
+  "components.PermissionEdit.viewwatchlistsDescription": "Concediu permís per veure les llistes de seguiment de Plex d'altres usuaris.",
+  "components.RequestCard.tvdbid": "Identificador de TheTVDB",
+  "components.Settings.advancedTooltip": "La configuració incorrecta d'aquesta configuració pot provocar un malfuncionament",
+  "components.Settings.experimentalTooltip": "L'activació d'aquesta configuració pot provocar un comportament inesperat de l'aplicació",
+  "components.TvDetails.reportissue": "Informar d'un problema",
+  "components.TitleCard.mediaerror": "No s'ha trobat {mediaType}",
+  "components.UserProfile.plexwatchlist": "Llista de seguiment de Plex",
+  "components.Layout.UserDropdown.requests": "Sol·licituds",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.movierequests": "Sol·licituds de pel·lícules",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.seriesrequests": "Sol·licituds de sèries",
+  "components.MovieDetails.reportissue": "Informa d'un problema",
+  "components.StatusChecker.appUpdatedDescription": "Feu clic al botó següent per tornar a carregar l'aplicació.",
+  "components.StatusChecker.appUpdated": "Actualitzat {applicationTitle}",
+  "components.StatusChecker.restartRequiredDescription": "Si us plau, reinicieu el servidor per aplicar la configuració actualitzada.",
+  "components.AirDateBadge.airsrelative": "Emissió {relativeTime}",
+  "components.MovieDetails.rtaudiencescore": "Puntuació d'audiència de Rotten Tomatoes",
+  "components.MovieDetails.rtcriticsscore": "Tomàmetre Rotten Tomatoes",
+  "components.MovieDetails.tmdbuserscore": "Puntuació d'usuaris de TMDB",
+  "components.RequestBlock.approve": "Aprova la sol·licitud",
+  "components.RequestBlock.decline": "Rebutja la sol·licitud",
+  "components.RequestBlock.requestdate": "Data de sol·licitud",
+  "components.RequestBlock.requestedby": "Sol·licitat per",
+  "components.Settings.restartrequiredTooltip": "Overseerr s'ha de reiniciar perquè els canvis a aquesta configuració tinguin efecte",
+  "components.StatusBadge.managemedia": "Gestiona {mediaType}",
+  "components.TvDetails.Season.somethingwentwrong": "S'ha produït un error en recuperar les dades de la temporada.",
+  "components.TvDetails.rtaudiencescore": "Puntuació d'audiència de Rotten Tomatoes",
+  "components.TvDetails.rtcriticsscore": "Tomàmetre Rotten Tomatoes",
+  "components.TvDetails.seasonstitle": "Temporades",
+  "components.RequestCard.approverequest": "Aprova la sol·licitud",
+  "components.RequestCard.cancelrequest": "Cancel·la la sol·licitud",
+  "components.RequestCard.editrequest": "Edita la sol·licitud",
+  "components.TvDetails.manageseries": "Gestiona les Sèries",
+  "components.RequestBlock.delete": "Suprimeix la sol·licitud",
+  "components.RequestBlock.edit": "Edita la sol·licitud",
+  "components.RequestBlock.lastmodifiedby": "Última modificació per",
+  "components.StatusBadge.playonplex": "Reprodueix a Plex",
+  "components.RequestCard.declinerequest": "Rebutja la sol·licitud",
+  "components.StatusBadge.openinarr": "Obre a {arr}",
+  "components.Settings.SettingsJobsCache.plex-watchlist-sync": "Sincronització de la llista de seguiment de Plex",
+  "components.TvDetails.seasonnumber": "Temporada {seasonNumber}",
+  "components.TvDetails.episodeCount": "{episodeCount, plural, one {# Episodi} other {# Episodis}}",
+  "components.TvDetails.tmdbuserscore": "Puntuació d'usuaris de TMDB",
+  "components.TvDetails.status4k": "4K {status}",
+  "components.StatusChecker.restartRequired": "Cal reiniciar el servidor",
+  "components.Discover.emptywatchlist": "Els mitjans afegits a la vostra <PlexWatchlistSupportLink>Llista de seguiment de Plex</PlexWatchlistSupportLink> apareixeran aquí.",
+  "components.RequestModal.requestcollection4ktitle": "Sol·licitud de col·lecció en 4K",
+  "components.RequestModal.SearchByNameModal.nomatches": "No hem pogut trobar cap coincidència per a aquesta sèrie.",
+  "components.UserProfile.emptywatchlist": "Els mitjans afegits a la vostra <PlexWatchlistSupportLink>Llista de seguiment de Plex</PlexWatchlistSupportLink> apareixeran aquí.",
+  "components.RequestModal.requestseries4ktitle": "Sol·licitud de sèries en 4K",
+  "components.RequestModal.requestcollectiontitle": "Sol·licitud de col·lecció",
+  "components.RequestModal.requestmovie4ktitle": "Sol·licitud de pel·lícula en 4K",
+  "components.RequestModal.requestmovietitle": "Sol·licitud de pel·lícula",
+  "components.RequestModal.requestseriestitle": "Sol·licitud de sèries",
+  "components.Settings.SettingsJobsCache.editJobScheduleCurrent": "Freqüència actual"
 }
diff --git a/src/i18n/locale/cs.json b/src/i18n/locale/cs.json
index fd8ef3ba..c4af1428 100644
--- a/src/i18n/locale/cs.json
+++ b/src/i18n/locale/cs.json
@@ -26,9 +26,9 @@
   "components.Settings.SettingsUsers.userSettings": "Uživatelské nastavení",
   "components.Settings.SettingsUsers.defaultPermissions": "Výchozí oprávnění",
   "components.Settings.SettingsJobsCache.unknownJob": "Neznámá úloha",
-  "components.Settings.SettingsJobsCache.sonarr-scan": "Sonarr Sken",
+  "components.Settings.SettingsJobsCache.sonarr-scan": "Sonarr sken",
   "components.Settings.SettingsJobsCache.runnow": "Spustit nyní",
-  "components.Settings.SettingsJobsCache.radarr-scan": "Radarr Sken",
+  "components.Settings.SettingsJobsCache.radarr-scan": "Radarr sken",
   "components.Settings.SettingsJobsCache.jobstarted": "{jobname} zahájeno.",
   "components.Settings.SettingsJobsCache.jobname": "Název úlohy",
   "components.Settings.SettingsJobsCache.jobcancelled": "{jobname} zrušeno.",
@@ -40,11 +40,11 @@
   "components.Settings.SettingsAbout.totalmedia": "Celkový počet médií",
   "components.Settings.SettingsAbout.timezone": "Časové pásmo",
   "components.Settings.SettingsAbout.supportoverseerr": "Podpořte Overseerr",
-  "components.Settings.SettingsAbout.overseerrinformation": "Overseerr Informace",
+  "components.Settings.SettingsAbout.overseerrinformation": "O Overseer",
   "components.Settings.SettingsAbout.githubdiscussions": "Diskuze na GitHubu",
   "components.Settings.SettingsAbout.Releases.viewchangelog": "Zobrazit seznam změn",
-  "components.Settings.SettingsAbout.Releases.versionChangelog": "Seznam změn",
-  "components.Settings.SettingsAbout.Releases.currentversion": "Aktuální verze",
+  "components.Settings.SettingsAbout.Releases.versionChangelog": "{version} Seznam změn",
+  "components.Settings.SettingsAbout.Releases.currentversion": "Aktuální",
   "components.Settings.RadarrModal.syncEnabled": "Povolit skenování",
   "components.Settings.RadarrModal.ssl": "Použít SSL",
   "components.Settings.RadarrModal.servername": "Název serveru",
@@ -85,13 +85,12 @@
   "components.Settings.Notifications.NotificationsLunaSea.webhookUrl": "Webhook URL",
   "components.Settings.Notifications.NotificationsLunaSea.profileName": "Jméno profilu",
   "components.Settings.Notifications.NotificationsLunaSea.agentenabled": "Povolit agenta",
-  "components.Search.searchresults": "Výsledek vyhledávání",
+  "components.Search.searchresults": "Výsledky vyhledávání",
   "components.ResetPassword.passwordreset": "Obnovení hesla",
   "components.ResetPassword.email": "E-mailová adresa",
   "components.ResetPassword.confirmpassword": "Potvrďte heslo",
   "components.RequestModal.selectseason": "Vyberte série",
   "components.RequestModal.seasonnumber": "{number} Série",
-  "components.RequestModal.requesttitle": "Zažádat o {title}",
   "components.RequestModal.edit": "Upravit žádost",
   "components.RequestModal.cancel": "Zrušit žádost",
   "components.RequestModal.autoapproval": "Automatické schválení",
@@ -106,7 +105,7 @@
   "components.RequestModal.AdvancedRequester.destinationserver": "Cílový server",
   "components.RequestModal.AdvancedRequester.default": "{name} (výchozí)",
   "components.RequestList.sortModified": "Naposledy změněno",
-  "components.RequestList.sortAdded": "Datum žádosti",
+  "components.RequestList.sortAdded": "Nejnovější",
   "components.RequestList.RequestItem.editrequest": "Upravit žádost",
   "components.RequestList.RequestItem.deleterequest": "Odstranit žádost",
   "components.RequestList.RequestItem.cancelRequest": "Zrušit žádost",
@@ -127,10 +126,9 @@
   "components.PersonDetails.ascharacter": "jako {character}",
   "components.PermissionEdit.viewrequests": "Zobrazit žádosti",
   "components.PermissionEdit.users": "Spravovat uživatele",
-  "components.PermissionEdit.settings": "Spravovat nastavení",
   "components.PermissionEdit.requestTv": "Žádat seriály",
-  "components.PermissionEdit.requestMovies": "Žádat filmy",
-  "components.PermissionEdit.request4k": "Žádosti ve 4K",
+  "components.PermissionEdit.requestMovies": "Vyžádat filmy",
+  "components.PermissionEdit.request4k": "Vyžádat ve 4K",
   "components.PermissionEdit.managerequests": "Spravovat žádosti",
   "components.PermissionEdit.autoapproveSeries": "Automaticky schvalovat seriály",
   "components.PermissionEdit.autoapproveMovies": "Automaticky schvalovat filmy",
@@ -156,7 +154,6 @@
   "components.TvDetails.overview": "Přehled",
   "components.TvDetails.cast": "Obsazení",
   "components.TvDetails.anime": "Anime",
-  "components.StatusChacker.reloadOverseerr": "Znovu načíst",
   "components.Setup.tip": "Tip",
   "components.Setup.setup": "Konfigurace",
   "components.Setup.finishing": "Dokončování…",
@@ -235,7 +232,7 @@
   "components.NotificationTypeSelector.usermediaapprovedDescription": "Získat upozornění na schválení vašich žádostí o média.",
   "components.NotificationTypeSelector.usermediaAutoApprovedDescription": "Získat upozornění, když ostatní uživatelé zadají nové požadavky na média, která jsou automaticky schválena.",
   "components.NotificationTypeSelector.mediarequestedDescription": "Odeslat oznámení, když uživatelé zažádají o média vyžadující schválení.",
-  "components.MovieDetails.streamingproviders": "Aktuálně streamovatelné zde",
+  "components.MovieDetails.streamingproviders": "Aktuálně streamovatelné na",
   "pages.serviceunavailable": "Služba není k dispozici",
   "pages.returnHome": "Vrátit se domů",
   "pages.pagenotfound": "Stránka nebyla nalezena",
@@ -294,7 +291,6 @@
   "components.UserProfile.seriesrequest": "Seriál zažádán",
   "components.UserProfile.requestsperdays": "Zbývá {limit}",
   "components.UserProfile.recentrequests": "Nedávné žádosti",
-  "components.UserProfile.norequests": "Žádné žádosti.",
   "components.UserProfile.UserSettings.menuPermissions": "Oprávnění",
   "components.UserProfile.UserSettings.menuNotifications": "Oznámení",
   "components.UserProfile.UserSettings.menuGeneralSettings": "Obecné",
@@ -319,17 +315,17 @@
   "components.PermissionEdit.advancedrequest": "Pokročilé žádosti",
   "components.PermissionEdit.admin": "Admin",
   "components.NotificationTypeSelector.notificationTypes": "Typy oznámení",
-  "components.NotificationTypeSelector.mediarequested": "Médium zažádáno",
+  "components.NotificationTypeSelector.mediarequested": "Žádost čeká na schválení",
   "components.NotificationTypeSelector.mediafailedDescription": "Odeslat oznámení, když se nepodaří přidat požadavky na média do Radarru nebo Sonarru.",
-  "components.NotificationTypeSelector.mediafailed": "Médium selhalo",
+  "components.NotificationTypeSelector.mediafailed": "Zpracování požadavku se nezdařilo",
   "components.NotificationTypeSelector.mediadeclinedDescription": "Odeslat oznámení, pokud jsou požadavky na média odmítnuty.",
-  "components.NotificationTypeSelector.mediadeclined": "Médium odmítnuto",
+  "components.NotificationTypeSelector.mediadeclined": "Žádost zamítnuta",
   "components.NotificationTypeSelector.mediaavailableDescription": "Odeslat oznámení, jakmile budou k dispozici žádosti o média.",
-  "components.NotificationTypeSelector.mediaavailable": "Médium je k dispozici",
+  "components.NotificationTypeSelector.mediaavailable": "Žádost k dispozici",
   "components.NotificationTypeSelector.mediaapprovedDescription": "Odeslat oznámení, když jsou požadavky na média ručně schváleny.",
-  "components.NotificationTypeSelector.mediaapproved": "Médium schváleno",
+  "components.NotificationTypeSelector.mediaapproved": "Žádost schválena",
   "components.NotificationTypeSelector.mediaAutoApprovedDescription": "Odeslat oznámení, když uživatelé zadají nové požadavky na média, která jsou automaticky schválena.",
-  "components.NotificationTypeSelector.mediaAutoApproved": "Médium automaticky schváleno",
+  "components.NotificationTypeSelector.mediaAutoApproved": "Žádost automaticky schválena",
   "components.MovieDetails.watchtrailer": "Sledovat trailer",
   "components.MovieDetails.viewfullcrew": "Zobrazit kompletní štáb",
   "components.MovieDetails.similar": "Podobné tituly",
@@ -337,7 +333,7 @@
   "components.MovieDetails.showless": "Zobrazit méně",
   "components.MovieDetails.runtime": "{minutes} minut",
   "components.MovieDetails.revenue": "Výnos",
-  "components.MovieDetails.releasedate": "Datum vydání",
+  "components.MovieDetails.releasedate": "{releaseCount, plural, one {Dátum vydání} other {Dátumy vydání}}",
   "components.MovieDetails.recommendations": "Doporučení",
   "components.MovieDetails.playonplex": "Přehrát v Plexu",
   "components.MovieDetails.play4konplex": "Přehrát v Plexu ve 4K",
@@ -390,7 +386,6 @@
   "components.Discover.DiscoverTvGenre.genreSeries": "{genre} Seriály",
   "components.Discover.DiscoverNetwork.networkSeries": "{network} Seriály",
   "components.Discover.popularmovies": "Populární filmy",
-  "components.Discover.noRequests": "Žádné požadavky.",
   "components.Discover.discovermovies": "Populární filmy",
   "components.Discover.discover": "Objevte",
   "components.Discover.TvGenreSlider.tvgenres": "Žánry seriálů",
@@ -410,7 +405,7 @@
   "components.Settings.SettingsJobsCache.cachemisses": "Neúspěchy",
   "components.NotificationTypeSelector.usermediadeclinedDescription": "Dostat oznámení o odmítnutí vašich požadavků na média.",
   "components.NotificationTypeSelector.usermediaavailableDescription": "Dostat oznámení, jakmile budou k dispozici žádosti o média.",
-  "components.Layout.VersionStatus.commitsbehind": "{commitsBehind} {commitsBehind, plural, one {commit} other {commits}} za",
+  "components.Layout.VersionStatus.commitsbehind": "{commitsBehind} {commitsBehind, plural, one {commit} other {commitů}} za",
   "components.Setup.configureplex": "Konfigurovat Plex",
   "components.Settings.serverpresetRefreshing": "Načítání serverů…",
   "components.Settings.applicationTitle": "Název aplikace",
@@ -472,7 +467,7 @@
   "components.IssueDetails.IssueComment.edit": "Upravit komentář",
   "components.IssueDetails.allseasons": "Všechny série",
   "components.IssueDetails.closeissue": "Uzavřít problém",
-  "components.ManageSlideOver.downloadstatus": "Stav stahování",
+  "components.ManageSlideOver.downloadstatus": "Stahování",
   "components.NotificationTypeSelector.issueresolved": "Problém vyřešen",
   "components.RequestList.RequestItem.modifieduserdate": "{date} od {user}",
   "components.RequestList.showallrequests": "Zobrazit všechny žádosti",
@@ -492,7 +487,6 @@
   "components.RequestModal.requestSuccess": "<strong>{title}</strong> bylo úspěšně zažádáno!",
   "components.Settings.SettingsLogs.logDetails": "Podrobnosti o záznamu",
   "components.StatusBadge.status4k": "4K {status}",
-  "components.StatusChacker.newversionavailable": "Aktualizace aplikace",
   "components.TvDetails.episodeRuntime": "Délka epizody",
   "components.TvDetails.episodeRuntimeMinutes": "{runtime} minut",
   "components.TvDetails.originallanguage": "Původní jazyk",
@@ -539,5 +533,588 @@
   "components.UserProfile.UserSettings.UserNotificationSettings.notificationsettings": "Nastavení oznámení",
   "components.UserProfile.UserSettings.UserNotificationSettings.telegramChatId": "ID chatu",
   "components.UserProfile.UserSettings.UserPasswordChange.confirmpassword": "Potvrďte heslo",
-  "components.UserProfile.UserSettings.UserPasswordChange.currentpassword": "Aktuální heslo"
+  "components.UserProfile.UserSettings.UserPasswordChange.currentpassword": "Aktuální heslo",
+  "components.IssueDetails.toastissuedeleted": "Problém byl úspěšně smazán!",
+  "components.IssueDetails.toaststatusupdated": "Stav problému byl úspěšně aktualizován!",
+  "components.ManageSlideOver.markavailable": "Označit jako dostupné",
+  "components.IssueDetails.commentplaceholder": "Přidat komentář…",
+  "components.IssueDetails.openedby": "#{issueId} otevřeno {relativeTime} uživatelem {username}",
+  "components.IssueDetails.openin4karr": "Otevřít ve 4K {arr}",
+  "components.IssueDetails.reopenissueandcomment": "Znovu otevřít pomocí komentáře",
+  "components.IssueModal.CreateIssueModal.validationMessageRequired": "Musíte poskytnout popis",
+  "components.ManageSlideOver.manageModalClearMedia": "Vyčistit data",
+  "components.ManageSlideOver.alltime": "Pořád",
+  "components.ManageSlideOver.manageModalAdvanced": "Pokročilý",
+  "components.ManageSlideOver.manageModalClearMediaWarning": "* Tímto nenávratně odstraníte všechna data pro tento {mediaType}, včetně všech požadavků. Pokud tato položka existuje ve vaší knihovně Plex, informace o médiích budou znovu vytvořeny během příštího skenování.",
+  "components.ManageSlideOver.manageModalMedia": "Média",
+  "components.ManageSlideOver.manageModalMedia4k": "4K Média",
+  "components.ManageSlideOver.markallseasonsavailable": "Označte všechny sezóny jako dostupné",
+  "components.ManageSlideOver.markallseasons4kavailable": "Označte všechny sezóny jako dostupné ve 4K",
+  "components.ManageSlideOver.openarr": "Otevřít v {arr}",
+  "components.ManageSlideOver.openarr4k": "Otevřít ve 4K {arr}",
+  "components.ManageSlideOver.opentautulli": "Otevřít v Tautulli",
+  "components.NotificationTypeSelector.adminissuecommentDescription": "Buďte upozorněn, když ostatní uživatelé komentují problémy.",
+  "components.NotificationTypeSelector.adminissuereopenedDescription": "Buďte upozorněn, když problémy znovu otevřou jiní uživatelé.",
+  "components.IssueDetails.toaststatusupdatefailed": "Při aktualizaci stavu problému se něco pokazilo.",
+  "components.IssueDetails.IssueComment.postedby": "Zveřejněno {relativeTime} uživatelem {username}",
+  "components.IssueDetails.playonplex": "Přehrát na Plex",
+  "components.IssueDetails.play4konplex": "Přehrát ve 4K na Plex",
+  "components.IssueList.IssueItem.openeduserdate": "{date} od uživatele {user}",
+  "components.IssueModal.CreateIssueModal.providedetail": "Uveďte prosím podrobné vysvětlení problému, na který jste narazili.",
+  "components.IssueModal.CreateIssueModal.reportissue": "Nahlásit problém",
+  "components.IssueModal.CreateIssueModal.toastFailedCreate": "Při odesílání problému se něco pokazilo.",
+  "components.IssueDetails.IssueComment.validationComment": "Musíte zadat zprávu",
+  "components.IssueDetails.IssueComment.areyousuredelete": "Opravdu chcete tento komentář smazat?",
+  "components.IssueDetails.openinarr": "Otevřít v {arr}",
+  "components.IssueDetails.IssueComment.postedbyedited": "Zveřejněno {relativeTime} uživatelem {username} (upraveno)",
+  "components.IssueDetails.toasteditdescriptionsuccess": "Popis problému byl úspěšně upraven!",
+  "components.IssueDetails.deleteissueconfirm": "Opravdu chcete tento problém smazat?",
+  "components.IssueDetails.toasteditdescriptionfailed": "Při úpravě popisu problému se něco pokazilo.",
+  "components.IssueDetails.toastissuedeletefailed": "Při mazání problému se něco pokazilo.",
+  "components.IssueModal.CreateIssueModal.extras": "Speciály",
+  "components.IssueList.showallissues": "Zobrazit všechny problémy",
+  "components.IssueModal.CreateIssueModal.toastSuccessCreate": "Zpráva o problému pro <strong>{title}</strong> byla úspěšně odeslána!",
+  "components.ManageSlideOver.mark4kavailable": "Označit jako dostupné ve 4K",
+  "components.NotificationTypeSelector.issuereopened": "Problém znovu otevřen",
+  "components.NotificationTypeSelector.userissuecreatedDescription": "Získejte upozornění, když ostatní uživatelé nahlásí problémy.",
+  "components.PermissionEdit.advancedrequestDescription": "Udělení oprávnění k úpravě pokročilých možností vyžádání médií.",
+  "components.PermissionEdit.request4kMovies": "Vyžádat si filmy 4K",
+  "components.PermissionEdit.usersDescription": "Udělení oprávnění ke správě uživatelů. Uživatelé s tímto oprávněním nemohou upravovat uživatele s oprávněním správce nebo jim toto oprávnění udělit.",
+  "components.RequestModal.selectmovies": "Vyberte film(y)",
+  "components.Settings.Notifications.NotificationsPushover.toastPushoverTestSending": "Odeslání oznámení o testu Pushover…",
+  "components.Settings.Notifications.NotificationsSlack.slacksettingssaved": "Nastavení oznámení služby Slack bylo úspěšně uloženo!",
+  "components.Settings.Notifications.NotificationsWebPush.toastWebPushTestFailed": "Testovací oznámení Web push se nepodařilo odeslat.",
+  "components.Settings.Notifications.encryptionDefault": "Použijte protokol STARTTLS, pokud je k dispozici",
+  "components.Settings.Notifications.pgpPrivateKey": "Soukromý klíč PGP",
+  "components.Settings.Notifications.validationEmail": "Musíte zadat platnou e-mailovou adresu",
+  "components.Settings.Notifications.validationPgpPrivateKey": "Musíte zadat platný soukromý klíč PGP",
+  "components.Settings.Notifications.validationUrl": "Musíte zadat platnou adresu URL",
+  "components.Settings.Notifications.validationPgpPassword": "Musíte zadat heslo PGP",
+  "components.Settings.RadarrModal.loadingrootfolders": "Načítání kořenových složek…",
+  "components.Settings.RadarrModal.testFirstQualityProfiles": "Test připojení pro načtení profilů kvality",
+  "components.Settings.RadarrModal.validationRootFolderRequired": "Je třeba vybrat kořenovou složku",
+  "components.Settings.SettingsAbout.Releases.releasedataMissing": "Údaje o vydání jsou momentálně nedostupné.",
+  "components.Settings.SettingsAbout.gettingsupport": "Získání podpory",
+  "components.Settings.SettingsJobsCache.download-sync-reset": "Resetování synchronizace stažení",
+  "components.Settings.SettingsJobsCache.jobScheduleEditFailed": "Při ukládání úlohy se něco pokazilo.",
+  "components.Settings.SonarrModal.testFirstQualityProfiles": "Test připojení pro načtení profilů kvality",
+  "components.Settings.notificationAgentSettingsDescription": "Konfigurace a povolení agentů pro oznámení.",
+  "components.Settings.settingUpPlexDescription": "Chcete-li nastavit službu Plex, můžete buď zadat údaje ručně, nebo vybrat server získaný z adresy <RegisterPlexTVLink>plex.tv</RegisterPlexTVLink>. Stisknutím tlačítka vpravo od rozevírací nabídky načtete seznam dostupných serverů.",
+  "components.Settings.toastPlexRefreshFailure": "Nepodařilo se načíst seznam serverů Plex.",
+  "components.TvDetails.play4konplex": "Přehrávání v rozlišení 4K na platformě Plex",
+  "components.TvDetails.playonplex": "Přehrávání v systému Plex",
+  "components.UserProfile.UserSettings.UserGeneralSettings.regionTip": "Filtrování obsahu podle regionální dostupnosti",
+  "components.Settings.Notifications.NotificationsGotify.agentenabled": "Povolení agenta",
+  "components.Settings.Notifications.NotificationsGotify.gotifysettingsfailed": "Nastavení oznámení Gotify se nepodařilo uložit.",
+  "components.Settings.Notifications.NotificationsGotify.gotifysettingssaved": "Nastavení oznámení Gotify úspěšně uloženo!",
+  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestFailed": "Testovací oznámení Gotify se nepodařilo odeslat.",
+  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestSending": "Odeslání oznámení o testu Gotify…",
+  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestSuccess": "Oznámení o testu Gotify odesláno!",
+  "components.Settings.Notifications.NotificationsGotify.validationUrlTrailingSlash": "Adresa URL nesmí končit koncovým lomítkem",
+  "components.Settings.Notifications.NotificationsGotify.validationTypes": "Musíte vybrat alespoň jeden typ oznámení",
+  "components.Settings.Notifications.NotificationsLunaSea.toastLunaSeaTestSuccess": "Oznámení o testu LunaSea odesláno!",
+  "components.Settings.Notifications.NotificationsGotify.validationUrlRequired": "Musíte zadat platnou adresu URL",
+  "components.Settings.Notifications.NotificationsPushbullet.toastPushbulletTestSuccess": "Testovací oznámení Pushbullet odesláno!",
+  "components.Settings.Notifications.NotificationsPushbullet.validationAccessTokenRequired": "Musíte zadat přístupový token",
+  "components.Settings.Notifications.NotificationsLunaSea.validationTypes": "Musíte vybrat alespoň jeden typ oznámení",
+  "components.Settings.Notifications.NotificationsPushbullet.toastPushbulletTestSending": "Odeslání testovacího oznámení Pushbullet…",
+  "components.Settings.RadarrModal.validationApplicationUrl": "Musíte zadat platnou adresu URL",
+  "components.Settings.RadarrModal.validationApplicationUrlTrailingSlash": "Adresa URL nesmí končit koncovým lomítkem",
+  "components.Settings.SettingsJobsCache.jobScheduleEditSaved": "Práce úspěšně upravena!",
+  "components.Settings.SonarrModal.baseUrl": "Základní adresa URL",
+  "components.Settings.SonarrModal.editsonarr": "Upravit server Sonarr",
+  "components.Settings.SonarrModal.enableSearch": "Povolení automatického vyhledávání",
+  "components.Settings.SonarrModal.edit4ksonarr": "Upravit 4K Sonarr Server",
+  "components.Settings.SonarrModal.testFirstLanguageProfiles": "Testovací připojení pro načtení jazykových profilů",
+  "components.Settings.SonarrModal.testFirstRootFolders": "Test připojení pro načtení kořenových složek",
+  "components.Settings.SonarrModal.validationApiKeyRequired": "Musíte zadat klíč API",
+  "components.Settings.SonarrModal.validationApplicationUrl": "Musíte zadat platnou adresu URL",
+  "components.Settings.csrfProtectionTip": "Nastavení externího přístupu k rozhraní API pouze pro čtení (vyžaduje protokol HTTPS)",
+  "components.Settings.deleteserverconfirm": "Opravdu chcete tento server odstranit?",
+  "components.Settings.menuJobs": "Práce a mezipaměť",
+  "components.Settings.toastApiKeyFailure": "Při generování nového klíče API se něco pokazilo.",
+  "components.Settings.toastApiKeySuccess": "Nový klíč API byl úspěšně vygenerován!",
+  "components.TvDetails.similar": "Podobné série",
+  "components.TvDetails.streamingproviders": "V současné době streamuje na",
+  "components.UserList.nouserstoimport": "Neexistují žádní uživatelé systému Plex, které by bylo možné importovat.",
+  "components.UserProfile.UserSettings.UserGeneralSettings.toastSettingsSuccess": "Nastavení úspěšně uloženo!",
+  "components.Settings.SettingsJobsCache.nextexecution": "Další spuštení",
+  "components.Settings.generalsettingsDescription": "Konfigurace globálních a výchozích nastavení pro Overseerr.",
+  "components.TvDetails.nextAirDate": "Další datum vysílání",
+  "components.TvDetails.viewfullcrew": "Zobrazit celé obsazení",
+  "components.UserList.displayName": "Zobrazené jméno",
+  "components.UserList.edituser": "Úprava oprávnění uživatele",
+  "components.NotificationTypeSelector.issuecreatedDescription": "Odesílat upozornění, když jsou nahlášeny problémy.",
+  "components.NotificationTypeSelector.issuereopenedDescription": "Odesílat upozornění, když se problémy znovu otevřou.",
+  "components.RequestModal.pending4krequest": "Čeká na vyřízení žádosti 4K",
+  "components.Settings.Notifications.NotificationsWebPush.webpushsettingsfailed": "Nastavení webových push oznámení se nepodařilo uložit.",
+  "components.Settings.Notifications.NotificationsWebhook.toastWebhookTestSending": "Odeslání testovacího oznámení webhooku…",
+  "components.Settings.Notifications.toastEmailTestSending": "Odeslání e-mailového oznámení o testu…",
+  "components.Settings.Notifications.validationChatIdRequired": "Musíte předložit platné chatovací ID",
+  "components.Settings.RadarrModal.hostname": "Název hostitele nebo IP adresa",
+  "components.Settings.RadarrModal.loadingprofiles": "Načítání profilů kvality…",
+  "components.Settings.RadarrModal.selectRootFolder": "Vyberte kořenovou složku",
+  "components.Settings.SettingsAbout.runningDevelop": "Používáte větev Overseerr <code>develop</code>, která je doporučena pouze těm, kteří se podílejí na vývoji nebo pomáhají s testováním.",
+  "components.Settings.webpush": "Web Push",
+  "components.RequestList.RequestItem.failedretry": "Při opakovaném pokusu o zadání požadavku se něco pokazilo.",
+  "components.Settings.RadarrModal.enableSearch": "Povolení automatického vyhledávání",
+  "components.RequestModal.requestCancel": "Žádost o <strong>{title}</strong> zrušena.",
+  "components.Settings.Notifications.NotificationsPushover.userTokenTip": "Váš 30znakový <UsersGroupsLink>identifikátor uživatele nebo skupiny</UsersGroupsLink>",
+  "components.ManageSlideOver.pastdays": "Posledních {days, number} dní",
+  "components.ManageSlideOver.playedby": "Hraje",
+  "components.NotificationTypeSelector.adminissueresolvedDescription": "Získejte upozornění, když problémy vyřeší ostatní uživatelé.",
+  "components.NotificationTypeSelector.issuecomment": "Komentář k problému",
+  "components.NotificationTypeSelector.issuecommentDescription": "Odesílat upozornění, když problémy obdrží nové komentáře.",
+  "components.NotificationTypeSelector.userissuecommentDescription": "Získejte upozornění na nové komentáře k problémům, které jste nahlásili.",
+  "components.NotificationTypeSelector.userissuereopenedDescription": "Dostávejte upozornění, když jsou vámi nahlášené problémy znovu otevřeny.",
+  "components.NotificationTypeSelector.userissueresolvedDescription": "Dostávejte oznámení o vyřešení problémů, které jste nahlásili.",
+  "components.NotificationTypeSelector.usermediafailedDescription": "Získejte upozornění, když se nepodaří přidat požadavky na média do Radarru nebo Sonarru.",
+  "components.NotificationTypeSelector.usermediarequestedDescription": "Získejte upozornění, když ostatní uživatelé zadají nové požadavky na média, které vyžadují schválení.",
+  "components.PermissionEdit.adminDescription": "Plný přístup správce. Obchází všechny ostatní kontroly oprávnění.",
+  "components.PermissionEdit.autoapprove4kMoviesDescription": "Automatické schvalování žádostí o filmy 4K.",
+  "components.PermissionEdit.autoapprove4kSeriesDescription": "Udělit automatické schválení žádostí o sérii 4K.",
+  "components.PermissionEdit.autoapproveSeriesDescription": "Udělit automatické schválení pro žádosti jiné než řady 4K.",
+  "components.PermissionEdit.createissuesDescription": "Udělit povolení k podávání zpráv o mediálních problémech.",
+  "components.PermissionEdit.manageissuesDescription": "Udělit povolení ke správě mediálních záležitostí.",
+  "components.PermissionEdit.managerequestsDescription": "Udělit povolení ke správě žádostí médií. Všechny žádosti podané uživatelem s tímto oprávněním budou automaticky schváleny.",
+  "components.PermissionEdit.request4kDescription": "Udělování povolení k předkládání žádostí o média 4K.",
+  "components.PermissionEdit.request4kMoviesDescription": "Udělit povolení k podávání žádostí o filmy 4K.",
+  "components.PermissionEdit.request4kTv": "Vyžádat si sérii 4K",
+  "components.PermissionEdit.requestMoviesDescription": "Udělit povolení k předkládání žádostí o filmy jiné než 4K.",
+  "components.PermissionEdit.requestTvDescription": "Udělit povolení k předkládání žádostí pro jiné série než 4K.",
+  "components.PermissionEdit.viewissuesDescription": "Udělit oprávnění k zobrazení problémů s médii nahlášených jinými uživateli.",
+  "components.PermissionEdit.viewrequestsDescription": "Udělit oprávnění k zobrazení požadavků na média zadaných jinými uživateli.",
+  "components.PersonDetails.alsoknownas": "Známý také jako: {names}",
+  "components.QuotaSelector.movieRequests": "{quotaLimit} <quotaUnits>{movies} na {quotaDays} {days}</quotaUnits>",
+  "components.RequestModal.QuotaDisplay.notenoughseasonrequests": "Zbývá málo žádostí na sezónu",
+  "components.ResetPassword.gobacklogin": "Zpět na stránku pro přihlášení",
+  "components.ResetPassword.resetpassword": "Obnovení hesla",
+  "components.ResetPassword.validationemailrequired": "Musíte zadat platnou e-mailovou adresu",
+  "components.ResetPassword.validationpasswordminchars": "Heslo je příliš krátké; mělo by mít minimálně 8 znaků",
+  "components.ResetPassword.validationpasswordrequired": "Musíte zadat heslo",
+  "components.Settings.Notifications.NotificationsGotify.url": "Adresa URL serveru",
+  "components.Settings.Notifications.NotificationsGotify.validationTokenRequired": "Musíte zadat token aplikace",
+  "components.Settings.Notifications.botAPI": "Autorizační token Bota",
+  "components.Settings.RadarrModal.validationHostnameRequired": "Musíte zadat platný název hostitele nebo IP adresu",
+  "components.Settings.Notifications.NotificationsSlack.validationTypes": "Musíte vybrat alespoň jeden typ oznámení",
+  "components.Settings.Notifications.enableMentions": "Povolit zmínky",
+  "components.Settings.Notifications.validationSmtpPortRequired": "Musíte zadat platné číslo portu",
+  "components.Settings.SettingsLogs.copyToClipboard": "Kopírování do schránky",
+  "components.Settings.SonarrModal.testFirstTags": "Testovací připojení k načítání značek",
+  "components.Settings.SonarrModal.toastSonarrTestFailure": "Nepodařilo se připojit k systému Sonarr.",
+  "components.Settings.SonarrModal.toastSonarrTestSuccess": "Připojení Sonarr úspěšně navázáno!",
+  "components.Settings.SonarrModal.validationBaseUrlLeadingSlash": "Základní adresa URL musí mít na začátku lomítko",
+  "components.Settings.cacheImages": "Povolení ukládání obrázků do mezipaměti",
+  "components.Settings.cacheImagesTip": "Ukládat do mezipaměti a poskytovat optimalizované obrazy (vyžaduje značné množství místa na disku)",
+  "components.Settings.manualscanDescription": "Obvykle se provádí pouze jednou za 24 hodin. Overseerr bude kontrolovat nedávno přidané položky vašeho serveru Plex agresivněji. Pokud Plex konfigurujete poprvé, doporučujeme provést jednorázovou úplnou ruční kontrolu knihovny!",
+  "components.Settings.originallanguageTip": "Filtrování obsahu podle původního jazyka",
+  "components.Settings.urlBase": "Základní adresa URL",
+  "components.Settings.tautulliSettingsDescription": "Volitelně nakonfigurujte nastavení serveru Tautulli. Overseerr načte data historie sledování pro vaše média Plex z Tautulli.",
+  "components.Settings.toastPlexConnecting": "Pokus o připojení k systému Plex…",
+  "components.Settings.validationApiKey": "Musíte zadat klíč API",
+  "components.Settings.validationApplicationUrlTrailingSlash": "Adresa URL nesmí končit koncovým lomítkem",
+  "components.Settings.validationHostnameRequired": "Musíte zadat platný název hostitele nebo IP adresu",
+  "components.Settings.validationPortRequired": "Musíte zadat platné číslo portu",
+  "components.Settings.validationUrl": "Musíte zadat platnou adresu URL",
+  "components.Settings.validationUrlBaseLeadingSlash": "Základ URL musí mít na začátku lomítko",
+  "components.TvDetails.showtype": "Typ série",
+  "components.UserList.importfromplex": "Import uživatelů systému Plex",
+  "components.UserProfile.UserSettings.UserNotificationSettings.discordsettingssaved": "Nastavení oznámení Discordu úspěšně uloženo!",
+  "components.RequestButton.requestmore4k": "Vyžádat si více informací v rozlišení 4K",
+  "components.RequestModal.QuotaDisplay.quotaLink": "Souhrn limitů vašich požadavků si můžete prohlédnout na stránce vašeho <ProfileLink>profilu</ProfileLink>.",
+  "components.RequestModal.QuotaDisplay.requiredquota": "Abyste mohli podat žádost o tuto sérii, musíte mít alespoň <strong>{seasons}</strong> {seasons, plural, one {season request} other {season requests}} zbývajících pro podání žádosti o tuto sérii.",
+  "components.RequestModal.requestfrom": "Žádost od {username} čeká na schválení.",
+  "components.RequestModal.requesterror": "Při odesílání žádosti se něco pokazilo.",
+  "components.Settings.Notifications.NotificationsLunaSea.webhookUrlTip": "Vaše adresa URL <LunaSeaLink>notification webhook</LunaSeaLink> pro uživatele nebo zařízení",
+  "components.Settings.Notifications.toastEmailTestSuccess": "E-mailové oznámení o testu odesláno!",
+  "components.Settings.RadarrModal.baseUrl": "Základní adresa URL",
+  "components.Settings.RadarrModal.default4kserver": "Výchozí server 4K",
+  "components.Settings.RadarrModal.edit4kradarr": "Upravit 4K Radarr Server",
+  "components.Settings.SettingsAbout.uptodate": "Aktuální",
+  "components.Settings.SonarrModal.validationProfileRequired": "Je třeba vybrat profil kvality",
+  "components.Settings.currentlibrary": "Současná knihovna: {name}",
+  "components.IssueDetails.closeissueandcomment": "Zavřete komentářem",
+  "components.UserProfile.UserSettings.UserNotificationSettings.telegramsettingsfailed": "Nastavení oznámení Telegramu se nepodařilo uložit.",
+  "components.UserProfile.UserSettings.UserNotificationSettings.validationPgpPublicKey": "Musíte zadat platné ID uživatele",
+  "components.RequestModal.pendingapproval": "Vaše žádost čeká na schválení.",
+  "components.Settings.Notifications.NotificationsPushover.accessToken": "Token API aplikace",
+  "components.Settings.Notifications.NotificationsWebhook.webhooksettingsfailed": "Nastavení oznámení webhooku se nepodařilo uložit.",
+  "components.Settings.Notifications.NotificationsWebhook.webhooksettingssaved": "Nastavení oznámení Webhook bylo úspěšně uloženo!",
+  "components.Settings.Notifications.botAvatarUrl": "Adresa URL avatara bota",
+  "components.Settings.Notifications.discordsettingssaved": "Nastavení oznámení Discordu úspěšně uloženo!",
+  "components.Settings.Notifications.webhookUrlTip": "Vytvoření <DiscordWebhookLink>webhook integrace</DiscordWebhookLink> na serveru",
+  "components.UserProfile.UserSettings.UserPasswordChange.nopermissionDescription": "Nemáte oprávnění měnit heslo tohoto uživatele.",
+  "components.Settings.Notifications.encryptionOpportunisticTls": "Vždy používejte protokol STARTTLS",
+  "components.Settings.RadarrModal.toastRadarrTestSuccess": "Spojení Radarr úspěšně navázáno!",
+  "components.Settings.SettingsJobsCache.cacheksize": "Velikost klíče",
+  "components.Settings.SettingsUsers.newPlexLoginTip": "Povolení přihlášení uživatelů systému Plex bez předchozího importu",
+  "components.Settings.SonarrModal.validationPortRequired": "Musíte zadat platné číslo portu",
+  "components.UserList.userfail": "Při ukládání uživatelských oprávnění se něco pokazilo.",
+  "components.UserProfile.UserSettings.UserNotificationSettings.sendSilentlyDescription": "Odesílání oznámení bez zvuku",
+  "components.RequestBlock.languageprofile": "Jazykový profil",
+  "components.RequestModal.QuotaDisplay.quotaLinkUser": "Souhrn limitů požadavků tohoto uživatele můžete zobrazit na jeho <ProfileLink>profilové stránce</ProfileLink>.",
+  "components.Settings.Notifications.NotificationsGotify.token": "Token aplikace",
+  "components.Settings.Notifications.NotificationsLunaSea.toastLunaSeaTestFailed": "Testovací oznámení LunaSea se nepodařilo odeslat.",
+  "components.Settings.Notifications.NotificationsLunaSea.validationWebhookUrl": "Musíte zadat platnou adresu URL",
+  "components.Settings.Notifications.NotificationsPushbullet.channelTag": "Označení kanálu",
+  "components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsFailed": "Nastavení oznámení Pushbullet se nepodařilo uložit.",
+  "components.Settings.Notifications.NotificationsPushbullet.validationTypes": "Musíte vybrat alespoň jeden typ oznámení",
+  "components.Settings.Notifications.NotificationsPushover.pushoversettingssaved": "Nastavení oznámení Pushover úspěšně uloženo!",
+  "components.Settings.Notifications.NotificationsSlack.toastSlackTestSending": "Odeslání oznámení o testu ve službě Slack…",
+  "components.Settings.Notifications.NotificationsSlack.toastSlackTestSuccess": "Oznámení o testu na Slacku odesláno!",
+  "components.Settings.Notifications.NotificationsWebPush.webpushsettingssaved": "Nastavení webových oznámení push bylo úspěšně uloženo!",
+  "components.Settings.Notifications.NotificationsWebhook.templatevariablehelp": "Nápověda k proměnné šablony",
+  "components.Settings.Notifications.NotificationsWebhook.toastWebhookTestSuccess": "Testovací oznámení Webhook odesláno!",
+  "components.Settings.Notifications.NotificationsWebhook.validationJsonPayloadRequired": "Musíte zadat platné užitečné zatížení JSON",
+  "components.Settings.Notifications.allowselfsigned": "Povolení certifikátů s vlastním podpisem",
+  "components.Settings.Notifications.discordsettingsfailed": "Nastavení oznámení Discordu se nepodařilo uložit.",
+  "components.Settings.Notifications.encryptionImplicitTls": "Použití implicitního protokolu TLS",
+  "components.Settings.Notifications.toastDiscordTestSending": "Odeslání oznámení o testu Discord…",
+  "components.Settings.Notifications.toastDiscordTestSuccess": "Oznámení o testu Discordu odesláno!",
+  "components.Settings.Notifications.toastEmailTestFailed": "E-mailové testovací oznámení se nepodařilo odeslat.",
+  "components.Settings.Notifications.validationBotAPIRequired": "Musíte zadat autorizační token bota",
+  "components.Settings.Notifications.validationTypes": "Musíte vybrat alespoň jeden typ oznámení",
+  "components.Settings.RadarrModal.announced": "Oznámeno",
+  "components.Settings.RadarrModal.create4kradarr": "Přidání nového serveru 4K Radarr",
+  "components.Settings.RadarrModal.selectQualityProfile": "Vyberte profil kvality",
+  "components.Settings.RadarrModal.testFirstRootFolders": "Test připojení pro načtení kořenových složek",
+  "components.Settings.RadarrModal.validationBaseUrlTrailingSlash": "Základ URL nesmí končit koncovým lomítkem",
+  "components.Settings.RadarrModal.validationNameRequired": "Je třeba zadat název serveru",
+  "components.Settings.SettingsAbout.appDataPath": "Adresář dat",
+  "components.Settings.SettingsAbout.helppaycoffee": "Pomozte zaplatit kávu",
+  "components.Settings.SettingsAbout.outofdate": "Zastaralé",
+  "components.Settings.SettingsJobsCache.cachekeys": "Klíče celkem",
+  "components.Settings.SettingsJobsCache.download-sync": "Synchronizovat stažení",
+  "components.Settings.SettingsJobsCache.jobsandcache": "Práce a mezipaměť",
+  "components.Settings.SettingsJobsCache.plex-full-scan": "Kompletní skenování knihovny Plex",
+  "components.Settings.SettingsLogs.copiedLogMessage": "Zkopírování zprávy protokolu do schránky.",
+  "components.Settings.SettingsUsers.defaultPermissionsTip": "Počáteční oprávnění přidělená novým uživatelům",
+  "components.Settings.SettingsUsers.tvRequestLimitLabel": "Globální limit požadavků na sérii",
+  "components.Settings.SettingsUsers.userSettingsDescription": "Konfigurace globálních a výchozích uživatelských nastavení.",
+  "components.Settings.SonarrModal.animequalityprofile": "Profil kvality anime",
+  "components.Settings.SonarrModal.create4ksonarr": "Přidání nového serveru 4K Sonarr",
+  "components.Settings.SonarrModal.hostname": "Název hostitele nebo IP adresa",
+  "components.Settings.SonarrModal.loadinglanguageprofiles": "Načítání jazykových profilů…",
+  "components.Settings.SonarrModal.validationApplicationUrlTrailingSlash": "Adresa URL nesmí končit koncovým lomítkem",
+  "components.Settings.addradarr": "Přidání serveru Radarr",
+  "components.Settings.addsonarr": "Adding a Radarr server",
+  "components.Settings.copied": "Zkopírování klíče API do schránky.",
+  "components.Settings.csrfProtection": "Povolení ochrany CSRF",
+  "components.Settings.externalUrl": "Externí adresa URL",
+  "components.Settings.hideAvailable": "Skrýt dostupná média",
+  "components.Settings.hostname": "Název hostitele nebo IP adresa",
+  "components.Settings.manualscan": "Manuální skenování knihovny",
+  "components.Settings.partialRequestsEnabled": "Povolení požadavků na částečné série",
+  "components.Settings.plexlibrariesDescription": "Knihovny Overseerr vyhledává tituly. Nastavte a uložte nastavení připojení k systému Plex a poté klikněte na tlačítko níže, pokud nejsou v seznamu uvedeny žádné knihovny.",
+  "components.Settings.serverpresetLoad": "Stisknutím tlačítka načtete dostupné servery",
+  "components.Settings.toastSettingsSuccess": "Nastavení úspěšně uloženo!",
+  "components.Settings.toastTautulliSettingsFailure": "Při ukládání nastavení Tautulli se něco pokazilo.",
+  "components.Settings.validationApplicationTitle": "Musíte uvést název žádosti",
+  "components.Settings.validationApplicationUrl": "Musíte zadat platnou adresu URL",
+  "components.Settings.webAppUrl": "<WebAppLink>Webová aplikace</WebAppLink> Adresa URL",
+  "components.Settings.validationUrlTrailingSlash": "Adresa URL nesmí končit koncovým lomítkem",
+  "components.Settings.webAppUrlTip": "Volitelné přesměrování uživatelů na webovou aplikaci na vašem serveru namísto hostované webové aplikace",
+  "components.Setup.loginwithplex": "Přihlášení pomocí služby Plex",
+  "components.Setup.scanbackground": "Skenování bude probíhat na pozadí. Mezitím můžete pokračovat v procesu nastavení.",
+  "components.Setup.welcome": "Vítejte v Overseerr",
+  "components.Setup.signinMessage": "Skenování bude probíhat na pozadí. Mezitím můžete pokračovat v procesu nastavení",
+  "components.TvDetails.TvCrew.fullseriescrew": "Posádka celé série",
+  "components.UserList.autogeneratepassword": "Automatické generování hesla",
+  "components.UserList.autogeneratepasswordTip": "Zaslání hesla vygenerovaného serverem uživateli e-mailem",
+  "components.UserList.deleteconfirm": "Opravdu chcete tohoto uživatele odstranit? Všechny údaje o jeho žádosti budou trvale odstraněny.",
+  "components.UserList.localLoginDisabled": "Nastavení <strong>Povolit místní přihlášení</strong> je v současné době zakázáno.",
+  "components.UserList.userssaved": "Uživatelská oprávnění byla úspěšně uložena!",
+  "components.UserList.validationEmail": "Musíte zadat platnou e-mailovou adresu",
+  "components.UserProfile.ProfileHeader.userid": "ID uživatele: {userid}",
+  "components.UserProfile.UserSettings.UserGeneralSettings.movierequestlimit": "Limit požadavků na filmy",
+  "components.UserProfile.UserSettings.UserGeneralSettings.seriesrequestlimit": "Limit požadavků na sérii",
+  "components.UserProfile.UserSettings.UserGeneralSettings.toastSettingsFailure": "Při ukládání nastavení se něco pokazilo.",
+  "components.UserProfile.UserSettings.UserNotificationSettings.emailsettingssaved": "Nastavení e-mailových oznámení bylo úspěšně uloženo!",
+  "components.UserProfile.UserSettings.UserNotificationSettings.validationTelegramChatId": "Musíte předložit platné chatovací ID",
+  "components.UserProfile.limit": "{remaining} z {limit}",
+  "components.UserProfile.recentlywatched": "Nedávno sledované",
+  "i18n.import": "Import",
+  "components.PermissionEdit.autoapproveDescription": "Udělit automatické schválení všem žádostem o média jiná než 4K.",
+  "components.PermissionEdit.autoapprove4kDescription": "Udělit automatické schválení všem žádostem o média 4K.",
+  "components.PermissionEdit.request4kTvDescription": "Udělit povolení k předkládání žádostí o seriály 4K.",
+  "components.Settings.Notifications.NotificationsPushbullet.toastPushbulletTestFailed": "Testovací oznámení Pushbullet se nepodařilo odeslat.",
+  "components.Settings.Notifications.NotificationsPushover.pushoversettingsfailed": "Nastavení oznámení Pushover se nepodařilo uložit.",
+  "components.Settings.Notifications.NotificationsSlack.toastSlackTestFailed": "Testovací oznámení služby Slack se nepodařilo odeslat.",
+  "components.Settings.Notifications.botApiTip": "<CreateBotLink>Vytvoření bota</CreateBotLink> pro použití s Overseerr",
+  "components.Settings.Notifications.pgpPrivateKeyTip": "Podepisování šifrovaných e-mailových zpráv pomocí <OpenPgpLink>OpenPGP</OpenPgpLink>",
+  "components.Settings.Notifications.sendSilentlyTip": "Odesílání oznámení bez zvuku",
+  "components.Settings.Notifications.telegramsettingssaved": "Nastavení oznámení Telegramu úspěšně uloženo!",
+  "components.Settings.RadarrModal.validationPortRequired": "Musíte zadat platné číslo portu",
+  "components.Settings.SettingsLogs.showall": "Zobrazit všechny protokoly",
+  "components.Settings.SettingsUsers.newPlexLogin": "Povolení nového přihlášení k systému Plex",
+  "components.Settings.SonarrModal.animerootfolder": "Kořenová složka Anime",
+  "components.Settings.SonarrModal.loadingrootfolders": "Načítání kořenových složek…",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoverApplicationToken": "Token API aplikace",
+  "components.Settings.RadarrModal.editradarr": "Upravit server Radarr",
+  "components.Settings.RadarrModal.createradarr": "Přidání nového serveru Radarr",
+  "components.Settings.RadarrModal.inCinemas": "V kinech",
+  "components.Settings.RadarrModal.released": "Vydáno",
+  "components.Settings.RadarrModal.selectMinimumAvailability": "Vyberte minimální dostupnost",
+  "components.Settings.SettingsAbout.Releases.viewongithub": "Zobrazit na GitHubu",
+  "components.Settings.librariesRemaining": "Zbývající knihovny: {count}",
+  "components.Settings.noDefault4kServer": "Server 4K {serverType} musí být označen jako výchozí, aby uživatelé mohli odesílat požadavky 4K {mediaType}.",
+  "components.Settings.noDefaultNon4kServer": "Pokud máte pouze jeden server {serverType} pro obsah jiný než 4K i 4K (nebo pokud stahujete pouze obsah 4K), váš server {serverType} by <strong>neměl</strong> být označen jako server 4K.",
+  "components.Settings.noDefaultServer": "Aby mohly být zpracovány požadavky typu {mediaType}, musí být alespoň jeden server typu {serverType} označen jako výchozí.",
+  "components.Settings.regionTip": "Filtrování obsahu podle regionální dostupnosti",
+  "components.Settings.plexsettingsDescription": "Knihovny Overseerr vyhledává tituly. Nastavte a uložte nastavení připojení k systému Plex a poté klikněte na tlačítko níže, pokud nejsou v seznamu uvedeny žádné knihovny.",
+  "components.Settings.toastSettingsFailure": "Při ukládání nastavení se něco pokazilo.",
+  "components.Settings.trustProxy": "Povolení podpory proxy serveru",
+  "components.Settings.toastPlexRefresh": "Získání seznamu serverů z aplikace Plex…",
+  "components.Settings.toastPlexRefreshSuccess": "Seznam serverů Plex úspěšně načten!",
+  "components.UserList.passwordinfodescription": "Nakonfigurujte adresu URL aplikace a povolte e-mailová oznámení, která umožní automatické generování hesla.",
+  "components.UserList.sortCreated": "Datum připojení",
+  "components.UserList.sortDisplayName": "Zobrazované jméno",
+  "components.UserList.usercreatedfailed": "Při vytváření uživatele se něco pokazilo.",
+  "components.UserList.usercreatedfailedexisting": "Zadaná e-mailová adresa je již používána jiným uživatelem.",
+  "components.UserList.userdeleteerror": "Při odstraňování uživatele se něco pokazilo.",
+  "components.RequestModal.requestApproved": "Žádost o <strong>{title}</strong> schválena!",
+  "components.Settings.Notifications.NotificationsPushbullet.pushbulletSettingsSaved": "Nastavení oznámení Pushbullet úspěšně uloženo!",
+  "components.RequestModal.approve": "Schválit žádost",
+  "components.RequestModal.errorediting": "Při úpravě požadavku se něco pokazilo.",
+  "components.Settings.Notifications.NotificationsPushover.validationTypes": "Musíte vybrat alespoň jeden typ oznámení",
+  "components.Settings.Notifications.NotificationsSlack.webhookUrlTip": "Vytvoření integrace <WebhookLink>Příchozí webový háček</WebhookLink>",
+  "components.RequestModal.requestedited": "Požadavek na <strong>{title}</strong> úspěšně upraven!",
+  "components.NotificationTypeSelector.issueresolvedDescription": "Odesílat upozornění, když jsou problémy vyřešeny.",
+  "components.Settings.Notifications.NotificationsPushover.validationUserTokenRequired": "Musíte zadat platný klíč uživatele nebo skupiny",
+  "components.Settings.Notifications.NotificationsWebPush.toastWebPushTestSuccess": "Web push testovací oznámení odesláno!",
+  "components.PermissionEdit.autoapproveMoviesDescription": "Automatické schvalování žádostí o filmy jiné než 4K.",
+  "components.PermissionEdit.requestDescription": "Udělit povolení k předkládání žádostí o média jiná než 4K.",
+  "components.RequestModal.AdvancedRequester.animenote": "* Tento seriál je anime.",
+  "components.Settings.Notifications.NotificationsPushover.userToken": "Klíč uživatele nebo skupiny",
+  "components.RequestCard.failedretry": "Při opakovaném pokusu o zadání požadavku se něco pokazilo.",
+  "components.Settings.Notifications.NotificationsLunaSea.profileNameTip": "Vyžaduje se pouze v případě, že nepoužíváte profil <code>default</code>",
+  "components.RequestCard.mediaerror": "{mediaType} Nenalezeno",
+  "components.Settings.trustProxyTip": "Povolit Overseerr správně registrovat IP adresy klientů za proxy serverem",
+  "components.RequestList.RequestItem.mediaerror": "{mediaType} Nenalezeno",
+  "components.RequestModal.QuotaDisplay.allowedRequests": "Můžete požádat o <strong>{limit}</strong> {type} každé <strong>{days}</strong> dny.",
+  "components.RequestModal.SearchByNameModal.notvdbiddescription": "Tuto sérii jsme nemohli automaticky spárovat. Níže prosím vyberte správnou shodu.",
+  "components.Settings.RadarrModal.validationBaseUrlLeadingSlash": "Základ URL musí mít na začátku lomítko",
+  "components.Settings.SettingsJobsCache.plex-recently-added-scan": "Plex Nedávno přidané skenování",
+  "components.Settings.SettingsLogs.logsDescription": "Tyto protokoly můžete také zobrazit přímo prostřednictvím <code>stdout</code> nebo v <code>{appDataPath}/logs/overseerr.log</code>.",
+  "components.UserProfile.UserSettings.UserNotificationSettings.emailsettingsfailed": "Nastavení e-mailových oznámení se nepodařilo uložit.",
+  "components.Settings.SonarrModal.loadingprofiles": "Načítání kvalitních profilů…",
+  "components.Settings.SonarrModal.selectRootFolder": "Vyberte kořenovou složku",
+  "components.ResetPassword.requestresetlinksuccessmessage": "Na zadanou e-mailovou adresu bude zaslán odkaz pro obnovení hesla, pokud je spojena s platným uživatelem.",
+  "components.RequestModal.pendingrequest": "Čekající žádost",
+  "components.Settings.Notifications.NotificationsLunaSea.settingsSaved": "Nastavení oznámení LunaSea úspěšně uloženo!",
+  "components.Settings.SonarrModal.default4kserver": "Výchozí server 4K",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoverUserKeyTip": "Váš 30znakový <UsersGroupsLink>identifikátor uživatele nebo skupiny</UsersGroupsLink>",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoversettingssaved": "Nastavení oznámení Pushover úspěšně uloženo!",
+  "components.RequestModal.requestcancelled": "Žádost o <strong>{title}</strong> zrušena.",
+  "components.Settings.SettingsUsers.toastSettingsFailure": "Při ukládání nastavení se něco pokazilo.",
+  "components.Settings.Notifications.NotificationsWebhook.toastWebhookTestFailed": "Testovací oznámení webhooku se nepodařilo odeslat.",
+  "components.Settings.Notifications.botUsernameTip": "Umožněte uživatelům také zahájit chat s vaším botem a nakonfigurovat si vlastní oznámení",
+  "components.Settings.Notifications.emailsettingssaved": "Nastavení e-mailových oznámení bylo úspěšně uloženo!",
+  "components.Settings.Notifications.NotificationsPushover.toastPushoverTestSuccess": "Oznámení o testu Pushover odesláno!",
+  "components.Settings.Notifications.NotificationsSlack.slacksettingsfailed": "Nastavení oznámení služby Slack se nepodařilo uložit.",
+  "components.Settings.toastPlexConnectingSuccess": "Připojení k systému Plex úspěšně navázáno!",
+  "components.Settings.Notifications.NotificationsLunaSea.toastLunaSeaTestSending": "Odeslání oznámení o testu LunaSea…",
+  "components.Settings.Notifications.NotificationsPushbullet.accessTokenTip": "Vytvořte token ze svého <PushbulletSettingsLink>Nastavení účtu</PushbulletSettingsLink>",
+  "components.Settings.Notifications.encryptionTip": "Ve většině případů používá implicitní TLS port 465 a STARTTLS port 587",
+  "components.Settings.Notifications.toastDiscordTestFailed": "Oznámení o testu Discord se nepodařilo odeslat.",
+  "components.Settings.SettingsUsers.movieRequestLimitLabel": "Globální limit požadavků na filmy",
+  "components.Settings.validationUrlBaseTrailingSlash": "Základ URL nesmí končit koncovým lomítkem",
+  "components.TvDetails.firstAirDate": "Datum prvního vysílání",
+  "components.Settings.RadarrModal.validationApiKeyRequired": "Musíte zadat klíč API",
+  "components.Settings.toastPlexConnectingFailure": "Nepodařilo se připojit k systému Plex.",
+  "components.Settings.Notifications.NotificationsLunaSea.settingsFailed": "Nastavení oznámení LunaSea se nepodařilo uložit.",
+  "components.Settings.Notifications.NotificationsPushover.accessTokenTip": "<ApplicationRegistrationLink>Registrace aplikace</ApplicationRegistrationLink> pro použití s aplikací Overseerr",
+  "components.Settings.Notifications.NotificationsPushover.validationAccessTokenRequired": "Musíte zadat platný token aplikace",
+  "components.Settings.Notifications.NotificationsPushover.toastPushoverTestFailed": "Testovací oznámení Pushover se nepodařilo odeslat.",
+  "components.Settings.SonarrModal.animelanguageprofile": "Profil jazyka Anime",
+  "components.Settings.Notifications.NotificationsWebhook.resetPayloadSuccess": "JSON payload úspěšně resetován!",
+  "components.Settings.SonarrModal.selectQualityProfile": "Vyberte profil kvality",
+  "components.Settings.tautulliApiKey": "Klíč API",
+  "components.Settings.Notifications.NotificationsWebPush.httpsRequirement": "Aby bylo možné přijímat webová oznámení push, musí být služba Overseerr obsluhována prostřednictvím protokolu HTTPS.",
+  "components.Settings.RadarrModal.validationMinimumAvailabilityRequired": "Musíte zvolit minimální dostupnost",
+  "components.Settings.SonarrModal.validationBaseUrlTrailingSlash": "Základní adresa URL nesmí končit koncovým lomítkem",
+  "components.Settings.SonarrModal.validationRootFolderRequired": "Je třeba vybrat kořenovou složku",
+  "components.UserList.createlocaluser": "Vytvořit místního uživatele",
+  "components.Settings.Notifications.NotificationsWebPush.toastWebPushTestSending": "Odesílání webového testovacího oznámení push…",
+  "components.Settings.Notifications.chatIdTip": "Spusťte chat s botem, přidejte <GetIdBotLink>@get_id_bot</GetIdBotLink> a zadejte příkaz <code>/my_id</code>",
+  "components.Settings.Notifications.emailsettingsfailed": "Nastavení e-mailových oznámení se nepodařilo uložit.",
+  "components.Settings.Notifications.NotificationsWebhook.validationTypes": "Musíte vybrat alespoň jeden typ oznámení",
+  "components.Settings.SettingsAbout.betawarning": "Jedná se o software BETA. Funkce mohou být nefunkční a/nebo nestabilní. Jakékoli problémy prosím nahlaste na GitHubu!",
+  "components.Settings.SonarrModal.createsonarr": "Přidání nového serveru Sonarr",
+  "components.Settings.Notifications.pgpPasswordTip": "Podepisování šifrovaných e-mailových zpráv pomocí <OpenPgpLink>OpenPGP</OpenPgpLink>",
+  "components.Settings.SonarrModal.selectLanguageProfile": "Výběr jazykového profilu",
+  "components.Settings.Notifications.telegramsettingsfailed": "Nastavení oznámení Telegramu se nepodařilo uložit.",
+  "components.Settings.RadarrModal.toastRadarrTestFailure": "Nepodařilo se připojit k Radarru.",
+  "components.Settings.SettingsUsers.localLogin": "Povolení místního přihlášení",
+  "components.Settings.SettingsUsers.localLoginTip": "Umožnit uživatelům přihlašovat se pomocí e-mailové adresy a hesla namísto protokolu Plex OAuth",
+  "components.UserProfile.UserSettings.UserNotificationSettings.discordsettingsfailed": "Nastavení oznámení Discordu se nepodařilo uložit.",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletsettingssaved": "Nastavení oznámení Pushbullet úspěšně uloženo!",
+  "components.UserProfile.UserSettings.UserNotificationSettings.validationPushbulletAccessToken": "Musíte zadat přístupový token",
+  "components.Settings.SettingsJobsCache.cacheDescription": "Overseerr ukládá do mezipaměti požadavky na externí koncové body API, aby optimalizoval výkon a zamezil zbytečným voláním API.",
+  "components.Settings.SonarrModal.validationHostnameRequired": "Musíte zadat platný název hostitele nebo IP adresu",
+  "components.Settings.Notifications.toastTelegramTestFailed": "Testovací oznámení Telegramu se nepodařilo odeslat.",
+  "components.Settings.Notifications.toastTelegramTestSending": "Odeslání testovacího oznámení Telegramu…",
+  "components.Settings.SettingsJobsCache.jobsDescription": "Overseerr provádí určité úlohy údržby jako pravidelně naplánované úlohy, ale lze je také spustit ručně níže. Ruční spuštění úlohy nezmění její plán.",
+  "components.Settings.SettingsUsers.toastSettingsSuccess": "Uživatelská nastavení byla úspěšně uložena!",
+  "components.UserProfile.UserSettings.UserNotificationSettings.validationPushoverApplicationToken": "Musíte zadat platný token aplikace",
+  "components.Settings.Notifications.toastTelegramTestSuccess": "Oznámení o testu Telegramu odesláno!",
+  "components.TvDetails.TvCast.fullseriescast": "Kompletní obsazení série",
+  "components.UserList.importfromplexerror": "Při importu uživatelů systému Plex se něco pokazilo.",
+  "components.Settings.Notifications.validationSmtpHostRequired": "Musíte zadat platný název hostitele nebo IP adresu",
+  "components.Settings.RadarrModal.validationProfileRequired": "Je třeba vybrat profil kvality",
+  "components.Settings.serviceSettingsDescription": "Níže nakonfigurujte server(y) {serverType}. Můžete připojit více serverů {serverType}, ale pouze dva z nich mohou být označeny jako výchozí (jeden ne-4K a jeden 4K). Správci mohou před schválením změnit server používaný ke zpracování nových požadavků.",
+  "components.Settings.RadarrModal.testFirstTags": "Testovací připojení k načítání značek",
+  "components.UserList.validationpasswordminchars": "Heslo je příliš krátké; mělo by mít minimálně 8 znaků",
+  "components.UserProfile.pastdays": "{type} (posledních {days} dnů)",
+  "components.Settings.SettingsJobsCache.cacheflushed": "Mezipaměť {cachename} byla vyprázdněna.",
+  "components.UserProfile.UserSettings.UserNotificationSettings.validationDiscordId": "Musíte zadat platné ID uživatele",
+  "components.Settings.SonarrModal.validationLanguageProfileRequired": "Je třeba vybrat jazykový profil",
+  "components.Settings.SonarrModal.validationNameRequired": "Je třeba zadat název serveru",
+  "components.UserProfile.UserSettings.UserGeneralSettings.displayName": "Zobrazované jméno",
+  "components.Settings.csrfProtectionHoverTip": "Toto nastavení NEPOVOLUJTE, pokud nerozumíte tomu, co děláte!",
+  "components.Settings.tautulliSettings": "Tautulli Nastavení",
+  "components.Settings.toastTautulliSettingsSuccess": "Nastavení Tautulli úspěšně uloženo!",
+  "components.UserProfile.UserSettings.unauthorizedDescription": "Nemáte oprávnění měnit nastavení tohoto uživatele.",
+  "components.UserList.newplexsigninenabled": "Nastavení <strong>Povolit nové přihlášení do systému Plex</strong> je v současné době povoleno. Uživatelé systému Plex s přístupem do knihovny nemusí být pro přihlášení importováni.",
+  "components.UserProfile.UserSettings.UserNotificationSettings.validationPushoverUserKey": "Musíte zadat platný klíč uživatele nebo skupiny",
+  "components.UserList.usercreatedsuccess": "Uživatel úspěšně vytvořen!",
+  "components.UserList.userdeleted": "Uživatel úspěšně smazán!",
+  "components.UserProfile.UserSettings.UserGeneralSettings.discordIdTip": "<FindDiscordIdLink>vícemístné identifikační číslo</FindDiscordIdLink> spojené s vaším uživatelským účtem Discord",
+  "components.UserProfile.UserSettings.UserGeneralSettings.discordId": "Uživatelské ID Discordu",
+  "components.UserProfile.UserSettings.UserGeneralSettings.enableOverride": "Přepsání globálního limitu",
+  "components.UserProfile.UserSettings.UserGeneralSettings.validationDiscordId": "Musíte zadat platné ID uživatele služby Discord",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pgpPublicKey": "Veřejný klíč PGP",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pgpPublicKeyTip": "Šifrování e-mailových zpráv pomocí <OpenPgpLink>OpenPGP</OpenPgpLink>",
+  "components.UserProfile.UserSettings.UserNotificationSettings.webpushsettingssaved": "Nastavení webových oznámení push bylo úspěšně uloženo!",
+  "components.UserProfile.UserSettings.UserNotificationSettings.discordIdTip": "<FindDiscordIdLink>vícemístné identifikační číslo</FindDiscordIdLink> spojené s vaším uživatelským účtem",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletAccessToken": "Přístupový token",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoverUserKey": "Klíč uživatele nebo skupiny",
+  "components.UserProfile.UserSettings.UserNotificationSettings.telegramChatIdTipLong": "<TelegramBotLink>Začněte chat</TelegramBotLink>, přidejte <GetIdBotLink>@get_id_bot</GetIdBotLink> a zadejte příkaz <code>/my_id</code>",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletsettingsfailed": "Nastavení oznámení Pushbullet se nepodařilo uložit.",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoversettingsfailed": "Nastavení oznámení Pushover se nepodařilo uložit.",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoverApplicationTokenTip": "<ApplicationRegistrationLink>Registrace aplikace</ApplicationRegistrationLink> pro použití s {applicationTitle}",
+  "components.UserProfile.UserSettings.UserNotificationSettings.telegramsettingssaved": "Nastavení oznámení Telegramu úspěšně uloženo!",
+  "components.UserProfile.UserSettings.UserNotificationSettings.webpushsettingsfailed": "Nastavení webových push oznámení se nepodařilo uložit.",
+  "components.UserProfile.UserSettings.UserPasswordChange.noPasswordSet": "Tento uživatelský účet v současné době nemá nastavené heslo. Níže nastavte heslo, aby se tento účet mohl přihlašovat jako \"místní uživatel.\"",
+  "components.UserProfile.UserSettings.UserPasswordChange.noPasswordSetOwnAccount": "Váš účet v současné době nemá nastavené heslo. Níže nastavte heslo, abyste se mohli přihlásit jako \"místní uživatel\" pomocí své e-mailové adresy.",
+  "i18n.importing": "Importování…",
+  "components.IssueList.IssueItem.episodes": "{episodeCount, plural, zero {Epizod} one {Epizoda} other {Epizody}}",
+  "components.IssueList.IssueItem.seasons": "{seasonCount, plural, zero {Sezón} one {Sezóna} other {Sezóny}}",
+  "components.TvDetails.productioncountries": "{countryCount, plural, one {Země} other {Země}} produkce",
+  "components.TvDetails.network": "{networkCount, plural, one {Síť} other {Sítě}}",
+  "components.RequestModal.QuotaDisplay.seasonlimit": "{limit, plural, one {sezóna} other {sezóny}}",
+  "components.ManageSlideOver.plays": "<strong>{playCount, number}</strong> {playCount, plural, one {přehrání} other {přehrání}}",
+  "components.MovieDetails.productioncountries": "Produkční {countryCount, plural, one {Země} other {Země}}",
+  "components.MovieDetails.studio": "{studioCount, plural, one {Studio} other {Studia}}",
+  "components.QuotaSelector.days": "{count, plural, zero {dní} one {den} other {dny}}",
+  "components.TvDetails.seasons": "{seasonCount, plural, one {# Sezóna} other {# Sezóny}}",
+  "components.RequestCard.seasons": "{seasonCount, plural, one {Sezóna} other {Sezóny}}",
+  "components.RequestModal.QuotaDisplay.requiredquotaUser": "Aby mohl tento uživatel odeslat žádost o seriál, musí mít zbývajících alespoň <strong>{seasons}</strong> {seasons, plural, one {požadavku pro sezónu} other {požadavky pro sezóny}}.",
+  "components.RequestModal.requestmovies4k": "Požádat {count} {count, plural, one {Movie} other {Movies}} v 4K",
+  "components.Settings.SettingsJobsCache.editJobScheduleSelectorHours": "{jobScheduleHours, plural, one {Každou hodinu} few {Každé {jobScheduleHours} hodiny} other {Každých {jobScheduleHours} hodin}}",
+  "components.RequestBlock.seasons": "{seasonCount, plural, zero {Sezón} one {Sezóna} other {Sezóny}}",
+  "components.RequestButton.approve4krequests": "Schválit {requestCount, plural, one {4K žádost} other {{requestCount} 4K žádosti}}",
+  "components.RequestList.RequestItem.seasons": "{seasonCount, plural, one {Sezóna} other {Sezóny}}",
+  "components.RequestModal.QuotaDisplay.allowedRequestsUser": "Tento uživatel může požádat o <strong>{limit}</strong> {type} každých <strong>{days}</strong> dní.",
+  "components.RequestModal.QuotaDisplay.movielimit": "{limit, plural, one {film} other {filmy}}",
+  "components.RequestModal.QuotaDisplay.requestsremaining": "{remaining, plural, =0 {Žiadne} other {<strong>#</strong>}} {type} {remaining, plural, one {požadavka} other {požadavky}} zbývající",
+  "components.RequestModal.requestseasons": "Požádat {seasonCount} {seasonCount, plural, one {sezónu} other {sezóny}}",
+  "components.RequestModal.requestseasons4k": "Požádat {seasonCount} {seasonCount, plural, one {sezónu} other {sezóny}} v 4K",
+  "components.UserList.importedfromplex": "<strong>{userCount}</strong> Plex {userCount, plural, one {uživatel úspěšně importován} other {uživatelů úspěšně importováno}}!",
+  "components.UserProfile.UserSettings.UserGeneralSettings.originallanguageTip": "Filtrovat obsah podle původního jazyka",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletAccessTokenTip": "Vytvořte token z <PushbulletSettingsLink>Nastavení účtu</PushbulletSettingsLink>",
+  "components.QuotaSelector.movies": "{count, plural, zero {filmů} one {film} other {filmy}}",
+  "components.QuotaSelector.seasons": "{seasonCount, plural, zero {sezón} one {sezóna} other {sezóny}}",
+  "components.QuotaSelector.tvRequests": "{quotaLimit} <quotaUnits>{seasons} za {quotaDays} {days}</quotaUnits>",
+  "components.RequestButton.approverequests": "Schválit {requestCount, plural, one {Žádost} other {{requestCount} Žádosti}}",
+  "components.RequestButton.decline4krequests": "Odmítnout {requestCount, plural, one {4K žádost} other {{requestCount} 4K žádosti}}",
+  "components.RequestButton.declinerequests": "Odmítnout {requestCount, plural, one {Žádost} other {{requestCount} Žádosti}}",
+  "components.RequestModal.requestmovies": "Požádat {count} {count, plural, one {film} other {filmy}}",
+  "components.Settings.SettingsJobsCache.editJobScheduleSelectorMinutes": "{jobScheduleMinutes, plural, one {Každou minutu} few {Každé {jobScheduleMinutes} minuty} other {Každých {jobScheduleMinutes} minut}}",
+  "components.MovieDetails.digitalrelease": "Digitální vydání",
+  "components.Discover.DiscoverWatchlist.discoverwatchlist": "Váš Plex Watchlist",
+  "components.MovieDetails.physicalrelease": "Fyzické vydání",
+  "components.MovieDetails.managemovie": "Spravovat film",
+  "components.AirDateBadge.airsrelative": "Vysíla se {relativeTime}",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.movierequests": "Žádosti o filmy",
+  "components.MovieDetails.rtaudiencescore": "Skóre publika Rotten Tomatoes",
+  "components.MovieDetails.rtcriticsscore": "Rotten Tomatoes Tomatometer",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.seriesrequests": "Žádosti o seriály",
+  "components.AirDateBadge.airedrelative": "Odvysílano {relativeTime}",
+  "components.Layout.UserDropdown.requests": "Žádosti",
+  "components.MovieDetails.reportissue": "Nahlásit problém",
+  "components.StatusChecker.restartRequired": "Je vyžadován restart serveru",
+  "components.PermissionEdit.viewrecent": "Zobrazit naposledy přidané",
+  "components.StatusChecker.appUpdated": "{applicationTitle} Aktualizováno",
+  "components.StatusChecker.appUpdatedDescription": "Chcete-li aplikaci znovu načíst, klikněte na tlačítko níže.",
+  "components.StatusChecker.restartRequiredDescription": "Chcete-li použít aktualizovaná nastavení, restartujte server.",
+  "components.RequestCard.tmdbid": "TMDB ID",
+  "components.RequestList.RequestItem.tmdbid": "TMDB ID",
+  "components.TitleCard.tmdbid": "TMDB ID",
+  "components.TitleCard.tvdbid": "TheTVDB ID",
+  "components.RequestCard.tvdbid": "TheTVDB ID",
+  "components.RequestList.RequestItem.tvdbid": "TheTVDB ID",
+  "components.PermissionEdit.autorequestMovies": "Automatické vyžádání filmů",
+  "components.PermissionEdit.autorequestMoviesDescription": "Udělte oprávnění k automatickému odesílání žádostí o filmy v jiném rozlišení než 4K prostřednictvím Plex Watchlistu.",
+  "components.PermissionEdit.viewrecentDescription": "Udělte oprávnění k zobrazení seznamu nedávno přidaných médií.",
+  "components.Settings.restartrequiredTooltip": "Aby se změny tohoto nastavení projevily, musí být Overserr restartován",
+  "components.StatusChecker.reloadApp": "Znovu načíst {applicationTitle}",
+  "components.TitleCard.cleardata": "Vyčistit data",
+  "components.TitleCard.mediaerror": "{mediaType} Nenalezeno",
+  "components.PermissionEdit.autorequestDescription": "Udělte oprávnění k automatickému odesílání žádostí o média jiná než 4K prostřednictvím seznamu Plex Watchlist.",
+  "components.PermissionEdit.autorequest": "Automatická žádost",
+  "components.PermissionEdit.autorequestSeries": "Automaticky vyžádat seriál",
+  "components.PermissionEdit.viewwatchlists": "Zobrazit Plex Watchilisty",
+  "components.Settings.advancedTooltip": "Nesprávná konfigurace tohoto nastavení může vést k narušení funkčnosti",
+  "components.Settings.deleteServer": "Smazat server {serverType}",
+  "components.Settings.experimentalTooltip": "Povolení tohoto nastavení může vést k neočekávanému chování aplikace",
+  "components.Settings.SettingsLogs.viewdetails": "Zobrazit podrobnosti",
+  "components.PermissionEdit.autorequestSeriesDescription": "Udělte oprávnění k automatickému odesílání žádostí o seriály jiné než 4K prostřednictvím Plex Watchlist.",
+  "components.RequestBlock.approve": "Schválit žádost",
+  "components.RequestBlock.decline": "Odmítnout požadavek",
+  "components.RequestBlock.lastmodifiedby": "Naposledy změněno od",
+  "components.RequestBlock.requestdate": "Datum požadavku",
+  "components.RequestBlock.requestedby": "Vyžádáno od",
+  "components.RequestCard.approverequest": "Schválit žádost",
+  "components.RequestCard.cancelrequest": "Zrušit žádost",
+  "components.RequestCard.declinerequest": "Odmítnout požadavek",
+  "components.Settings.SettingsJobsCache.plex-watchlist-sync": "Plex Watchlist synchronizace",
+  "components.StatusBadge.managemedia": "Spravovat {mediaType}",
+  "components.StatusBadge.openinarr": "Otevřít v {arr}",
+  "components.StatusBadge.playonplex": "Přehrávání cez Plex",
+  "components.TvDetails.manageseries": "Spravovat sérii",
+  "components.RequestBlock.delete": "Smazat požadavek",
+  "components.RequestBlock.edit": "Upravit požadavek",
+  "components.RequestCard.editrequest": "Upravit požadavek",
+  "components.RequestModal.SearchByNameModal.nomatches": "Pro tuto sérii jsme nenašli shodu.",
+  "components.RequestModal.requestcollection4ktitle": "Vyžádejte si kolekci ve 4K",
+  "components.RequestModal.requestcollectiontitle": "Vyžádat kolekci",
+  "components.RequestModal.requestmovie4ktitle": "Vyžádejte si film ve 4K",
+  "components.RequestModal.requestmovietitle": "Vyžádat si film",
+  "components.RequestModal.requestseries4ktitle": "Žádost o sérii ve 4K",
+  "components.RequestModal.requestseriestitle": "Vyžádat sérii",
+  "components.TvDetails.episodeCount": "{episodeCount, plural, one {# Epizoda} other {# Epizody}}",
+  "components.NotificationTypeSelector.mediaautorequested": "Žádost byla odeslána automaticky",
+  "components.NotificationTypeSelector.mediaautorequestedDescription": "Získejte upozornění, když jsou automaticky odeslány nové požadavky na média pro položky na vašem Plex Watchlistu.",
+  "components.PermissionEdit.viewwatchlistsDescription": "Udělte oprávnění k zobrazení Plex Watchlistu ostatních uživatelů.",
+  "components.TvDetails.Season.somethingwentwrong": "Při načítání údajů o sezóně se něco pokazilo.",
+  "i18n.restartRequired": "Je vyžadován restart",
+  "components.Discover.plexwatchlist": "Váš Plex Watchlist",
+  "components.MovieDetails.theatricalrelease": "Dostupné v kinách",
+  "components.Discover.DiscoverWatchlist.watchlist": "Plex Watchlist",
+  "components.TvDetails.reportissue": "Nahlásit problém",
+  "components.MovieDetails.tmdbuserscore": "Uživatelské skóre TMDB",
+  "components.TvDetails.seasonstitle": "Sezóny",
+  "components.TvDetails.seasonnumber": "Sezóna {seasonNumber}",
+  "components.TvDetails.rtcriticsscore": "Rotten Tomatoes Tomatometer",
+  "components.TvDetails.rtaudiencescore": "Rotten Tomatoes Audience Skóre",
+  "components.TvDetails.tmdbuserscore": "Uživatelské skóre TMDB",
+  "components.TvDetails.status4k": "4K {status}",
+  "components.Discover.emptywatchlist": "Média přidaná do vašeho <PlexWatchlistSupportLink>Plex Watchlistu</PlexWatchlistSupportLink> se zobrazí zde.",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmoviestip": "Automaticky vyžádat filmy na vašem <PlexWatchlistSupportLink>Plex Watchlistu</PlexWatchlistSupportLink>",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseriestip": "Automaticky vyžádejte sérii na vašem <PlexWatchlistSupportLink>Plex Watchlistu</PlexWatchlistSupportLink>",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseries": "Automaticky vyžádat sérii",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmovies": "Automaticky vyžádat filmy",
+  "components.UserProfile.plexwatchlist": "Plex Watchlist",
+  "components.UserProfile.emptywatchlist": "Zde se zobrazí média přidaná do vašeho <PlexWatchlistSupportLink>Plex Watchlistu</PlexWatchlistSupportLink>."
 }
diff --git a/src/i18n/locale/da.json b/src/i18n/locale/da.json
index ab232761..3df86ad8 100644
--- a/src/i18n/locale/da.json
+++ b/src/i18n/locale/da.json
@@ -29,10 +29,9 @@
   "components.Discover.upcoming": "Kommende Film",
   "components.Discover.trending": "Aktuelle",
   "components.Discover.recentrequests": "Seneste Forespørgsler",
-  "components.Discover.recentlyAdded": "Nyligt tilføjet",
+  "components.Discover.recentlyAdded": "Tilføjet for nyligt",
   "components.Discover.populartv": "Populære Serier",
   "components.Discover.popularmovies": "Populære Film",
-  "components.Discover.noRequests": "Ingen forespørgsler.",
   "components.Discover.discovertv": "Populære Serier",
   "components.Discover.discover": "Udforsk",
   "components.Discover.TvGenreSlider.tvgenres": "Seriegenrer",
@@ -126,7 +125,7 @@
   "components.IssueDetails.IssueComment.postedby": "Sendt {relativeTime} af {username}",
   "components.IssueDetails.IssueComment.postedbyedited": "Sendt {relativeTime} af {username} (Redigeret)",
   "components.IssueDetails.problemepisode": "Påvirket Episode",
-  "components.ManageSlideOver.downloadstatus": "Download Status",
+  "components.ManageSlideOver.downloadstatus": "Downloads",
   "components.ManageSlideOver.manageModalNoRequests": "Ingen forespørgsler.",
   "components.ManageSlideOver.movie": "film",
   "components.PersonDetails.lifespan": "{birthdate} – {deathdate}",
@@ -161,7 +160,6 @@
   "components.PermissionEdit.viewissues": "Vis Problemer",
   "components.RequestBlock.server": "Destinationsserver",
   "components.IssueModal.CreateIssueModal.extras": "Ekstra",
-  "components.IssueModal.CreateIssueModal.issomethingwrong": "Er der et problem med {title}?",
   "components.IssueModal.CreateIssueModal.problemseason": "Berørt Sæson",
   "components.IssueModal.CreateIssueModal.providedetail": "Giv venligst en detaljeret beskrivelse af problemet du stødte på.",
   "components.IssueModal.CreateIssueModal.reportissue": "Rapportér et Problem",
@@ -202,7 +200,7 @@
   "components.IssueModal.issueSubtitles": "Undertekst",
   "components.IssueModal.issueVideo": "Video",
   "components.Layout.Sidebar.issues": "Problemer",
-  "components.ManageSlideOver.manageModalClearMedia": "Ryd Mediedata",
+  "components.ManageSlideOver.manageModalClearMedia": "Ryd data",
   "components.ManageSlideOver.manageModalClearMediaWarning": "* Dette vil slette alle data for denne {mediaType} uden mulighed for gendannelse, inklusiv alle forespørgsler. Hvis dette objekt findes i dit Plex bibliotek vil medieinformationen blive genskabt under næste skanning.",
   "components.IssueModal.CreateIssueModal.whatswrong": "Hvad er galt?",
   "components.IssueModal.issueAudio": "Lyd",
@@ -224,7 +222,6 @@
   "components.PermissionEdit.requestTv": "Forespørg Serier",
   "components.PermissionEdit.autoapproveMoviesDescription": "Giv automatisk godkendelse for alle ikke-4K filmforespørgsler.",
   "components.PermissionEdit.requestTvDescription": "Bliv notificeret når problemer er genåbnet af andre brugere.",
-  "components.PermissionEdit.settings": "Administrér Indstillinger",
   "components.RegionSelector.regionServerDefault": "Standard ({region})",
   "components.RequestCard.deleterequest": "Slet Forespørgsel",
   "components.RequestCard.mediaerror": "Den forbundne titel for denne forespørgsel er ikke længere tilgængelig.",
@@ -253,7 +250,6 @@
   "components.RequestModal.QuotaDisplay.allowedRequests": "Du kan forespørge om <strong>{limit}</strong> {type} hver <strong>{days}</strong> dag.",
   "components.RequestModal.QuotaDisplay.allowedRequestsUser": "Denne bruger kan forespørge om <strong>{limit}</strong> {type} hver <strong>{days}</strong> dag.",
   "components.IssueDetails.IssueComment.validationComment": "Du skal skrive en besked",
-  "components.PermissionEdit.settingsDescription": "Giv tilladelse til at modificere globale indstillinger. En bruger skal have denne rettighed for at kunne give den til andre.",
   "components.ManageSlideOver.manageModalIssues": "Åbne Problemer",
   "components.MovieDetails.showless": "Vis Mindre",
   "components.MovieDetails.cast": "Medvirkende",
@@ -272,8 +268,8 @@
   "components.RequestModal.seasonnumber": "Vis Alle Forespørgsler",
   "components.NotificationTypeSelector.mediadeclinedDescription": "Send notifikationer når medieforespørgsler afvises.",
   "components.Settings.Notifications.NotificationsWebPush.httpsRequirement": "For at kunne modtage web push-notifikationer skal Overseerr benytte HTTPS.",
-  "components.NotificationTypeSelector.mediaavailable": "Medie Tilgængelig",
-  "components.NotificationTypeSelector.mediafailed": "Medie Fejlede",
+  "components.NotificationTypeSelector.mediaavailable": "Forespørgsel tilgængelig",
+  "components.NotificationTypeSelector.mediafailed": "Behandling af forespørgsel mislykkedes",
   "components.PermissionEdit.admin": "Administrator",
   "components.PermissionEdit.adminDescription": "Fuld administratoradgang. Omgår alle andre tilladelseskontroller.",
   "components.PermissionEdit.advancedrequest": "Avancerede Forespørgsler",
@@ -288,14 +284,13 @@
   "components.RequestModal.QuotaDisplay.requiredquotaUser": "Denne bruger skal mindst have <strong>{seasons}</strong> {seasons, plural, one {sæsonforespørgsel} other {sæsonforespørgsler}} tilbage for at indsende en forespørgsel fore denne serie.",
   "components.RequestModal.QuotaDisplay.season": "sæson",
   "components.RequestModal.QuotaDisplay.seasonlimit": "{limit, plural, one {sæson} other {sæsoner}}",
-  "components.RequestModal.SearchByNameModal.nosummary": "Der kunne ikke findes en beskrivelse for denne titel.",
   "components.RequestModal.alreadyrequested": "Allerede Forespurgt",
   "components.RequestModal.cancel": "Annullér Forespørgsel",
   "components.RequestModal.edit": "Redigér Forespørgsel",
   "components.RequestModal.errorediting": "Noget gik galt under redigeringen af forespørgslen.",
   "components.RequestModal.extras": "Ekstra",
   "components.RequestModal.numberofepisodes": "Antal Episoder",
-  "components.RequestModal.pending4krequest": "Afventende 4K Forespørgsler for {title}",
+  "components.RequestModal.pending4krequest": "Afventende 4K Forespørgsler",
   "components.RequestModal.pendingapproval": "Din forespørgsel afventer godkendelse.",
   "components.ResetPassword.resetpasswordsuccessmessage": "Kodeord er nulstillet!",
   "components.Settings.Notifications.NotificationsLunaSea.profileName": "Profilnavn",
@@ -321,7 +316,7 @@
   "components.NotificationTypeSelector.issuereopened": "Problem Genåbnet",
   "components.NotificationTypeSelector.issuereopenedDescription": "Send notifikationer når problemer genåbnes.",
   "components.NotificationTypeSelector.mediafailedDescription": "Send notifikationer når medieforespørgsler ikke kunne tilføjes til Radarr eller Sonarr.",
-  "components.NotificationTypeSelector.mediarequested": "Medie Forespurgt",
+  "components.NotificationTypeSelector.mediarequested": "Forespørgsel afventer godkendelse",
   "components.NotificationTypeSelector.userissuecommentDescription": "Bliv notificeret når problemer du har rapporteret får nye kommentarer.",
   "components.NotificationTypeSelector.userissuecreatedDescription": "Bliv notificeret når andre brugere rapporterer problemer.",
   "components.NotificationTypeSelector.userissuereopenedDescription": "Bliv notificeret når problemer du har rapporteret er genåbnet.",
@@ -338,7 +333,6 @@
   "components.RequestModal.requesterror": "Noget gik galt under indsendelsen af forespørgslen.",
   "components.RequestModal.requestfrom": "{username}s forespørgsel afventer godkendelse.",
   "components.RequestModal.requestseasons": "Forespørg om {seasonCount} {seasonCount, plural, one {Sæson} other {Sæsoner}}",
-  "components.RequestModal.requesttitle": "Forespørg om {title}",
   "components.RequestModal.season": "Sæson",
   "components.ResetPassword.passwordreset": "Nulstil Kodeord",
   "components.ResetPassword.requestresetlinksuccessmessage": "Et link til nulstilling af dit kodeord vil blive sendt til den angivne email adresse såfremt der eksisterer en konto til den.",
@@ -384,11 +378,11 @@
   "components.NotificationTypeSelector.usermediadeclinedDescription": "Bliv notificeret når dine medieforespørgsler afvises.",
   "components.RequestModal.autoapproval": "Automatisk Godkendelse",
   "components.ResetPassword.emailresetlink": "Send email med gendannelseslink",
-  "components.NotificationTypeSelector.mediaAutoApproved": "Medie Automatisk Godkendt",
+  "components.NotificationTypeSelector.mediaAutoApproved": "Anmodning godkendes automatisk",
   "components.NotificationTypeSelector.mediarequestedDescription": "Send notifikationer når brugere indsender nye medieforespørgsler som kræver godkendelse.",
   "components.NotificationTypeSelector.notificationTypes": "Notifikationstyper",
   "components.Settings.Notifications.NotificationsWebhook.agentenabled": "Aktivér Agent",
-  "components.NotificationTypeSelector.mediaapproved": "Medie Godkendt",
+  "components.NotificationTypeSelector.mediaapproved": "Anmodning godkendt",
   "components.NotificationTypeSelector.issuecomment": "Problemkommentar",
   "components.NotificationTypeSelector.issuecommentDescription": "Send notifikationer når problemer får nye kommentarer.",
   "components.NotificationTypeSelector.issuecreated": "Problem Rapporteret",
@@ -397,7 +391,7 @@
   "components.NotificationTypeSelector.issueresolvedDescription": "Send notifikationer når problemer er løst.",
   "components.NotificationTypeSelector.mediaapprovedDescription": "Send notifikationer når medieforespørgsler manuelt godkendes.",
   "components.NotificationTypeSelector.mediaavailableDescription": "Send notifikationer når medieforespørgsler bliver tilgængelige.",
-  "components.NotificationTypeSelector.mediadeclined": "Medie Afvist",
+  "components.NotificationTypeSelector.mediadeclined": "Forespørgsel Afvist",
   "components.NotificationTypeSelector.usermediafailedDescription": "Bliv notificeret når medieforespørgsler ikke kunne tilføjes til Radarr eller Sonarr.",
   "components.NotificationTypeSelector.usermediarequestedDescription": "Bliv notificeret når andre brugere indsender nye medieforespørgsler som kræver godkendelse.",
   "components.PermissionEdit.autoapprove4kDescription": "Giv automatisk godkendelse for alle 4K medieforespørgsler.",
@@ -410,8 +404,7 @@
   "components.RequestCard.failedretry": "Noget gik galt ved nyt forsøg på forespørgslen.",
   "components.RequestModal.QuotaDisplay.requestsremaining": "{remaining, plural, =0 {Ingen} other {<strong>#</strong>}} {type} {remaining, plural, one {forespørgsel} other {forespørgsler}} tilbage",
   "components.RequestModal.SearchByNameModal.notvdbiddescription": "Vi kunne ikke automatisk matche din forespørgsel. Vælg venligst det korrekte match fra listen nedenfor.",
-  "components.RequestModal.pendingrequest": "Afventende Forespørgsel for {title}",
-  "components.RequestModal.request4ktitle": "Forespørg om {title} i 4K",
+  "components.RequestModal.pendingrequest": "Afventende Forespørgsel",
   "components.Settings.Notifications.NotificationsPushover.userToken": "Bruger- eller Gruppenøgle",
   "components.Settings.Notifications.NotificationsPushover.userTokenTip": "Dit 30-tegns <UsersGroupsLink>bruger- eller gruppe-ID</UsersGroupsLink>",
   "components.Settings.Notifications.NotificationsPushover.validationUserTokenRequired": "Du skal angive en gyldig bruger- eller gruppenøgle",
@@ -448,9 +441,9 @@
   "components.Settings.RadarrModal.testFirstQualityProfiles": "Test forbindelse for at indlæse kvalitetsprofiler",
   "components.Settings.RadarrModal.validationApplicationUrl": "Du skal angive en gyldig URL",
   "components.Settings.RadarrModal.validationApplicationUrlTrailingSlash": "URL'en må ikke afsluttes med en skråstreg",
-  "components.Settings.RadarrModal.validationBaseUrlTrailingSlash": "Base-URL'en må ikke afsluttes med en skråstreg",
+  "components.Settings.RadarrModal.validationBaseUrlTrailingSlash": "URL-basen må ikke slutte med en skråstreg",
   "components.Settings.RadarrModal.validationHostnameRequired": "Du skal angive et gyldigt domænenavn eller en gyldig IP-adresse",
-  "components.Settings.RadarrModal.validationBaseUrlLeadingSlash": "Base-URL'en må ikke starte med en skråstreg",
+  "components.Settings.RadarrModal.validationBaseUrlLeadingSlash": "URL-basen skal have en indledende skråstreg",
   "components.Settings.RadarrModal.validationPortRequired": "Du skal angive et gyldigt port-nummer",
   "components.Settings.RadarrModal.validationProfileRequired": "Du skal vælge en kvalitetsprofil",
   "components.Settings.SettingsAbout.Releases.latestversion": "Nyeste",
@@ -638,7 +631,7 @@
   "components.Settings.partialRequestsEnabled": "Tillad Delvise Serieforespørgsler",
   "components.Settings.plex": "Plex",
   "components.Settings.SettingsJobsCache.jobScheduleEditSaved": "Jobbet er blevet redigeret!",
-  "components.Settings.csrfProtectionTip": "Sæt ekstern API-adgang til skrivebeskyttet (kræver HTTPS samt at Overseerr genstartes for at ændringerne vil træde i kraft)",
+  "components.Settings.csrfProtectionTip": "Sæt ekstern API-adgang til skrivebeskyttet (kræver HTTPS)",
   "components.Settings.generalsettingsDescription": "Konfigurér global- og standardindstillinger for Overseerr.",
   "components.Settings.general": "Generelt",
   "components.Settings.hideAvailable": "Skjul Tilgængelige Medier",
@@ -729,7 +722,6 @@
   "components.StatusBadge.status4k": "4K {status}",
   "components.Setup.tip": "Tip",
   "components.Setup.welcome": "Velkommen til Overseerr",
-  "components.StatusChacker.reloadOverseerr": "Genindlæs",
   "components.TvDetails.anime": "Anime",
   "components.TvDetails.cast": "Roller",
   "components.TvDetails.episodeRuntimeMinutes": "{runtime} minutter",
@@ -761,7 +753,7 @@
   "components.Settings.radarrsettings": "Radarr-indstillinger",
   "components.Settings.region": "Udforsk Region",
   "components.Settings.trustProxy": "Aktivér Proxy-understøttelse",
-  "components.Settings.trustProxyTip": "Tillad Overseerr at registrere klienters IP addresser korrekt bag en proxy (Overseerr skal genstartes for at ændringerne træder i kraft)",
+  "components.Settings.trustProxyTip": "Tillad Overseerr at registrere klienters IP addresser korrekt bag en proxy",
   "components.TvDetails.nextAirDate": "Næste Udsendelsesdato",
   "components.TvDetails.playonplex": "Afspil i Plex",
   "components.TvDetails.recommendations": "Anbefalinger",
@@ -778,7 +770,7 @@
   "components.UserList.created": "Tilsluttet",
   "components.UserList.createlocaluser": "Opret lokal bruger",
   "components.UserList.creating": "Opretter…",
-  "components.UserList.importfromplexerror": "Noget gik galt under importeringen af brugere fra Plex.",
+  "components.UserList.importfromplexerror": "Noget gik galt under importen af Plex-brugere.",
   "components.UserList.sortRequests": "Antal Forespørgsler",
   "components.UserProfile.UserSettings.UserGeneralSettings.seriesrequestlimit": "Grænse for Serieforespørgsler",
   "components.UserProfile.UserSettings.UserGeneralSettings.toastSettingsSuccess": "Indstillingerne er blevet gemt!",
@@ -824,7 +816,7 @@
   "components.Settings.toastPlexRefresh": "Henter serverliste fra Plex…",
   "components.Settings.toastPlexRefreshFailure": "Kunne ikke hente Plex-serverliste.",
   "components.Settings.toastPlexRefreshSuccess": "Plex-serverliste er blevet hentet!",
-  "components.Settings.toastSettingsFailure": "Noget gik galt. Indstillingerne kunne ikke gemmes.",
+  "components.Settings.toastSettingsFailure": "Noget gik galt under opdateringen af indstillingerne.",
   "components.Settings.validationApplicationTitle": "Du skal angive en applikationstitel",
   "components.Settings.validationApplicationUrlTrailingSlash": "URL'en må ikke afsluttes med en skråstreg",
   "components.Settings.validationHostnameRequired": "Du skal angive et gyldigt domænenavn eller en gyldig IP adresse",
@@ -837,20 +829,18 @@
   "components.Setup.loginwithplex": "Log in med Plex",
   "components.Setup.scanbackground": "Skanningen wil køre i baggrunden. Du kan fortsætte opsætningsprocessen i mellemtiden.",
   "components.Setup.setup": "Opsætning",
-  "components.StatusChacker.newversionDescription": "Overseerr er blevet opdateret! Klik venligst på knappen nedenfor for at genindlæse siden.",
   "components.TvDetails.firstAirDate": "Første Udsendelsesdato",
   "components.TvDetails.overview": "Oversigt",
-  "components.StatusChacker.newversionavailable": "Applikationsopdatering",
   "components.TvDetails.TvCrew.fullseriescrew": "Komplet Rolleliste",
   "components.TvDetails.overviewunavailable": "Oversigt utilgængelig.",
   "components.TvDetails.play4konplex": "Afspil i 4K i Plex",
   "components.UserList.localuser": "Lokal Bruger",
   "components.UserList.deleteuser": "Slet Bruger",
   "components.UserList.displayName": "Kaldenavn",
-  "components.UserList.nouserstoimport": "Ingen nye brugere som kan importeres fra Plex.",
+  "components.UserList.nouserstoimport": "Der er ingen Plex-brugere, der skal importeres.",
   "components.UserList.edituser": "Redigér Brugertilladelser",
   "components.UserList.email": "Email Adresse",
-  "components.UserList.importfromplex": "Importér Brugere fra Plex",
+  "components.UserList.importfromplex": "Importer Plex-brugere",
   "components.UserList.owner": "Ejer",
   "components.UserList.password": "Kodeord",
   "components.UserList.passwordinfodescription": "Konfigurér en applikations-URL og aktivér emailnotifikationer for at tillade automatisk kodeordsgenerering.",
@@ -933,7 +923,6 @@
   "components.UserProfile.UserSettings.UserPasswordChange.toastSettingsFailure": "Noget gik galt, kodeordet kunne ikke gemmes.",
   "components.UserProfile.UserSettings.menuPermissions": "Tilladelser",
   "components.UserProfile.UserSettings.unauthorizedDescription": "Du har ikke tilladelse til at ændre denne bruger's indstillinger.",
-  "components.UserProfile.norequests": "Ingen forespørgsler.",
   "components.UserProfile.pastdays": "{type} (seneste {days} dage)",
   "components.UserProfile.recentrequests": "Seneste Forespørgsler",
   "components.UserProfile.requestsperdays": "{limit} tilbage",
@@ -952,7 +941,7 @@
   "i18n.loading": "Indlæser…",
   "i18n.movie": "Film",
   "i18n.movies": "Film",
-  "i18n.open": "Åben",
+  "i18n.open": "Åbn",
   "i18n.partiallyavailable": "Delvist Tilgængelig",
   "i18n.pending": "Afventer",
   "i18n.requesting": "Forespørger…",
@@ -1013,5 +1002,29 @@
   "components.Settings.Notifications.NotificationsGotify.validationTokenRequired": "Der skal angives en applikations token",
   "components.Settings.Notifications.NotificationsGotify.gotifysettingsfailed": "Gemning notifikationsindstillinger kunne ikke gemmes.",
   "components.Settings.validationUrlTrailingSlash": "URL'en må ikke afsluttes med en skråstreg",
-  "components.ManageSlideOver.manageModalMedia": "Medie"
+  "components.ManageSlideOver.manageModalMedia": "Medie",
+  "components.Settings.RadarrModal.released": "Udgivet",
+  "components.Settings.tautulliApiKey": "API nøgle",
+  "components.Settings.tautulliSettings": "Tautulli indstillinger",
+  "components.Settings.tautulliSettingsDescription": "Alternativt kan du konfigurere indstillingerne for din Tautulli server. Overseerr henter visningshistorikken for dit Plex medie fra Tautulli.",
+  "components.Settings.toastTautulliSettingsFailure": "Noget gik galt, da du gemte Tautulli indstillinger.",
+  "components.Settings.validationApiKey": "Du skal angive en API-nøgle",
+  "components.UserProfile.recentlywatched": "For nylig set",
+  "components.Settings.toastTautulliSettingsSuccess": "Tautulli indstillingerne blev gemt succesfuldt!",
+  "components.UserProfile.UserSettings.UserGeneralSettings.discordId": "Discord-bruger-id",
+  "components.Settings.validationUrl": "Du skal angive en gyldig URL",
+  "components.Settings.validationUrlBaseLeadingSlash": "URL-basen skal have en foranstillet skråstreg",
+  "components.UserProfile.UserSettings.UserGeneralSettings.discordIdTip": "Det <FindDiscordIdLink> flercifrede ID-nummer</FindDiscordIdLink>, der er knyttet til din Discord-brugerkonto",
+  "components.Settings.validationUrlBaseTrailingSlash": "URL-basen må ikke ende i en efterfølgende skråstreg",
+  "components.UserProfile.UserSettings.UserGeneralSettings.validationDiscordId": "Du skal oplyse et gyldigt Discord-bruger-id",
+  "i18n.import": "Importere",
+  "components.ManageSlideOver.manageModalMedia4k": "4K medier",
+  "components.Settings.externalUrl": "Ekstern URL",
+  "components.Settings.RadarrModal.announced": "Annonceret",
+  "components.Settings.RadarrModal.inCinemas": "I biograferne",
+  "components.Settings.urlBase": "URL base",
+  "components.UserList.newplexsigninenabled": "Indstillingen <strong>Aktiver nyt Plex-login</strong> er i øjeblikket aktiveret. Plex-brugere med biblioteksadgang behøver ikke at blive importeret for at kunne logge ind.",
+  "components.Settings.SettingsAbout.appDataPath": "Data mappe",
+  "components.Settings.Notifications.NotificationsPushbullet.channelTag": "Kanal tag",
+  "i18n.importing": "Importerer…"
 }
diff --git a/src/i18n/locale/de.json b/src/i18n/locale/de.json
index 182590ae..5c96a715 100644
--- a/src/i18n/locale/de.json
+++ b/src/i18n/locale/de.json
@@ -33,13 +33,12 @@
   "components.RequestModal.cancel": "Anfrage abbrechen",
   "components.RequestModal.extras": "Extras",
   "components.RequestModal.numberofepisodes": "Anzahl der Folgen",
-  "components.RequestModal.pendingrequest": "Ausstehende Anfrage für {title}",
+  "components.RequestModal.pendingrequest": "Ausstehende Anfrage",
   "components.RequestModal.requestCancel": "Anfrage für <strong>{title}</strong> abgebrochen.",
   "components.RequestModal.requestSuccess": "<strong>{title}</strong> erfolgreich angefragt!",
   "components.RequestModal.requestadmin": "Diese Anfrage wird automatisch genehmigt.",
   "components.RequestModal.requestfrom": "Die Anfrage von {username} muss noch genehmigt werden.",
   "components.RequestModal.requestseasons": "{seasonCount} {seasonCount, plural, one {Staffel} other {Staffeln}} anfragen",
-  "components.RequestModal.requesttitle": "{title} anfragen",
   "components.RequestModal.season": "Staffel",
   "components.RequestModal.seasonnumber": "Staffel {number}",
   "components.RequestModal.selectseason": "Staffel(n) Auswählen",
@@ -229,7 +228,7 @@
   "components.PersonDetails.crewmember": "Crew",
   "components.MovieDetails.viewfullcrew": "Komplette Crew anzeigen",
   "components.MovieDetails.MovieCrew.fullcrew": "Komplette Crew",
-  "components.UserList.importedfromplex": "<strong>{userCount}</strong> {userCount, Plural, ein {Benutzer} other {Benutzer}} Plex-Benutzer erfolgreich importiert!",
+  "components.UserList.importedfromplex": "<strong>{userCount}</strong> Plex {userCount, Plural, ein {Benutzer} other {Benutzer}} erfolgreich importiert!",
   "components.TvDetails.firstAirDate": "Erstausstrahlung",
   "components.Settings.Notifications.allowselfsigned": "Selbstsignierte Zertifikate erlauben",
   "components.TvDetails.watchtrailer": "Trailer ansehen",
@@ -252,9 +251,6 @@
   "components.Settings.Notifications.senderName": "Absendername",
   "components.Settings.Notifications.chatId": "Chat-ID",
   "components.Settings.Notifications.botAPI": "Bot-Autorisierungstoken",
-  "components.StatusChacker.reloadOverseerr": "Overseerr neu laden",
-  "components.StatusChacker.newversionavailable": "Anwendungsaktualisierung",
-  "components.StatusChacker.newversionDescription": "Overseerr wurde aktualisiert! Bitte klicke auf die Schaltfläche unten, um die Seite neu zu laden.",
   "components.Settings.SettingsAbout.documentation": "Dokumentation",
   "components.NotificationTypeSelector.mediarequestedDescription": "Sende Benachrichtigungen, wenn neue Medien angefordert wurden und auf Genehmigung warten.",
   "components.NotificationTypeSelector.mediarequested": "Anfrage in Bearbeitung",
@@ -286,8 +282,7 @@
   "components.Settings.Notifications.NotificationsWebhook.customJson": "JSON-Inhalt",
   "components.Settings.Notifications.NotificationsWebhook.authheader": "Autorisierungsüberschrift",
   "components.Settings.Notifications.NotificationsWebhook.agentenabled": "Dienst aktivieren",
-  "components.RequestModal.request4ktitle": "{title} in 4K anfragen",
-  "components.RequestModal.pending4krequest": "Ausstehende 4K Anfrage für {title}",
+  "components.RequestModal.pending4krequest": "Ausstehende 4K Anfrage",
   "components.RequestButton.viewrequest4k": "4K Anfrage anzeigen",
   "components.RequestButton.viewrequest": "Anfrage anzeigen",
   "components.RequestButton.requestmore4k": "Mehr in 4K anfragen",
@@ -339,7 +334,6 @@
   "components.Settings.hideAvailable": "Verfügbare Medien ausblenden",
   "components.RequestModal.requesterror": "Beim Senden der Anfragen ist etwas schief gelaufen.",
   "components.RequestModal.SearchByNameModal.notvdbiddescription": "Wir konnten deine Anfrage nicht automatisch zuordnen. Bitte wähle eine korrekte Übereinstimmung aus der Liste aus.",
-  "components.RequestModal.SearchByNameModal.nosummary": "Keine Zusammenfassung für diesen Titel gefunden.",
   "components.Login.signinwithplex": "Benutze dein Plex-Konto",
   "components.Login.signinheader": "Anmelden um fortzufahren",
   "components.Login.signingin": "Anmelden …",
@@ -354,7 +348,7 @@
   "components.PermissionEdit.request": "Anfrage",
   "components.PermissionEdit.autoapproveMovies": "Automatische Genehmigung von Filmen",
   "components.PermissionEdit.admin": "Admin",
-  "components.PermissionEdit.managerequestsDescription": "Gewähre Berechtigung zum Verwalten von Medienanfragen. Alle Anfragen eines Benutzers mit dieser Berechtigung werden automatisch genehmigt.",
+  "components.PermissionEdit.managerequestsDescription": "Autorisierung zur Verwaltung von Medienanfragen. Alle Anfragen, die von einem Benutzer mit dieser Berechtigung gestellt werden, werden automatisch genehmigt.",
   "components.UserList.userssaved": "Benutzerberechtigungen erfolgreich gespeichert!",
   "components.UserList.bulkedit": "Ausgewählte bearbeiten",
   "components.Settings.toastPlexRefreshSuccess": "Plex-Serverliste erfolgreich abgerufen!",
@@ -370,25 +364,23 @@
   "components.Settings.serverpreset": "Server",
   "components.Settings.serverRemote": "entfernt",
   "components.Settings.serverLocal": "lokal",
-  "components.Settings.csrfProtectionTip": "Macht den externen API Zugang schreibgeschützt (setzt HTTPS voraus und Overseerr muss neu gestartet werden, damit die Änderungen wirksam werden)",
+  "components.Settings.csrfProtectionTip": "Macht den externen API Zugang schreibgeschützt (setzt HTTPS voraus)",
   "components.Settings.csrfProtection": "Aktiviere CSRF Schutz",
   "components.Settings.SonarrModal.toastSonarrTestSuccess": "Sonarr-Verbindung erfolgreich hergestellt!",
   "components.Settings.SonarrModal.toastSonarrTestFailure": "Verbindung zu Sonarr fehlgeschlagen.",
-  "components.PermissionEdit.usersDescription": "Gewähre Berechtigung zum Verwalten von Benutzern. Benutzer mit dieser Berechtigung können Benutzer mit Adminrechten nicht bearbeiten oder Adminrechte erteilen.",
+  "components.PermissionEdit.usersDescription": "Autorisierung zur Benutzerverwaltung erteilen. Benutzer mit dieser Berechtigung können keine Benutzer mit Admin-Recht ändern oder das Admin-Recht gewähren.",
   "components.PermissionEdit.users": "Benutzer verwalten",
-  "components.PermissionEdit.settingsDescription": "Gewähre Berechtigung um globale Einstellungen zu ändern. Ein Benutzer muss über diese Berechtigung verfügen, um sie anderen Benutzern erteilen zu können.",
-  "components.PermissionEdit.settings": "Einstellungen verwalten",
-  "components.PermissionEdit.requestDescription": "Berechtigt, nicht-4K Inhalte anzufragen.",
-  "components.PermissionEdit.request4kTvDescription": "Berechtigt, Serien in 4K anzufragen.",
+  "components.PermissionEdit.requestDescription": "Autorisierung zur Übermittlung von Anfragen für nicht-4K Medien.",
+  "components.PermissionEdit.request4kTvDescription": "Autorisierung zur Übermittlung von Anfragen für 4K-Serien.",
   "components.PermissionEdit.request4kTv": "4K Serien anfragen",
-  "components.PermissionEdit.request4kMoviesDescription": "Berechtigt, Filme in 4K anzufragen.",
+  "components.PermissionEdit.request4kMoviesDescription": "Autorisierung zur Übermittlung von Anfragen für 4K-Filme.",
   "components.PermissionEdit.request4kMovies": "4K Filme anfragen",
   "components.PermissionEdit.request4k": "4K anfragen",
-  "components.PermissionEdit.request4kDescription": "Gewähre Berechtigung Medien in 4K anzufragen.",
-  "components.PermissionEdit.autoapproveSeriesDescription": "Gewähre Berechtigung zur automatischen Genehmigung von nicht-4K Serienanfragen.",
-  "components.PermissionEdit.autoapproveMoviesDescription": "Gewähre Berechtigung zur automatischen Genehmigung von nicht-4K Filmanfragen.",
-  "components.PermissionEdit.autoapproveDescription": "Gewähre Berechtigung zur automatischen Genehmigung von allen nicht-4K Anfragen.",
-  "components.PermissionEdit.advancedrequestDescription": "Gewähre Berechtigung zum Ändern erweiterter Anfrageoptionen.",
+  "components.PermissionEdit.request4kDescription": "Autorisierung zur Anfrage von Medien in 4K.",
+  "components.PermissionEdit.autoapproveSeriesDescription": "Autorisierung der automatischen Freigabe von Anfragen für nicht-4K-Serien.",
+  "components.PermissionEdit.autoapproveMoviesDescription": "Autorisierung der automatischen Freigabe von Anfragen für nicht-4K-Filme.",
+  "components.PermissionEdit.autoapproveDescription": "Autorisierung der automatischen Freigabe von nicht-4K Anfragen.",
+  "components.PermissionEdit.advancedrequestDescription": "Autorisierung zur Änderung der erweiterten Optionen für Medienanfragen.",
   "components.PermissionEdit.adminDescription": "Voller Administratorzugriff. Umgeht alle anderen Rechteabfragen.",
   "components.Settings.SonarrModal.syncEnabled": "Scannen aktivieren",
   "components.Settings.SonarrModal.externalUrl": "Externe URL",
@@ -398,7 +390,7 @@
   "components.MovieDetails.playonplex": "Auf Plex abspielen",
   "components.TvDetails.play4konplex": "In 4K auf Plex abspielen",
   "components.MovieDetails.play4konplex": "In 4K auf Plex abspielen",
-  "components.Settings.trustProxyTip": "Erlaubt es Overseerr Client IP Adressen hinter einem Proxy korrekt zu registrieren (Overseerr muss neu gestartet werden, damit die Änderungen wirksam werden)",
+  "components.Settings.trustProxyTip": "Erlaubt es Overseerr Client IP Adressen hinter einem Proxy korrekt zu registrieren",
   "components.Settings.trustProxy": "Proxy-Unterstützung aktivieren",
   "components.Settings.SettingsJobsCache.runnow": "Jetzt ausführen",
   "components.Settings.SettingsJobsCache.nextexecution": "Nächste Ausführung",
@@ -452,7 +444,7 @@
   "components.ResetPassword.gobacklogin": "Zurück zur Anmeldeseite",
   "components.ResetPassword.emailresetlink": "Wiederherstellungs-Link per E-Mail senden",
   "components.ResetPassword.email": "E-Mail-Adresse",
-  "components.PermissionEdit.viewrequestsDescription": "Berechtigt, Anfragen anderer Nutzer zu sehen.",
+  "components.PermissionEdit.viewrequestsDescription": "Autorisierung zur Anzeige der von anderen Benutzern eingereichten Medienanfragen.",
   "components.PermissionEdit.viewrequests": "Anfragen anzeigen",
   "components.Login.forgotpassword": "Passwort vergessen?",
   "components.Settings.csrfProtectionHoverTip": "Aktiviere diese Option NICHT, es sei denn du weißt, was du tust!",
@@ -477,11 +469,11 @@
   "components.UserList.sortDisplayName": "Anzeigename",
   "components.UserList.sortCreated": "Beitrittsdatum",
   "components.PermissionEdit.autoapprove4k": "Automatische Genehmigung von 4K",
-  "components.PermissionEdit.autoapprove4kSeriesDescription": "Gewähre Berechtigung zur automatischen Genehmigung von 4K Serienanfragen.",
+  "components.PermissionEdit.autoapprove4kSeriesDescription": "Autorisierung der automatischen Freigabe von Anfragen für 4K-Serien.",
   "components.PermissionEdit.autoapprove4kSeries": "Automatische Genehmigung von 4K Serien",
-  "components.PermissionEdit.autoapprove4kMoviesDescription": "Gewähre Berechtigung zur automatischen Genehmigung von 4K Filmanfragen.",
+  "components.PermissionEdit.autoapprove4kMoviesDescription": "Autorisierung der automatischen Freigabe von Anfragen für 4K-Filme.",
   "components.PermissionEdit.autoapprove4kMovies": "Automatische Genehmigung von 4K Filmen",
-  "components.PermissionEdit.autoapprove4kDescription": "Gewähre Berechtigung zur automatischen Genehmigung von allen 4K Anfragen.",
+  "components.PermissionEdit.autoapprove4kDescription": "Autorisierung der automatischen Freigabe für alle 4K-Medienanfragen.",
   "components.UserProfile.recentrequests": "Kürzliche Anfragen",
   "components.UserProfile.UserSettings.menuPermissions": "Berechtigungen",
   "components.UserProfile.UserSettings.menuNotifications": "Benachrichtigungen",
@@ -521,7 +513,7 @@
   "components.Layout.UserDropdown.settings": "Einstellungen",
   "components.Layout.UserDropdown.myprofile": "Profil",
   "components.UserProfile.UserSettings.UserNotificationSettings.validationDiscordId": "Du musst eine gültige Benutzer-ID angeben",
-  "components.UserProfile.UserSettings.UserNotificationSettings.discordIdTip": "Die <FindDiscordIdLink>ID Nummer</FindDiscordIdLink> für dein Benutzerkonto",
+  "components.UserProfile.UserSettings.UserNotificationSettings.discordIdTip": "Die <FindDiscordIdLink>mehrstellige ID-Nummer</FindDiscordIdLink> die mit deinem Benutzerkonto verbunden ist",
   "components.CollectionDetails.requestcollection4k": "Sammlung in 4K anfragen",
   "components.Settings.region": "Region Entdecken",
   "components.Settings.originallanguage": "Sprache Entdecken",
@@ -586,7 +578,6 @@
   "components.Settings.SettingsUsers.toastSettingsFailure": "Beim Speichern der Einstellungen ist ein Fehler aufgetreten.",
   "components.Settings.Notifications.pgpPrivateKeyTip": "Signiere verschlüsselte E-Mail-Nachrichten mit <OpenPgpLink>OpenPGP</OpenPgpLink>",
   "components.Settings.Notifications.pgpPasswordTip": "Signiere verschlüsselte E-Mail-Nachrichten mit <OpenPgpLink>OpenPGP</OpenPgpLink>",
-  "components.UserProfile.norequests": "Keine Anfragen.",
   "components.UserProfile.UserSettings.unauthorizedDescription": "Sie haben keine Berechtigung, die Einstellungen dieses Benutzers zu ändern.",
   "components.UserProfile.UserSettings.UserPermissions.unauthorizedDescription": "Sie können Ihre eigenen Berechtigungen nicht ändern.",
   "components.TvDetails.episodeRuntimeMinutes": "{runtime} Minuten",
@@ -738,12 +729,12 @@
   "components.RequestModal.AdvancedRequester.tags": "Tags",
   "components.RequestModal.AdvancedRequester.selecttags": "Wähle Tags aus",
   "components.RequestModal.AdvancedRequester.notagoptions": "Keine Tags.",
-  "components.RequestList.RequestItem.mediaerror": "Der zugehörige Titel für diese Anfrage ist nicht mehr verfügbar.",
+  "components.RequestList.RequestItem.mediaerror": "{mediaType} wurde nicht gefunden",
   "components.RequestList.RequestItem.editrequest": "Anfrage bearbeiten",
   "components.RequestList.RequestItem.deleterequest": "Anfrage löschen",
   "components.RequestCard.deleterequest": "Anfrage löschen",
   "components.RequestList.RequestItem.cancelRequest": "Anfrage abbrechen",
-  "components.RequestCard.mediaerror": "Der zugehörige Titel für diese Anfrage ist nicht mehr verfügbar.",
+  "components.RequestCard.mediaerror": "{mediaType} wurde nicht gefunden",
   "components.QuotaSelector.unlimited": "Unbegrenzt",
   "components.NotificationTypeSelector.notificationTypes": "Benachrichtigungstypen",
   "components.MovieDetails.originaltitle": "Originaltitel",
@@ -753,7 +744,6 @@
   "components.Layout.VersionStatus.commitsbehind": "{commitsBehind} {commitsBehind, plural, one {Version} other {Versionen}} hinterher",
   "components.LanguageSelector.originalLanguageDefault": "Alle Sprachen",
   "components.LanguageSelector.languageServerDefault": "Standard ({language})",
-  "components.Discover.noRequests": "Keine Anfragen.",
   "components.Settings.Notifications.NotificationsWebhook.validationTypes": "Sie müssen mindestens einen Benachrichtigungstypen auswählen",
   "components.Settings.Notifications.NotificationsWebhook.toastWebhookTestSuccess": "Webhook Test Benachrichtigung gesendet!",
   "components.Settings.Notifications.NotificationsWebhook.toastWebhookTestSending": "Webhook test Benachrichtigung wird gesendet…",
@@ -776,7 +766,7 @@
   "components.Settings.Notifications.NotificationsPushover.accessTokenTip": "<ApplicationRegistrationLink>Registriere eine Anwendung</ApplicationRegistrationLink> für die Benutzung mit Overseerr",
   "components.Settings.Notifications.NotificationsPushbullet.validationTypes": "Sie müssen mindestens einen Benachrichtigungstypen auswählen",
   "components.RequestCard.failedretry": "Beim erneuten Versuch die Anfrage zu senden ist ein Fehler aufgetreten.",
-  "components.PermissionEdit.requestTvDescription": "Berechtigt, nicht-4K Serien anzufragen.",
+  "components.PermissionEdit.requestTvDescription": "Autorisierung zur Übermittlung von Anfragen für nicht-4K-Serien.",
   "components.NotificationTypeSelector.usermediafailedDescription": "Werde benachrichtigt, wenn die angeforderten Medien bei der Hinzufügung zu Radarr oder Sonarr fehlschlagen.",
   "components.Settings.Notifications.NotificationsPushbullet.accessTokenTip": "Erstellen Sie einen Token in Ihren <PushbulletSettingsLink>Account Einstellungen</PushbulletSettingsLink>",
   "components.Settings.Notifications.NotificationsLunaSea.webhookUrl": "Webhook URL",
@@ -789,7 +779,7 @@
   "components.QuotaSelector.tvRequests": "{quotaLimit} <quotaUnits>{seasons} pro {quotaDays} {days}</quotaUnits>",
   "components.QuotaSelector.movieRequests": "{quotaLimit} <quotaUnits>{movies} pro {quotaDays} {days}</quotaUnits>",
   "components.PermissionEdit.requestTv": "Serien anfragen",
-  "components.PermissionEdit.requestMoviesDescription": "Berechtigt, nicht-4K Filme anzufordern.",
+  "components.PermissionEdit.requestMoviesDescription": "Autorisierung zur Übermittlung von Anfragen für nicht-4K-Filme.",
   "components.PermissionEdit.requestMovies": "Filme anfragen",
   "components.NotificationTypeSelector.usermediarequestedDescription": "Werde benachrichtigt, wenn andere Nutzer ein Medium anfordern, welches eine Genehmigung erfordert.",
   "components.NotificationTypeSelector.usermediadeclinedDescription": "Werde benachrichtigt, wenn deine Medienanfrage abgelehnt wurde.",
@@ -858,7 +848,6 @@
   "components.StatusBadge.status": "{status}",
   "components.IssueDetails.reopenissueandcomment": "Mit Kommentar wieder öffnen",
   "components.IssueModal.CreateIssueModal.allseasons": "Alle Staffeln",
-  "components.IssueModal.CreateIssueModal.issomethingwrong": "Gibt es ein Problem mit {title}?",
   "components.IssueModal.CreateIssueModal.problemepisode": "Betroffene Episode",
   "components.IssueModal.CreateIssueModal.problemseason": "Betroffene Staffel",
   "components.IssueModal.CreateIssueModal.providedetail": "Geben Sie eine detaillierte Erklärung des Problems an.",
@@ -977,9 +966,9 @@
   "components.UserProfile.UserSettings.UserNotificationSettings.validationPushoverApplicationToken": "Sie müssen ein gültiges Anwendungs-Token angeben",
   "components.UserProfile.UserSettings.UserNotificationSettings.validationPushoverUserKey": "Du musst einen gültigen Benutzer- oder Gruppenschlüssel angeben",
   "i18n.resolved": "Gelöst",
-  "components.PermissionEdit.viewissuesDescription": "Berechtigt, von andereren Nutzern gemeldete Medienprobleme zu sehen.",
-  "components.PermissionEdit.createissuesDescription": "Berechtigt, Medienprobleme zu melden.",
-  "components.PermissionEdit.manageissuesDescription": "Berechtigt, Medienprobleme zu verwalten.",
+  "components.PermissionEdit.viewissuesDescription": "Autorisierung zur Ansicht von Medienproblemen, die von anderen Benutzern gemeldet wurden.",
+  "components.PermissionEdit.createissuesDescription": "Autorisierung zur Meldung von Medienproblemen.",
+  "components.PermissionEdit.manageissuesDescription": "Autorisierung zur Verwaltung von Medienproblemen.",
   "components.NotificationTypeSelector.issuereopened": "Problem wiedereröffnet",
   "components.NotificationTypeSelector.userissuereopenedDescription": "Sende eine Benachrichtigung, wenn die von dir gemeldeten Probleme wieder geöffnet werden.",
   "components.MovieDetails.productioncountries": "Produktions {countryCount, plural, one {Land} other {Länder}}",
@@ -1040,5 +1029,41 @@
   "components.UserProfile.UserSettings.UserGeneralSettings.discordId": "Discord User ID",
   "components.UserProfile.UserSettings.UserGeneralSettings.validationDiscordId": "Du musst eine gültige Discord User ID angeben",
   "components.Settings.SettingsAbout.appDataPath": "Datenverzeichnis",
-  "components.UserProfile.UserSettings.UserGeneralSettings.discordIdTip": "Die <FindDiscordIdLink>mehrstellige ID-Nummer</FindDiscordIdLink> Deines Discord-Accounts"
+  "components.UserProfile.UserSettings.UserGeneralSettings.discordIdTip": "Die <FindDiscordIdLink>mehrstellige ID-Nummer</FindDiscordIdLink> Deines Discord-Accounts",
+  "components.RequestBlock.languageprofile": "Sprachprofil",
+  "components.MovieDetails.digitalrelease": "Digitale Veröffentlichung",
+  "components.MovieDetails.physicalrelease": "DVD/Bluray-Veröffentlichungen",
+  "components.MovieDetails.theatricalrelease": "Kinostart",
+  "components.StatusChecker.appUpdated": "{applicationTitle} aktualisiert",
+  "components.PermissionEdit.viewrecent": "Kürzlich hinzugefügt anzeigen",
+  "components.Settings.deleteServer": "{serverType} Server löschen",
+  "components.StatusChecker.reloadApp": "{applicationTitle} neu laden",
+  "components.StatusChecker.restartRequiredDescription": "Starte bitte den Server neu, um die aktualisierten Einstellungen zu übernehmen.",
+  "components.TitleCard.cleardata": "Daten löschen",
+  "components.TitleCard.tmdbid": "TMDB-ID",
+  "components.TitleCard.tvdbid": "TheTVDB-ID",
+  "components.Discover.DiscoverWatchlist.discoverwatchlist": "Deine Plex-Watchlist",
+  "components.Discover.plexwatchlist": "Deine Plex-Watchlist",
+  "components.PermissionEdit.autorequest": "Automatische Anfrage",
+  "components.PermissionEdit.autorequestSeries": "Auto-Anfrage-Serien",
+  "components.PermissionEdit.autorequestMoviesDescription": "Autorisierung zur automatischen Anfrage von Nicht-4K-Medien über die Plex Watchlist.",
+  "components.PermissionEdit.autorequestSeriesDescription": "Autorisierung der automatischen Anfrage von Nicht-4K-Serien über die Plex Watchlist.",
+  "components.PermissionEdit.autorequestDescription": "Autorisierung zur automatischen Anfrage von Nicht-4K-Medien über die Plex Watchlist.",
+  "components.PermissionEdit.viewrecentDescription": "Autorisierung zur Anzeige der Liste der kürzlich hinzugefügten Medien.",
+  "components.RequestList.RequestItem.tmdbid": "TMDB-ID",
+  "components.RequestList.RequestItem.tvdbid": "TheTVDB-ID",
+  "components.PermissionEdit.autorequestMovies": "Filme automatisch anfragen",
+  "components.Settings.SettingsJobsCache.plex-watchlist-sync": "Plex-Watchlist Sync",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmovies": "Filme automatisch anfragen",
+  "components.RequestCard.tmdbid": "TMDB-ID",
+  "components.RequestCard.tvdbid": "TheTVDB-ID",
+  "components.StatusChecker.appUpdatedDescription": "Klicke bitte auf die Schaltfläche unten, um die Anwendung neu zu laden.",
+  "components.StatusChecker.restartRequired": "Server Neustart erforderlich",
+  "components.TitleCard.mediaerror": "{mediaType} wurde nicht gefunden",
+  "i18n.restartRequired": "Neustart erforderlich",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseries": "Serien automatisch anfragen",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseriestip": "Automatisch Serien auf deiner <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink> anfragen",
+  "components.NotificationTypeSelector.mediaautorequestedDescription": "Erhalten eine Benachrichtigung, wenn neue Medienanfragen für Objekte auf deiner Plex Watchlist automatisch übermittelt werden.",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmoviestip": "Automatisch Filme auf deiner <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink> anfordern",
+  "components.NotificationTypeSelector.mediaautorequested": "Automatisch übermittelte Anfrage"
 }
diff --git a/src/i18n/locale/el.json b/src/i18n/locale/el.json
index d7e4d3c8..729ee427 100644
--- a/src/i18n/locale/el.json
+++ b/src/i18n/locale/el.json
@@ -1,7 +1,5 @@
 {
   "components.PermissionEdit.users": "Διαχείριση Χρηστών",
-  "components.PermissionEdit.settingsDescription": "Εκχώρηση άδειας για τροποποίηση των ρυθμίσεων Overseerr. Ένας χρήστης χρειάζεται να έχει αυτό το δικαίωμα για να το εκχωρήσει σε άλλους.",
-  "components.PermissionEdit.settings": "Διαχείριση Ρυθμίσεων",
   "components.PermissionEdit.requestTvDescription": "Εκχώρηση άδειας για αιτήματα που δεν είναι 4K σειρές.",
   "components.PermissionEdit.requestTv": "Αιτήματα για Σειρές",
   "components.PermissionEdit.requestMoviesDescription": "Εκχώρηση άδειας για αιτήματα που δεν είναι 4K ταινίες.",
@@ -116,7 +114,6 @@
   "components.Discover.recentrequests": "Πρόσφατα Αιτήματα",
   "components.Discover.recentlyAdded": "Προστέθηκαν πρόσφατα",
   "components.Discover.populartv": "Δημοφιλείς Σειρές",
-  "components.Discover.noRequests": "Δεν υπάρχουν αιτήματα.",
   "components.Settings.Notifications.NotificationsLunaSea.webhookUrl": "Webhook URL",
   "components.Settings.Notifications.NotificationsLunaSea.validationWebhookUrl": "Πρέπει να βάλεις μια έγκυρη διεύθυνση URL",
   "components.Settings.Notifications.NotificationsLunaSea.toastLunaSeaTestSuccess": "Η δοκιμαστική ειδοποίηση LunaSea εστάλη!",
@@ -145,7 +142,6 @@
   "components.RequestModal.selectseason": "Επιλογή Σεζόν",
   "components.RequestModal.seasonnumber": "Σεζόν {number}",
   "components.RequestModal.season": "Σεζόν",
-  "components.RequestModal.requesttitle": "Ζήτα {title}",
   "components.RequestModal.requestseasons": "Ζήτα {seasonCount} {seasonCount, plural, one {Σεζόν} other {Σεζόν}}",
   "components.RequestModal.requestfrom": "Το αίτημα του/της {username} εκκρεμεί προς έγκριση.",
   "components.RequestModal.requesterror": "Κάτι πήγε στραβά κατά την υποβολή του αιτήματος.",
@@ -154,17 +150,15 @@
   "components.RequestModal.requestadmin": "Αυτό το αίτημα θα εγκριθεί αυτόματα.",
   "components.RequestModal.requestSuccess": "<strong>{title}</strong> ζητήθηκε επιτυχώς!",
   "components.RequestModal.requestCancel": "Το αίτημα για <strong>{title}</strong> ακυρώθηκε.",
-  "components.RequestModal.request4ktitle": "Ζήτα {title} σε 4K",
-  "components.RequestModal.pendingrequest": "Εκκρεμές Αίτημα για {title}",
+  "components.RequestModal.pendingrequest": "",
   "components.RequestModal.pendingapproval": "Το αίτημα σου εκκρεμεί προς έγκριση.",
-  "components.RequestModal.pending4krequest": "Εκκρεμές 4K Αίτημα για {title}",
+  "components.RequestModal.pending4krequest": "",
   "components.RequestModal.errorediting": "Κάτι πήγε στραβά κατά την επεξεργασία του αιτήματος.",
   "components.RequestModal.edit": "Επεξεργασία Αιτήματος",
   "components.RequestModal.cancel": "Ακύρωση Αιτήματος",
   "components.RequestModal.autoapproval": "Αυτόματη Έγκριση",
   "components.RequestModal.alreadyrequested": "Έχει ήδη ζητηθεί",
   "components.RequestModal.SearchByNameModal.notvdbiddescription": "Δεν μπορέσαμε να αντιστοιχίσουμε αυτόματα το αίτημά σου. Παρακαλώ επίλεξε τη σωστή αντιστοιχία από την παρακάτω λίστα.",
-  "components.RequestModal.SearchByNameModal.nosummary": "Δεν βρέθηκε περίληψη για αυτόν τον τίτλο.",
   "components.RequestModal.QuotaDisplay.seasonlimit": "{limit, plural, one {σεζόν} other {σεζόν}}",
   "components.RequestModal.QuotaDisplay.season": "σεζόν",
   "components.RequestModal.QuotaDisplay.requiredquotaUser": "Αυτός ο χρήστης χρειάζεται τουλάχιστον <strong>{seasons}</strong> {seasons, plural, one {αίτημα σεζόν} other {αιτήματα σεζόν}} απομένουν έτσι ώστε να γίνει αίτημα για αυτή τη σειρά.",
@@ -500,7 +494,6 @@
   "components.UserProfile.requestsperdays": "Απομένει {limit}",
   "components.UserProfile.recentrequests": "Πρόσφατα Αιτήματα",
   "components.UserProfile.pastdays": "{type} (περασμένες {days} ημέρες)",
-  "components.UserProfile.norequests": "Δεν υπάρχουν αιτήματα.",
   "components.UserProfile.movierequests": "Αιτήματα Ταινιών",
   "components.UserProfile.limit": "{remaining} από {limit}",
   "components.UserProfile.UserSettings.UserPasswordChange.nopermissionDescription": "Δεν έχεις άδεια να τροποποιήσεις τον κωδικό πρόσβασης αυτού του χρήστη.",
@@ -636,9 +629,6 @@
   "components.TvDetails.anime": "Anime",
   "components.TvDetails.TvCrew.fullseriescrew": "Όλο το Πλήρωμα της Σειράς",
   "components.TvDetails.TvCast.fullseriescast": "Όλοι οι Ηθοποιοί της Σειράς",
-  "components.StatusChacker.reloadOverseerr": "Επαναφόρτωση",
-  "components.StatusChacker.newversionavailable": "Ενημέρωση εφαρμογής",
-  "components.StatusChacker.newversionDescription": "Το Overseerr έχει ενημερωθεί! Κάνε κλικ στο παρακάτω κουμπί για να φορτώσει ξανά η σελίδα.",
   "components.StatusBadge.status4k": "4K {status}",
   "components.Setup.welcome": "Καλώς ήρθες στο Overseerr",
   "components.Setup.tip": "Συμβουλή",
@@ -659,7 +649,7 @@
   "components.Settings.validationApplicationUrlTrailingSlash": "Η διεύθυνση URL δεν πρέπει να τελειώνει με κάθετο",
   "components.Settings.validationApplicationUrl": "Πρέπει να βάλεις μια έγκυρη διεύθυνση URL",
   "components.Settings.validationApplicationTitle": "Πρέπει να δώσεις έναν τίτλο εφαρμογής",
-  "components.Settings.trustProxyTip": "Επίτρεψε στο Overseerr να καταχωρίζει σωστά τις διευθύνσεις IP του πελάτη πίσω από έναν διακομιστή μεσολάβησης (το Overseerr πρέπει να φορτωθεί ξανά για να εφαρμοστούν οι αλλαγές)",
+  "components.Settings.trustProxyTip": "Επίτρεψε στο Overseerr να καταχωρίζει σωστά τις διευθύνσεις IP του πελάτη πίσω από έναν διακομιστή μεσολάβησης",
   "components.Settings.trustProxy": "Ενεργοποίηση υποστήριξης διαμεσολαβητή",
   "components.Settings.toastSettingsSuccess": "Οι ρυθμίσεις αποθηκεύτηκαν με επιτυχία!",
   "components.Settings.toastSettingsFailure": "Κάτι πήγε στραβά κατά την αποθήκευση των ρυθμίσεων.",
@@ -730,7 +720,7 @@
   "components.Settings.default4k": "Προεπιλεγμένο 4K",
   "components.Settings.default": "Προκαθορισμένο",
   "components.Settings.currentlibrary": "Τρέχουσα βιβλιοθήκη: {name}",
-  "components.Settings.csrfProtectionTip": "Ορισμός εξωτερικής πρόσβασης API σε μόνο για ανάγνωση (απαιτείται HTTPS και το Overseerr πρέπει να φορτωθεί ξανά για να εφαρμοστούν οι αλλαγές)",
+  "components.Settings.csrfProtectionTip": "Ορισμός εξωτερικής πρόσβασης API σε μόνο για ανάγνωση (απαιτείται HTTPS)",
   "components.Settings.csrfProtectionHoverTip": "ΜΗΝ ενεργοποιήσεις αυτή τη ρύθμιση αν δεν καταλαβαίνεις τι κάνεις!",
   "components.Settings.csrfProtection": "Ενεργοποίηση της προστασίας CSRF",
   "components.Settings.copied": "Αντιγράφηκε το κλειδί API στο πρόχειρο.",
diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json
index 6bcb3932..7e4cfa6e 100644
--- a/src/i18n/locale/en.json
+++ b/src/i18n/locale/en.json
@@ -1,4 +1,6 @@
 {
+  "components.AirDateBadge.airedrelative": "Aired {relativeTime}",
+  "components.AirDateBadge.airsrelative": "Airing {relativeTime}",
   "components.AppDataWarning.dockerVolumeMissingDescription": "The <code>{appDataPath}</code> volume mount was not configured properly. All data will be cleared when the container is stopped or restarted.",
   "components.CollectionDetails.numberofmovies": "{count} Movies",
   "components.CollectionDetails.overview": "Overview",
@@ -10,6 +12,8 @@
   "components.Discover.DiscoverStudio.studioMovies": "{studio} Movies",
   "components.Discover.DiscoverTvGenre.genreSeries": "{genre} Series",
   "components.Discover.DiscoverTvLanguage.languageSeries": "{language} Series",
+  "components.Discover.DiscoverWatchlist.discoverwatchlist": "Your Plex Watchlist",
+  "components.Discover.DiscoverWatchlist.watchlist": "Plex Watchlist",
   "components.Discover.MovieGenreList.moviegenres": "Movie Genres",
   "components.Discover.MovieGenreSlider.moviegenres": "Movie Genres",
   "components.Discover.NetworkSlider.networks": "Networks",
@@ -19,7 +23,8 @@
   "components.Discover.discover": "Discover",
   "components.Discover.discovermovies": "Popular Movies",
   "components.Discover.discovertv": "Popular Series",
-  "components.Discover.noRequests": "No requests.",
+  "components.Discover.emptywatchlist": "Media added to your <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink> will appear here.",
+  "components.Discover.plexwatchlist": "Your Plex Watchlist",
   "components.Discover.popularmovies": "Popular Movies",
   "components.Discover.populartv": "Popular Series",
   "components.Discover.recentlyAdded": "Recently Added",
@@ -86,7 +91,6 @@
   "components.IssueModal.CreateIssueModal.allseasons": "All Seasons",
   "components.IssueModal.CreateIssueModal.episode": "Episode {episodeNumber}",
   "components.IssueModal.CreateIssueModal.extras": "Extras",
-  "components.IssueModal.CreateIssueModal.issomethingwrong": "Is there a problem with {title}?",
   "components.IssueModal.CreateIssueModal.problemepisode": "Affected Episode",
   "components.IssueModal.CreateIssueModal.problemseason": "Affected Season",
   "components.IssueModal.CreateIssueModal.providedetail": "Please provide a detailed explanation of the issue you encountered.",
@@ -111,7 +115,10 @@
   "components.Layout.Sidebar.requests": "Requests",
   "components.Layout.Sidebar.settings": "Settings",
   "components.Layout.Sidebar.users": "Users",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.movierequests": "Movie Requests",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.seriesrequests": "Series Requests",
   "components.Layout.UserDropdown.myprofile": "Profile",
+  "components.Layout.UserDropdown.requests": "Requests",
   "components.Layout.UserDropdown.settings": "Settings",
   "components.Layout.UserDropdown.signout": "Sign Out",
   "components.Layout.VersionStatus.commitsbehind": "{commitsBehind} {commitsBehind, plural, one {commit} other {commits}} behind",
@@ -157,24 +164,32 @@
   "components.MovieDetails.MovieCrew.fullcrew": "Full Crew",
   "components.MovieDetails.budget": "Budget",
   "components.MovieDetails.cast": "Cast",
+  "components.MovieDetails.digitalrelease": "Digital Release",
+  "components.MovieDetails.managemovie": "Manage Movie",
   "components.MovieDetails.mark4kavailable": "Mark as Available in 4K",
   "components.MovieDetails.markavailable": "Mark as Available",
   "components.MovieDetails.originallanguage": "Original Language",
   "components.MovieDetails.originaltitle": "Original Title",
   "components.MovieDetails.overview": "Overview",
   "components.MovieDetails.overviewunavailable": "Overview unavailable.",
+  "components.MovieDetails.physicalrelease": "Physical Release",
   "components.MovieDetails.play4konplex": "Play in 4K on Plex",
   "components.MovieDetails.playonplex": "Play on Plex",
   "components.MovieDetails.productioncountries": "Production {countryCount, plural, one {Country} other {Countries}}",
   "components.MovieDetails.recommendations": "Recommendations",
   "components.MovieDetails.releasedate": "{releaseCount, plural, one {Release Date} other {Release Dates}}",
+  "components.MovieDetails.reportissue": "Report an Issue",
   "components.MovieDetails.revenue": "Revenue",
+  "components.MovieDetails.rtaudiencescore": "Rotten Tomatoes Audience Score",
+  "components.MovieDetails.rtcriticsscore": "Rotten Tomatoes Tomatometer",
   "components.MovieDetails.runtime": "{minutes} minutes",
   "components.MovieDetails.showless": "Show Less",
   "components.MovieDetails.showmore": "Show More",
   "components.MovieDetails.similar": "Similar Titles",
   "components.MovieDetails.streamingproviders": "Currently Streaming On",
   "components.MovieDetails.studio": "{studioCount, plural, one {Studio} other {Studios}}",
+  "components.MovieDetails.theatricalrelease": "Theatrical Release",
+  "components.MovieDetails.tmdbuserscore": "TMDB User Score",
   "components.MovieDetails.viewfullcrew": "View Full Crew",
   "components.MovieDetails.watchtrailer": "Watch Trailer",
   "components.NotificationTypeSelector.adminissuecommentDescription": "Get notified when other users comment on issues.",
@@ -192,6 +207,8 @@
   "components.NotificationTypeSelector.mediaAutoApprovedDescription": "Send notifications when users submit new media requests which are automatically approved.",
   "components.NotificationTypeSelector.mediaapproved": "Request Approved",
   "components.NotificationTypeSelector.mediaapprovedDescription": "Send notifications when media requests are manually approved.",
+  "components.NotificationTypeSelector.mediaautorequested": "Request Automatically Submitted",
+  "components.NotificationTypeSelector.mediaautorequestedDescription": "Get notified when new media requests are automatically submitted for items on your Plex Watchlist.",
   "components.NotificationTypeSelector.mediaavailable": "Request Available",
   "components.NotificationTypeSelector.mediaavailableDescription": "Send notifications when media requests become available.",
   "components.NotificationTypeSelector.mediadeclined": "Request Declined",
@@ -227,6 +244,12 @@
   "components.PermissionEdit.autoapproveMoviesDescription": "Grant automatic approval for non-4K movie requests.",
   "components.PermissionEdit.autoapproveSeries": "Auto-Approve Series",
   "components.PermissionEdit.autoapproveSeriesDescription": "Grant automatic approval for non-4K series requests.",
+  "components.PermissionEdit.autorequest": "Auto-Request",
+  "components.PermissionEdit.autorequestDescription": "Grant permission to automatically submit requests for non-4K media via Plex Watchlist.",
+  "components.PermissionEdit.autorequestMovies": "Auto-Request Movies",
+  "components.PermissionEdit.autorequestMoviesDescription": "Grant permission to automatically submit requests for non-4K movies via Plex Watchlist.",
+  "components.PermissionEdit.autorequestSeries": "Auto-Request Series",
+  "components.PermissionEdit.autorequestSeriesDescription": "Grant permission to automatically submit requests for non-4K series via Plex Watchlist.",
   "components.PermissionEdit.createissues": "Report Issues",
   "components.PermissionEdit.createissuesDescription": "Grant permission to report media issues.",
   "components.PermissionEdit.manageissues": "Manage Issues",
@@ -245,14 +268,16 @@
   "components.PermissionEdit.requestMoviesDescription": "Grant permission to submit requests for non-4K movies.",
   "components.PermissionEdit.requestTv": "Request Series",
   "components.PermissionEdit.requestTvDescription": "Grant permission to submit requests for non-4K series.",
-  "components.PermissionEdit.settings": "Manage Settings",
-  "components.PermissionEdit.settingsDescription": "Grant permission to modify global settings. A user must have this permission to grant it to others.",
   "components.PermissionEdit.users": "Manage Users",
   "components.PermissionEdit.usersDescription": "Grant permission to manage users. Users with this permission cannot modify users with or grant the Admin privilege.",
   "components.PermissionEdit.viewissues": "View Issues",
   "components.PermissionEdit.viewissuesDescription": "Grant permission to view media issues reported by other users.",
+  "components.PermissionEdit.viewrecent": "View Recently Added",
+  "components.PermissionEdit.viewrecentDescription": "Grant permission to view the list of recently added media.",
   "components.PermissionEdit.viewrequests": "View Requests",
   "components.PermissionEdit.viewrequestsDescription": "Grant permission to view media requests submitted by other users.",
+  "components.PermissionEdit.viewwatchlists": "View Plex Watchlists",
+  "components.PermissionEdit.viewwatchlistsDescription": "Grant permission to view other users' Plex Watchlists.",
   "components.PersonDetails.alsoknownas": "Also Known As: {names}",
   "components.PersonDetails.appearsin": "Appearances",
   "components.PersonDetails.ascharacter": "as {character}",
@@ -269,7 +294,15 @@
   "components.QuotaSelector.unlimited": "Unlimited",
   "components.RegionSelector.regionDefault": "All Regions",
   "components.RegionSelector.regionServerDefault": "Default ({region})",
+  "components.RequestBlock.approve": "Approve Request",
+  "components.RequestBlock.decline": "Decline Request",
+  "components.RequestBlock.delete": "Delete Request",
+  "components.RequestBlock.edit": "Edit Request",
+  "components.RequestBlock.languageprofile": "Language Profile",
+  "components.RequestBlock.lastmodifiedby": "Last Modified By",
   "components.RequestBlock.profilechanged": "Quality Profile",
+  "components.RequestBlock.requestdate": "Request Date",
+  "components.RequestBlock.requestedby": "Requested By",
   "components.RequestBlock.requestoverrides": "Request Overrides",
   "components.RequestBlock.rootfolder": "Root Folder",
   "components.RequestBlock.seasons": "{seasonCount, plural, one {Season} other {Seasons}}",
@@ -286,20 +319,28 @@
   "components.RequestButton.requestmore4k": "Request More in 4K",
   "components.RequestButton.viewrequest": "View Request",
   "components.RequestButton.viewrequest4k": "View 4K Request",
+  "components.RequestCard.approverequest": "Approve Request",
+  "components.RequestCard.cancelrequest": "Cancel Request",
+  "components.RequestCard.declinerequest": "Decline Request",
   "components.RequestCard.deleterequest": "Delete Request",
+  "components.RequestCard.editrequest": "Edit Request",
   "components.RequestCard.failedretry": "Something went wrong while retrying the request.",
-  "components.RequestCard.mediaerror": "The associated title for this request is no longer available.",
+  "components.RequestCard.mediaerror": "{mediaType} Not Found",
   "components.RequestCard.seasons": "{seasonCount, plural, one {Season} other {Seasons}}",
+  "components.RequestCard.tmdbid": "TMDB ID",
+  "components.RequestCard.tvdbid": "TheTVDB ID",
   "components.RequestList.RequestItem.cancelRequest": "Cancel Request",
   "components.RequestList.RequestItem.deleterequest": "Delete Request",
   "components.RequestList.RequestItem.editrequest": "Edit Request",
   "components.RequestList.RequestItem.failedretry": "Something went wrong while retrying the request.",
-  "components.RequestList.RequestItem.mediaerror": "The associated title for this request is no longer available.",
+  "components.RequestList.RequestItem.mediaerror": "{mediaType} Not Found",
   "components.RequestList.RequestItem.modified": "Modified",
   "components.RequestList.RequestItem.modifieduserdate": "{date} by {user}",
   "components.RequestList.RequestItem.requested": "Requested",
   "components.RequestList.RequestItem.requesteddate": "Requested",
   "components.RequestList.RequestItem.seasons": "{seasonCount, plural, one {Season} other {Seasons}}",
+  "components.RequestList.RequestItem.tmdbid": "TMDB ID",
+  "components.RequestList.RequestItem.tvdbid": "TheTVDB ID",
   "components.RequestList.requests": "Requests",
   "components.RequestList.showallrequests": "Show All Requests",
   "components.RequestList.sortAdded": "Most Recent",
@@ -328,8 +369,8 @@
   "components.RequestModal.QuotaDisplay.requiredquotaUser": "This user needs to have at least <strong>{seasons}</strong> {seasons, plural, one {season request} other {season requests}} remaining in order to submit a request for this series.",
   "components.RequestModal.QuotaDisplay.season": "season",
   "components.RequestModal.QuotaDisplay.seasonlimit": "{limit, plural, one {season} other {seasons}}",
-  "components.RequestModal.SearchByNameModal.nosummary": "No summary for this title was found.",
-  "components.RequestModal.SearchByNameModal.notvdbiddescription": "We couldn't automatically match your request. Please select the correct match from the list below.",
+  "components.RequestModal.SearchByNameModal.nomatches": "We were unable to find a match for this series.",
+  "components.RequestModal.SearchByNameModal.notvdbiddescription": "We were unable to automatically match this series. Please select the correct match below.",
   "components.RequestModal.alreadyrequested": "Already Requested",
   "components.RequestModal.approve": "Approve Request",
   "components.RequestModal.autoapproval": "Automatic Approval",
@@ -338,23 +379,27 @@
   "components.RequestModal.errorediting": "Something went wrong while editing the request.",
   "components.RequestModal.extras": "Extras",
   "components.RequestModal.numberofepisodes": "# of Episodes",
-  "components.RequestModal.pending4krequest": "Pending 4K Request for {title}",
+  "components.RequestModal.pending4krequest": "Pending 4K Request",
   "components.RequestModal.pendingapproval": "Your request is pending approval.",
-  "components.RequestModal.pendingrequest": "Pending Request for {title}",
-  "components.RequestModal.request4ktitle": "Request {title} in 4K",
+  "components.RequestModal.pendingrequest": "Pending Request",
   "components.RequestModal.requestApproved": "Request for <strong>{title}</strong> approved!",
   "components.RequestModal.requestCancel": "Request for <strong>{title}</strong> canceled.",
   "components.RequestModal.requestSuccess": "<strong>{title}</strong> requested successfully!",
   "components.RequestModal.requestadmin": "This request will be approved automatically.",
   "components.RequestModal.requestcancelled": "Request for <strong>{title}</strong> canceled.",
+  "components.RequestModal.requestcollection4ktitle": "Request Collection in 4K",
+  "components.RequestModal.requestcollectiontitle": "Request Collection",
   "components.RequestModal.requestedited": "Request for <strong>{title}</strong> edited successfully!",
   "components.RequestModal.requesterror": "Something went wrong while submitting the request.",
   "components.RequestModal.requestfrom": "{username}'s request is pending approval.",
+  "components.RequestModal.requestmovie4ktitle": "Request Movie in 4K",
   "components.RequestModal.requestmovies": "Request {count} {count, plural, one {Movie} other {Movies}}",
   "components.RequestModal.requestmovies4k": "Request {count} {count, plural, one {Movie} other {Movies}} in 4K",
+  "components.RequestModal.requestmovietitle": "Request Movie",
   "components.RequestModal.requestseasons": "Request {seasonCount} {seasonCount, plural, one {Season} other {Seasons}}",
   "components.RequestModal.requestseasons4k": "Request {seasonCount} {seasonCount, plural, one {Season} other {Seasons}} in 4K",
-  "components.RequestModal.requesttitle": "Request {title}",
+  "components.RequestModal.requestseries4ktitle": "Request Series in 4K",
+  "components.RequestModal.requestseriestitle": "Request Series",
   "components.RequestModal.season": "Season",
   "components.RequestModal.seasonnumber": "Season {number}",
   "components.RequestModal.selectmovies": "Select Movie(s)",
@@ -594,7 +639,8 @@
   "components.Settings.SettingsJobsCache.download-sync": "Download Sync",
   "components.Settings.SettingsJobsCache.download-sync-reset": "Download Sync Reset",
   "components.Settings.SettingsJobsCache.editJobSchedule": "Modify Job",
-  "components.Settings.SettingsJobsCache.editJobSchedulePrompt": "Frequency",
+  "components.Settings.SettingsJobsCache.editJobScheduleCurrent": "Current Frequency",
+  "components.Settings.SettingsJobsCache.editJobSchedulePrompt": "New Frequency",
   "components.Settings.SettingsJobsCache.editJobScheduleSelectorHours": "Every {jobScheduleHours, plural, one {hour} other {{jobScheduleHours} hours}}",
   "components.Settings.SettingsJobsCache.editJobScheduleSelectorMinutes": "Every {jobScheduleMinutes, plural, one {minute} other {{jobScheduleMinutes} minutes}}",
   "components.Settings.SettingsJobsCache.flushcache": "Flush Cache",
@@ -610,6 +656,7 @@
   "components.Settings.SettingsJobsCache.nextexecution": "Next Execution",
   "components.Settings.SettingsJobsCache.plex-full-scan": "Plex Full Library Scan",
   "components.Settings.SettingsJobsCache.plex-recently-added-scan": "Plex Recently Added Scan",
+  "components.Settings.SettingsJobsCache.plex-watchlist-sync": "Plex Watchlist Sync",
   "components.Settings.SettingsJobsCache.process": "Process",
   "components.Settings.SettingsJobsCache.radarr-scan": "Radarr Scan",
   "components.Settings.SettingsJobsCache.runnow": "Run Now",
@@ -632,6 +679,7 @@
   "components.Settings.SettingsLogs.resumeLogs": "Resume",
   "components.Settings.SettingsLogs.showall": "Show All Logs",
   "components.Settings.SettingsLogs.time": "Timestamp",
+  "components.Settings.SettingsLogs.viewdetails": "View Details",
   "components.Settings.SettingsUsers.defaultPermissions": "Default Permissions",
   "components.Settings.SettingsUsers.defaultPermissionsTip": "Initial permissions assigned to new users",
   "components.Settings.SettingsUsers.localLogin": "Enable Local Sign-In",
@@ -701,22 +749,25 @@
   "components.Settings.addradarr": "Add Radarr Server",
   "components.Settings.address": "Address",
   "components.Settings.addsonarr": "Add Sonarr Server",
+  "components.Settings.advancedTooltip": "Incorrectly configuring this setting may result in broken functionality",
   "components.Settings.apikey": "API Key",
   "components.Settings.applicationTitle": "Application Title",
   "components.Settings.applicationurl": "Application URL",
   "components.Settings.cacheImages": "Enable Image Caching",
-  "components.Settings.cacheImagesTip": "Optimize and store all images locally (consumes a significant amount of disk space)",
+  "components.Settings.cacheImagesTip": "Cache and serve optimized images (requires a significant amount of disk space)",
   "components.Settings.cancelscan": "Cancel Scan",
   "components.Settings.copied": "Copied API key to clipboard.",
   "components.Settings.csrfProtection": "Enable CSRF Protection",
   "components.Settings.csrfProtectionHoverTip": "Do NOT enable this setting unless you understand what you are doing!",
-  "components.Settings.csrfProtectionTip": "Set external API access to read-only (requires HTTPS, and Overseerr must be reloaded for changes to take effect)",
+  "components.Settings.csrfProtectionTip": "Set external API access to read-only (requires HTTPS)",
   "components.Settings.currentlibrary": "Current Library: {name}",
   "components.Settings.default": "Default",
   "components.Settings.default4k": "Default 4K",
+  "components.Settings.deleteServer": "Delete {serverType} Server",
   "components.Settings.deleteserverconfirm": "Are you sure you want to delete this server?",
   "components.Settings.email": "Email",
   "components.Settings.enablessl": "Use SSL",
+  "components.Settings.experimentalTooltip": "Enabling this setting may result in unexpected application behavior",
   "components.Settings.externalUrl": "External URL",
   "components.Settings.general": "General",
   "components.Settings.generalsettings": "General Settings",
@@ -757,6 +808,7 @@
   "components.Settings.radarrsettings": "Radarr Settings",
   "components.Settings.region": "Discover Region",
   "components.Settings.regionTip": "Filter content by regional availability",
+  "components.Settings.restartrequiredTooltip": "Overseerr must be restarted for changes to this setting to take effect",
   "components.Settings.scan": "Sync Libraries",
   "components.Settings.scanning": "Syncing…",
   "components.Settings.serverLocal": "local",
@@ -788,7 +840,7 @@
   "components.Settings.toastTautulliSettingsFailure": "Something went wrong while saving Tautulli settings.",
   "components.Settings.toastTautulliSettingsSuccess": "Tautulli settings saved successfully!",
   "components.Settings.trustProxy": "Enable Proxy Support",
-  "components.Settings.trustProxyTip": "Allow Overseerr to correctly register client IP addresses behind a proxy (Overseerr must be reloaded for changes to take effect)",
+  "components.Settings.trustProxyTip": "Allow Overseerr to correctly register client IP addresses behind a proxy",
   "components.Settings.urlBase": "URL Base",
   "components.Settings.validationApiKey": "You must provide an API key",
   "components.Settings.validationApplicationTitle": "You must provide an application title",
@@ -815,18 +867,30 @@
   "components.Setup.signinMessage": "Get started by signing in with your Plex account",
   "components.Setup.tip": "Tip",
   "components.Setup.welcome": "Welcome to Overseerr",
+  "components.StatusBadge.managemedia": "Manage {mediaType}",
+  "components.StatusBadge.openinarr": "Open in {arr}",
+  "components.StatusBadge.playonplex": "Play on Plex",
   "components.StatusBadge.status": "{status}",
   "components.StatusBadge.status4k": "4K {status}",
-  "components.StatusChacker.newversionDescription": "Overseerr has been updated! Please click the button below to reload the page.",
-  "components.StatusChacker.newversionavailable": "Application Update",
-  "components.StatusChacker.reloadOverseerr": "Reload",
+  "components.StatusChecker.appUpdated": "{applicationTitle} Updated",
+  "components.StatusChecker.appUpdatedDescription": "Please click the button below to reload the application.",
+  "components.StatusChecker.reloadApp": "Reload {applicationTitle}",
+  "components.StatusChecker.restartRequired": "Server Restart Required",
+  "components.StatusChecker.restartRequiredDescription": "Please restart the server to apply the updated settings.",
+  "components.TitleCard.cleardata": "Clear Data",
+  "components.TitleCard.mediaerror": "{mediaType} Not Found",
+  "components.TitleCard.tmdbid": "TMDB ID",
+  "components.TitleCard.tvdbid": "TheTVDB ID",
+  "components.TvDetails.Season.somethingwentwrong": "Something went wrong while retrieving season data.",
   "components.TvDetails.TvCast.fullseriescast": "Full Series Cast",
   "components.TvDetails.TvCrew.fullseriescrew": "Full Series Crew",
   "components.TvDetails.anime": "Anime",
   "components.TvDetails.cast": "Cast",
+  "components.TvDetails.episodeCount": "{episodeCount, plural, one {# Episode} other {# Episodes}}",
   "components.TvDetails.episodeRuntime": "Episode Runtime",
   "components.TvDetails.episodeRuntimeMinutes": "{runtime} minutes",
   "components.TvDetails.firstAirDate": "First Air Date",
+  "components.TvDetails.manageseries": "Manage Series",
   "components.TvDetails.network": "{networkCount, plural, one {Network} other {Networks}}",
   "components.TvDetails.nextAirDate": "Next Air Date",
   "components.TvDetails.originallanguage": "Original Language",
@@ -837,10 +901,17 @@
   "components.TvDetails.playonplex": "Play on Plex",
   "components.TvDetails.productioncountries": "Production {countryCount, plural, one {Country} other {Countries}}",
   "components.TvDetails.recommendations": "Recommendations",
+  "components.TvDetails.reportissue": "Report an Issue",
+  "components.TvDetails.rtaudiencescore": "Rotten Tomatoes Audience Score",
+  "components.TvDetails.rtcriticsscore": "Rotten Tomatoes Tomatometer",
+  "components.TvDetails.seasonnumber": "Season {seasonNumber}",
   "components.TvDetails.seasons": "{seasonCount, plural, one {# Season} other {# Seasons}}",
+  "components.TvDetails.seasonstitle": "Seasons",
   "components.TvDetails.showtype": "Series Type",
   "components.TvDetails.similar": "Similar Series",
+  "components.TvDetails.status4k": "4K {status}",
   "components.TvDetails.streamingproviders": "Currently Streaming On",
+  "components.TvDetails.tmdbuserscore": "TMDB User Score",
   "components.TvDetails.viewfullcrew": "View Full Crew",
   "components.TvDetails.watchtrailer": "Watch Trailer",
   "components.UserList.accounttype": "Type",
@@ -905,6 +976,10 @@
   "components.UserProfile.UserSettings.UserGeneralSettings.originallanguageTip": "Filter content by original language",
   "components.UserProfile.UserSettings.UserGeneralSettings.owner": "Owner",
   "components.UserProfile.UserSettings.UserGeneralSettings.plexuser": "Plex User",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmovies": "Auto-Request Movies",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmoviestip": "Automatically request movies on your <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink>",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseries": "Auto-Request Series",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseriestip": "Automatically request series on your <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink>",
   "components.UserProfile.UserSettings.UserGeneralSettings.region": "Discover Region",
   "components.UserProfile.UserSettings.UserGeneralSettings.regionTip": "Filter content by regional availability",
   "components.UserProfile.UserSettings.UserGeneralSettings.role": "Role",
@@ -973,10 +1048,11 @@
   "components.UserProfile.UserSettings.menuNotifications": "Notifications",
   "components.UserProfile.UserSettings.menuPermissions": "Permissions",
   "components.UserProfile.UserSettings.unauthorizedDescription": "You do not have permission to modify this user's settings.",
+  "components.UserProfile.emptywatchlist": "Media added to your <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink> will appear here.",
   "components.UserProfile.limit": "{remaining} of {limit}",
   "components.UserProfile.movierequests": "Movie Requests",
-  "components.UserProfile.norequests": "No requests.",
   "components.UserProfile.pastdays": "{type} (past {days} days)",
+  "components.UserProfile.plexwatchlist": "Plex Watchlist",
   "components.UserProfile.recentlywatched": "Recently Watched",
   "components.UserProfile.recentrequests": "Recent Requests",
   "components.UserProfile.requestsperdays": "{limit} remaining",
@@ -1019,6 +1095,7 @@
   "i18n.requested": "Requested",
   "i18n.requesting": "Requesting…",
   "i18n.resolved": "Resolved",
+  "i18n.restartRequired": "Restart Required",
   "i18n.resultsperpage": "Display {pageSize} results per page",
   "i18n.retry": "Retry",
   "i18n.retrying": "Retrying…",
diff --git a/src/i18n/locale/es.json b/src/i18n/locale/es.json
index 753daab0..a8602254 100644
--- a/src/i18n/locale/es.json
+++ b/src/i18n/locale/es.json
@@ -63,13 +63,12 @@
   "components.RequestModal.selectseason": "Seleccionar Temporada(s)",
   "components.RequestModal.seasonnumber": "Temporada {number}",
   "components.RequestModal.season": "Temporada",
-  "components.RequestModal.requesttitle": "Solicitar {title}",
   "components.RequestModal.requestseasons": "Solicitar {seasonCount} {seasonCount, plural, one {Temporada} other {Temporadas}}",
   "components.RequestModal.requestfrom": "La solicitud de {username} está pendiente de aprobación.",
   "components.RequestModal.requestadmin": "Esta solicitud será aprobada automáticamente.",
   "components.RequestModal.requestSuccess": "¡<strong>{title}</strong> solicitada con éxito!",
   "components.RequestModal.requestCancel": "Solicitud para <strong>{title}</strong> cancelada.",
-  "components.RequestModal.pendingrequest": "Solicitud pendiente para {title}",
+  "components.RequestModal.pendingrequest": "Solicitud pendiente",
   "components.RequestModal.numberofepisodes": "# de Episodios",
   "components.RequestModal.extras": "Extras",
   "components.RequestModal.cancel": "Cancelar Petición",
@@ -246,9 +245,6 @@
   "components.RequestList.RequestItem.failedretry": "Algo salió mal al reintentar la solicitud.",
   "components.MovieDetails.watchtrailer": "Ver Trailer",
   "components.NotificationTypeSelector.mediarequestedDescription": "Envía una notificación cuando se solicita nuevo contenido que requiere ser aprobado.",
-  "components.StatusChacker.reloadOverseerr": "Recargar",
-  "components.StatusChacker.newversionavailable": "Actualización de Aplicación",
-  "components.StatusChacker.newversionDescription": "¡Overseerr se ha actualizado!Haga clic en el botón de abajo para volver a cargar la aplicación.",
   "components.Settings.SettingsAbout.documentation": "Documentación",
   "components.Settings.Notifications.validationChatIdRequired": "Debes proporcionar un ID de chat válido",
   "components.Settings.Notifications.validationBotAPIRequired": "Debes proporcionar un token de autorización del bot",
@@ -301,8 +297,7 @@
   "components.Settings.Notifications.NotificationsWebhook.agentenabled": "Habilitar Agente",
   "components.RequestModal.requestedited": "¡Solicitud para <strong>{title}</strong> modificada con éxito!",
   "components.RequestModal.requestcancelled": "Solicitud para <strong>{title}</strong> cancelada.",
-  "components.RequestModal.request4ktitle": "Solicitar {title} en 4K",
-  "components.RequestModal.pending4krequest": "Solicitud pendiente en 4K para {title}",
+  "components.RequestModal.pending4krequest": "Solicitud pendiente en 4K",
   "components.RequestModal.errorediting": "Algo salió mal al editar la solicitud.",
   "components.RequestModal.AdvancedRequester.rootfolder": "Carpeta Raíz",
   "components.RequestModal.AdvancedRequester.qualityprofile": "Perfil de calidad",
@@ -361,7 +356,6 @@
   "components.ResetPassword.confirmpassword": "Confirmar Contraseña",
   "components.RequestModal.requesterror": "Algo fue mal al realizar la solicitud.",
   "components.RequestModal.SearchByNameModal.notvdbiddescription": "No hemos podido emparejar automáticamente tu solicitud. Por favor, selecciona el correcto de la lista.",
-  "components.RequestModal.SearchByNameModal.nosummary": "No se ha encontrado un resumen para este título.",
   "components.RequestModal.AdvancedRequester.requestas": "Pedir como",
   "components.RequestModal.AdvancedRequester.languageprofile": "Perfil de Idioma",
   "components.RequestModal.AdvancedRequester.folder": "{path} ({space})",
@@ -374,8 +368,6 @@
   "components.PermissionEdit.viewrequests": "Ver Solicitudes",
   "components.PermissionEdit.usersDescription": "Concede permisos para gestionar usuarios. Los usuarios con este permiso no pueden modificar usuarios o conceder privilegios de Administrador.",
   "components.PermissionEdit.users": "Gestión de Usuarios",
-  "components.PermissionEdit.settingsDescription": "Concede permisos para modificar los ajustes globales. Un usuario debe tener este permiso para poder concedérselo a otros.",
-  "components.PermissionEdit.settings": "Gestionar Ajustes",
   "components.PermissionEdit.requestDescription": "Concede permisos para solicitar contenidos que no sean 4K.",
   "components.PermissionEdit.request4kTvDescription": "Concede permisos para solicitar series en 4K.",
   "components.PermissionEdit.request4kTv": "Pedir Series 4K",
@@ -516,7 +508,7 @@
   "components.Settings.validationApplicationUrlTrailingSlash": "La URL no puede acabar con una barra",
   "components.Settings.validationApplicationUrl": "Debes indicar una URL válida",
   "components.Settings.validationApplicationTitle": "Debes indicar un título de aplicación",
-  "components.Settings.trustProxyTip": "Permite a Overserr registrar correctamente la IP del cliente detrás de un Proxy (Overseer debe recargarse para que los cambios surtan efecto)",
+  "components.Settings.trustProxyTip": "Permite a Overserr registrar correctamente la IP del cliente detrás de un proxy",
   "components.Settings.trustProxy": "Habilitar soporte Proxy",
   "components.Settings.toastPlexRefreshSuccess": "¡Recibida la lista de servidores de Plex con éxito!",
   "components.Settings.toastPlexRefreshFailure": "Fallo al obtener la lista de servidores de Plex.",
@@ -541,7 +533,7 @@
   "components.Settings.notificationAgentSettingsDescription": "Configura y habilita los agentes de notificaciones.",
   "components.Settings.menuUsers": "Usuarios",
   "components.Settings.email": "Email",
-  "components.Settings.csrfProtectionTip": "Asigna acceso a una API externa en modo solo lectura (requiere HTTPS y debe recargarse Overseer para poder aplicar los cambios)",
+  "components.Settings.csrfProtectionTip": "Asigna acceso a una API externa en modo solo lectura (requiere HTTPS)",
   "components.Settings.csrfProtectionHoverTip": "¡NO habilitar esta opción a menos que seas consciente de lo que estás haciendo!",
   "components.Settings.csrfProtection": "Habilitar Protección CSRF",
   "components.Settings.applicationTitle": "Título de la Aplicación",
@@ -614,7 +606,6 @@
   "i18n.settings": "Ajustes",
   "i18n.advanced": "Avanzado",
   "components.UserProfile.recentrequests": "Solicitudes Recientes",
-  "components.UserProfile.norequests": "Sin solicitudes.",
   "components.UserProfile.UserSettings.menuPermissions": "Permisos",
   "components.UserProfile.UserSettings.menuNotifications": "Notificaciones",
   "components.UserProfile.UserSettings.menuGeneralSettings": "General",
@@ -747,7 +738,6 @@
   "components.Layout.VersionStatus.streamstable": "Overseer (Estable)",
   "components.Layout.VersionStatus.streamdevelop": "Overseer (Desarrollo)",
   "components.Layout.VersionStatus.outofdate": "Desactualizado",
-  "components.Discover.noRequests": "Sin solicitudes.",
   "components.UserList.autogeneratepasswordTip": "Envía por email una contraseña al usuario generada por el servidor",
   "i18n.retrying": "Reintentando…",
   "components.Settings.serverSecure": "seguro",
@@ -901,7 +891,6 @@
   "components.ManageSlideOver.manageModalRequests": "Solicitudes",
   "components.IssueList.sortModified": "Última Modificación",
   "components.IssueModal.CreateIssueModal.allseasons": "Todas las Temporadas",
-  "components.IssueModal.CreateIssueModal.issomethingwrong": "¿Hay algún problema con {title}?",
   "components.IssueModal.CreateIssueModal.episode": "Episodio {episodeNumber}",
   "components.IssueModal.CreateIssueModal.problemseason": "Temporada Afectada",
   "components.IssueModal.CreateIssueModal.toastviewissue": "Ver Incidencia",
diff --git a/src/i18n/locale/fr.json b/src/i18n/locale/fr.json
index d3b7a98b..ccf6f059 100644
--- a/src/i18n/locale/fr.json
+++ b/src/i18n/locale/fr.json
@@ -6,8 +6,8 @@
   "components.Discover.recentlyAdded": "Ajouts récents",
   "components.Discover.recentrequests": "Demandes récentes",
   "components.Discover.trending": "Tendances",
-  "components.Discover.upcoming": "Prochaines sorties",
-  "components.Discover.upcomingmovies": "Prochaines sorties",
+  "components.Discover.upcoming": "Films à venir",
+  "components.Discover.upcomingmovies": "Films à venir",
   "components.Layout.SearchInput.searchPlaceholder": "Rechercher des films et des séries",
   "components.Layout.Sidebar.dashboard": "Découvrir",
   "components.Layout.Sidebar.requests": "Demandes",
@@ -20,7 +20,7 @@
   "components.MovieDetails.overview": "Résumé",
   "components.MovieDetails.overviewunavailable": "Résumé indisponible.",
   "components.MovieDetails.recommendations": "Recommandations",
-  "components.MovieDetails.releasedate": "Date de sortie",
+  "components.MovieDetails.releasedate": "{releaseCount, plural, one {Date} other {Dates}} de sortie",
   "components.MovieDetails.revenue": "Revenus",
   "components.MovieDetails.runtime": "{minutes} minutes",
   "components.MovieDetails.similar": "Titres similaires",
@@ -33,17 +33,16 @@
   "components.RequestModal.cancel": "Annuler la demande",
   "components.RequestModal.extras": "Extras",
   "components.RequestModal.numberofepisodes": "Nbr d'épisodes",
-  "components.RequestModal.pendingrequest": "Demande en attente pour {title}",
-  "components.RequestModal.requestCancel": "Demande pour <strong>{title}</strong> annulée.",
+  "components.RequestModal.pendingrequest": "Demande en attente",
+  "components.RequestModal.requestCancel": "Demande pour <strong>{title}</strong> refusée.",
   "components.RequestModal.requestSuccess": "<strong>{title}</strong> demandé avec succès !",
   "components.RequestModal.requestadmin": "Cette demande sera validée automatiquement.",
   "components.RequestModal.requestfrom": "La demande de {username} est en attente de validation.",
-  "components.RequestModal.requestseasons": "Demander {seasonCount} {seasonCount, plural, one {Saison} other {Saisons}}",
-  "components.RequestModal.requesttitle": "Demander {title}",
+  "components.RequestModal.requestseasons": "Demander {seasonCount} {seasonCount, plural, one {saison} other {saisons}}",
   "components.RequestModal.season": "Saison",
   "components.RequestModal.seasonnumber": "Saison {number}",
-  "components.RequestModal.selectseason": "Selectionner Saison(s)",
-  "components.Search.searchresults": "Résultats de recherche",
+  "components.RequestModal.selectseason": "Sélectionner la/les saison(s)",
+  "components.Search.searchresults": "Résultats de la recherche",
   "components.Settings.Notifications.agentenabled": "Activer l'agent",
   "components.Settings.Notifications.authPass": "Mot de passe SMTP",
   "components.Settings.Notifications.authUser": "Nom d'utilisateur SMTP",
@@ -62,7 +61,7 @@
   "components.Settings.RadarrModal.hostname": "Nom d'hôte ou adresse IP",
   "components.Settings.RadarrModal.minimumAvailability": "Disponibilité minimale",
   "components.Settings.RadarrModal.port": "Port",
-  "components.Settings.RadarrModal.qualityprofile": "Profil qualité",
+  "components.Settings.RadarrModal.qualityprofile": "Profil de qualité",
   "components.Settings.RadarrModal.rootfolder": "Dossier racine",
   "components.Settings.RadarrModal.selectMinimumAvailability": "Sélectionner une disponibilté minimale",
   "components.Settings.RadarrModal.selectQualityProfile": "Sélectionner un profil qualité",
@@ -85,7 +84,7 @@
   "components.Settings.SonarrModal.editsonarr": "Modifier le serveur Sonarr",
   "components.Settings.SonarrModal.hostname": "Nom d'hôte ou adresse IP",
   "components.Settings.SonarrModal.port": "Port",
-  "components.Settings.SonarrModal.qualityprofile": "Profil qualité",
+  "components.Settings.SonarrModal.qualityprofile": "Profil de qualité",
   "components.Settings.SonarrModal.rootfolder": "Dossier racine",
   "components.Settings.SonarrModal.seasonfolders": "Dossier saison",
   "components.Settings.SonarrModal.selectQualityProfile": "Sélectionner un profil qualité",
@@ -122,7 +121,7 @@
   "components.Settings.menuLogs": "Journaux",
   "components.Settings.menuNotifications": "Notifications",
   "components.Settings.menuPlexSettings": "Plex",
-  "components.Settings.menuServices": "Services",
+  "components.Settings.menuServices": "Applications",
   "components.Settings.notificationsettings": "Paramètres de notification",
   "components.Settings.notrunning": "Pas en exécution",
   "components.Settings.plexlibraries": "Bibliothèques Plex",
@@ -152,7 +151,7 @@
   "components.UserList.created": "A rejoint",
   "components.UserList.plexuser": "Utilisateur Plex",
   "components.UserList.role": "Rôle",
-  "components.UserList.totalrequests": "Requêtes",
+  "components.UserList.totalrequests": "Demandes",
   "components.UserList.user": "Utilisateur",
   "components.UserList.userlist": "Liste des utilisateurs",
   "i18n.approve": "Valider",
@@ -225,7 +224,7 @@
   "components.UserList.importfromplexerror": "Une erreur s'est produite durant l'importation des utilisateurs de Plex.",
   "components.UserList.importfromplex": "Importer les utilisateurs de Plex",
   "components.UserList.importedfromplex": "<strong>{userCount}</strong> {userCount, plural, one {utilisateur} other {utilisateurs}} importé(s) depuis Plex avec succès !",
-  "components.TvDetails.viewfullcrew": "Voir l'équipe complète de la série",
+  "components.TvDetails.viewfullcrew": "Voir l'équipe complète",
   "components.TvDetails.TvCrew.fullseriescrew": "Équipe complète de la série",
   "components.PersonDetails.crewmember": "Équipe",
   "components.MovieDetails.viewfullcrew": "Voir l'équipe complète",
@@ -236,13 +235,13 @@
   "components.MovieDetails.watchtrailer": "Regarder la bande-annonce",
   "components.CollectionDetails.requestcollection": "Demander la collection",
   "components.CollectionDetails.overview": "Résumé",
-  "components.CollectionDetails.numberofmovies": "{count} Films",
+  "components.CollectionDetails.numberofmovies": "{count} films",
   "i18n.requested": "Demandé",
   "i18n.retry": "Réessayer",
   "i18n.failed": "Échec",
-  "components.Settings.Notifications.NotificationsSlack.webhookUrl": "URL webhook",
-  "components.Settings.Notifications.NotificationsSlack.slacksettingssaved": "Les paramètres de notifications Slack ont été enregistrés avec succès !",
-  "components.Settings.Notifications.NotificationsSlack.slacksettingsfailed": "Impossible d'enregistrer les paramètres des notifications Slack.",
+  "components.Settings.Notifications.NotificationsSlack.webhookUrl": "URL de webhook",
+  "components.Settings.Notifications.NotificationsSlack.slacksettingssaved": "Paramètres de notification de Slack sauvegardés avec succès !",
+  "components.Settings.Notifications.NotificationsSlack.slacksettingsfailed": "Les paramètres de notification Slack n'ont pas pu être enregistrés.",
   "components.Settings.Notifications.NotificationsSlack.agentenabled": "Activer l'agent",
   "components.RequestList.RequestItem.failedretry": "Une erreur s'est produite lors du renvoi de la demande.",
   "components.Settings.Notifications.validationChatIdRequired": "Vous devez fournir un identifiant de discussion valide",
@@ -252,41 +251,37 @@
   "components.Settings.Notifications.telegramsettingsfailed": "Les paramètres de notification Telegram n'ont pas pu être enregistrés.",
   "components.Settings.Notifications.senderName": "Nom de l'expéditeur",
   "components.Settings.Notifications.chatId": "ID discussion",
-  "components.StatusChacker.reloadOverseerr": "Recharger",
-  "components.StatusChacker.newversionavailable": "Mise à jour de l'application",
-  "components.StatusChacker.newversionDescription": "Overseerr a été mis à jour ! Veuillez cliquer sur le bouton ci-dessous pour recharger la page.",
   "components.Settings.SettingsAbout.documentation": "Documentation",
-  "components.NotificationTypeSelector.mediarequestedDescription": "Envoie une notification quand un média est demandé et nécessite une validation.",
-  "components.NotificationTypeSelector.mediarequested": "Demande en attente d'approbation",
-  "components.NotificationTypeSelector.mediafailedDescription": "Envoie une notification lorsqu'un média demandé n'a pas pu être ajouté sur Radarr /Sonarr.",
+  "components.NotificationTypeSelector.mediarequestedDescription": "Envoyer des notifications lorsque des utilisateurs soumettent une demande de média qui nécessite une validation.",
+  "components.NotificationTypeSelector.mediarequested": "Demande en attente de validation",
+  "components.NotificationTypeSelector.mediafailedDescription": "Envoyer des notifications lorsqu'une demande de média n'a pas pu être ajoutée à Radarr ou Sonarr.",
   "components.NotificationTypeSelector.mediafailed": "Échec d’ajout de la demande",
-  "components.NotificationTypeSelector.mediaavailableDescription": "Envoie une notification quand le média demandé devient disponible.",
+  "components.NotificationTypeSelector.mediaavailableDescription": "Envoyer des notifications lorsque le média demandé devient disponible.",
   "components.NotificationTypeSelector.mediaavailable": "Demande disponible",
-  "components.NotificationTypeSelector.mediaapprovedDescription": "Envoie une notification quand le média demandé est validé manuellement.",
+  "components.NotificationTypeSelector.mediaapprovedDescription": "Envoyer des notifications lorsqu'une demande de média est validée manuellement.",
   "components.NotificationTypeSelector.mediaapproved": "Demande validée",
   "i18n.request": "Demander",
-  "components.Settings.Notifications.NotificationsPushover.validationUserTokenRequired": "Vous devez fournir un jeton utilisateur valide ou une clef partagée",
+  "components.Settings.Notifications.NotificationsPushover.validationUserTokenRequired": "Vous devez fournir une clé d'utilisateur ou de groupe valide",
   "components.Settings.Notifications.NotificationsPushover.validationAccessTokenRequired": "Vous devez fournir un jeton d'application valide",
   "components.Settings.Notifications.NotificationsPushover.userToken": "Clé d'utilisateur ou de groupe",
-  "components.Settings.Notifications.NotificationsPushover.pushoversettingssaved": "Paramètres de notification pushover enregistrés avec succès !",
-  "components.Settings.Notifications.NotificationsPushover.pushoversettingsfailed": "Les paramètres de notification pushover n'ont pas pu être enregistrés.",
+  "components.Settings.Notifications.NotificationsPushover.pushoversettingssaved": "Paramètres de notification Pushover enregistrés avec succès !",
+  "components.Settings.Notifications.NotificationsPushover.pushoversettingsfailed": "Les paramètres de notification Pushover n'ont pas pu être enregistrés.",
   "components.Settings.Notifications.NotificationsPushover.agentenabled": "Activer l'agent",
-  "components.Settings.Notifications.NotificationsPushover.accessToken": "Clé API d'application",
+  "components.Settings.Notifications.NotificationsPushover.accessToken": "Jeton API d'application",
   "components.RequestList.sortModified": "Dernière modification",
-  "components.RequestList.sortAdded": "Plus récents",
+  "components.RequestList.sortAdded": "Plus récent",
   "components.RequestList.showallrequests": "Afficher toutes les demandes",
   "components.StatusBadge.status4k": "{status} en 4K",
   "components.Settings.Notifications.NotificationsWebhook.webhooksettingssaved": "Paramètres de notification Webhook enregistrés avec succès !",
   "components.Settings.Notifications.NotificationsWebhook.webhooksettingsfailed": "Échec de l'enregistrement des paramètres de notification du webhook.",
-  "components.Settings.Notifications.NotificationsWebhook.webhookUrl": "URL webhook",
+  "components.Settings.Notifications.NotificationsWebhook.webhookUrl": "URL de webhook",
   "components.Settings.Notifications.NotificationsWebhook.templatevariablehelp": "Aide sur les variables de modèle",
   "components.Settings.Notifications.NotificationsWebhook.authheader": "En-tête d'autorisation",
   "components.Settings.Notifications.NotificationsWebhook.agentenabled": "Activer l'agent",
-  "components.RequestModal.request4ktitle": "Demander {title} en 4K",
-  "components.RequestModal.pending4krequest": "Demande en attente pour {title} en 4K",
+  "components.RequestModal.pending4krequest": "Demande 4K en attente",
   "components.RequestButton.viewrequest4k": "Voir la demande 4K",
   "components.RequestButton.viewrequest": "Voir la demande",
-  "components.RequestButton.requestmore4k": "Demander plus d'ajouts en 4K",
+  "components.RequestButton.requestmore4k": "Demander d'autres ajouts en 4K",
   "components.RequestButton.requestmore": "Demander d'autres ajouts",
   "components.RequestButton.declinerequests": "Refuser {requestCount, plural, one {demande} other {{requestCount} demandes}}",
   "components.RequestButton.declinerequest4k": "Refuser la demande 4K",
@@ -311,7 +306,7 @@
   "components.UserList.autogeneratepassword": "Générer automatiquement le mot de passe",
   "components.UserList.passwordinfodescription": "Configurez l'URL de l'application ainsi que les notifications par e-mail pour permettre la génération automatique de mots de passe.",
   "components.UserList.email": "Adresse e-mail",
-  "components.Login.validationpasswordrequired": "Vous devez fournir un mot de passe",
+  "components.Login.validationpasswordrequired": "Vous devez renseigner un mot de passe",
   "components.Login.validationemailrequired": "Vous devez fournir un e-mail valide",
   "components.Login.signinwithoverseerr": "Utilisez votre compte {applicationTitle}",
   "components.Login.password": "Mot de passe",
@@ -320,58 +315,55 @@
   "components.MediaSlider.ShowMoreCard.seemore": "Voir plus",
   "i18n.edit": "Modifier",
   "components.RequestModal.requestedited": "Demande pour <strong>{title}</strong> modifiée avec succès !",
-  "components.RequestModal.requestcancelled": "Demande pour <strong>{title}</strong> annulée.",
+  "components.RequestModal.requestcancelled": "Demande pour <strong>{title}</strong> refusée.",
   "components.RequestModal.errorediting": "Une erreur s'est produite lors de la modification de la demande.",
   "components.RequestModal.autoapproval": "Validation automatique",
-  "components.RequestModal.AdvancedRequester.rootfolder": "Dossier Racine",
+  "components.RequestModal.AdvancedRequester.rootfolder": "Dossier racine",
   "components.RequestModal.AdvancedRequester.qualityprofile": "Profil de qualité",
   "components.RequestModal.AdvancedRequester.destinationserver": "Serveur de destination",
   "components.RequestModal.AdvancedRequester.default": "{name} (Défaut)",
   "components.RequestModal.AdvancedRequester.animenote": "* Cette série est un animé.",
   "components.RequestModal.AdvancedRequester.advancedoptions": "Options Avancées",
-  "components.RequestBlock.requestoverrides": "Contournements de demande",
+  "components.RequestBlock.requestoverrides": "Modifications de la demande",
   "components.RequestBlock.server": "Serveur de destination",
   "components.RequestBlock.rootfolder": "Dossier racine",
-  "components.RequestBlock.profilechanged": "Profil qualité",
+  "components.RequestBlock.profilechanged": "Profil de qualité",
   "components.NotificationTypeSelector.mediadeclined": "Demande refusée",
-  "components.NotificationTypeSelector.mediadeclinedDescription": "Envoie une notification lorsqu'un média demandé est refusé.",
+  "components.NotificationTypeSelector.mediadeclinedDescription": "Envoyer des notifications lorsqu'une demande de média est refusée.",
   "i18n.experimental": "Expérimentale",
   "components.Settings.hideAvailable": "Masquer les médias disponibles",
-  "components.RequestModal.requesterror": "Il y a eu un problème lors de la demande.",
-  "components.RequestModal.SearchByNameModal.notvdbiddescription": "Nous n'avons pas pu associer votre demande automatiquement. Veuillez sélectionner l'association correcte dans la liste ci-dessous.",
-  "components.RequestModal.SearchByNameModal.nosummary": "Aucun résumé trouvé pour ce titre.",
+  "components.RequestModal.requesterror": "Une erreur s'est produite lors de la demande.",
+  "components.RequestModal.SearchByNameModal.notvdbiddescription": "Nous n'avons pas pu associer cette série automatiquement. Veuillez sélectionner l'association correcte dans la liste ci-dessous.",
   "components.Login.signinwithplex": "Utilisez votre compte Plex",
   "components.Login.signin": "Connexion",
   "components.Login.signinheader": "Connectez-vous pour continuer",
   "components.Login.signingin": "Connexion en cours…",
   "components.Settings.notificationAgentSettingsDescription": "Configurer et activer les agents de notification.",
-  "components.PlexLoginButton.signinwithplex": "Connectez-vous",
+  "components.PlexLoginButton.signinwithplex": "Se connecter",
   "components.PlexLoginButton.signingin": "Connexion en cours…",
   "components.UserList.userssaved": "Les permissions d'utilisateur ont été enregistrées avec succès !",
   "components.UserList.bulkedit": "Modification en masse",
-  "components.Settings.csrfProtectionTip": "Définir l'accès à l'API externe en lecture seule (nécessite HTTPS et Overseerr doit être rechargé pour que les modifications prennent effet)",
+  "components.Settings.csrfProtectionTip": "Définir l'accès à l'API externe en lecture seule (nécessite HTTPS)",
   "components.Settings.csrfProtection": "Activer la protection CSRF",
-  "components.PermissionEdit.usersDescription": "Accorder l'autorisation de gérer les utilisateurs. Les utilisateurs disposant de cette autorisation ne peuvent pas modifier les utilisateurs dotés de privilèges d'administrateur ni les accorder.",
+  "components.PermissionEdit.usersDescription": "Autorise à gérer les utilisateurs. Les utilisateurs avec cette autorisation ne peuvent pas modifier les utilisateurs dotés de privilèges d'administrateur ni les accorder.",
   "components.PermissionEdit.users": "Gérer les utilisateurs",
-  "components.PermissionEdit.settingsDescription": "Accorde la permission de modifier les paramètres globaux. Un utilisateur doit avoir cette autorisation pour l'accorder à d'autres.",
-  "components.PermissionEdit.settings": "Gérer les paramètres",
-  "components.PermissionEdit.requestDescription": "Accorde la permission de demander des médias non-4K.",
-  "components.PermissionEdit.request4kTvDescription": "Accorde l'autorisation de demander des séries en 4K.",
-  "components.PermissionEdit.request4kTv": "Demande de séries 4K",
-  "components.PermissionEdit.request4kMoviesDescription": "Accorder la permission de soumettre des demandes de films en 4K.",
-  "components.PermissionEdit.request4kMovies": "Demande de films 4K",
-  "components.PermissionEdit.request4kDescription": "Accorde la permission de soumettre des demandes pour des médias en 4K.",
-  "components.PermissionEdit.request4k": "Demande 4K",
-  "components.PermissionEdit.request": "Demande",
-  "components.PermissionEdit.managerequestsDescription": "Accorde la permission de gérer les demandes de média. Toutes les demandes faites par un utilisateur avec cette autorisation seront automatiquement approuvées.",
+  "components.PermissionEdit.requestDescription": "Autorise à demander des médias non-4K.",
+  "components.PermissionEdit.request4kTvDescription": "Autorise à demander des séries en 4K.",
+  "components.PermissionEdit.request4kTv": "Demander des séries en 4K",
+  "components.PermissionEdit.request4kMoviesDescription": "Autorise à demander des films en 4K.",
+  "components.PermissionEdit.request4kMovies": "Demander des films en 4K",
+  "components.PermissionEdit.request4kDescription": "Autorise à demander des médias en 4K.",
+  "components.PermissionEdit.request4k": "Demander en 4K",
+  "components.PermissionEdit.request": "Demander",
+  "components.PermissionEdit.managerequestsDescription": "Autorise à gérer les demandes de média. Toutes les demandes faites par un utilisateur avec cette autorisation seront validées automatiquement.",
   "components.PermissionEdit.managerequests": "Gérer les demandes",
-  "components.PermissionEdit.autoapproveSeriesDescription": "Accorde la validation automatique pour toutes les demandes de série non-4K.",
-  "components.PermissionEdit.autoapproveSeries": "Validation automatique des séries",
-  "components.PermissionEdit.autoapproveMoviesDescription": "Accorde la validation automatique des demandes de films non-4K.",
-  "components.PermissionEdit.autoapproveMovies": "Validation automatique des films",
-  "components.PermissionEdit.autoapproveDescription": "Accorde la validation automatique pour toutes les demandes de média non-4K.",
-  "components.PermissionEdit.autoapprove": "Validation automatique",
-  "components.PermissionEdit.advancedrequestDescription": "Accorde la permission de modifier les options de demande de média avancées.",
+  "components.PermissionEdit.autoapproveSeriesDescription": "Valider automatiquement les demandes de séries non-4K.",
+  "components.PermissionEdit.autoapproveSeries": "Valider automatiquement les séries",
+  "components.PermissionEdit.autoapproveMoviesDescription": "Valide automatiquement les demandes de films non-4K.",
+  "components.PermissionEdit.autoapproveMovies": "Valider automatiquement les films",
+  "components.PermissionEdit.autoapproveDescription": "Valide automatiquement toutes les demandes de média non-4K.",
+  "components.PermissionEdit.autoapprove": "Valider automatiquement",
+  "components.PermissionEdit.advancedrequestDescription": "Permet de modifier les options de demande de média avancées.",
   "components.PermissionEdit.advancedrequest": "Demandes avancées",
   "components.PermissionEdit.adminDescription": "Accès administrateur complet. Contourne toutes les autres permissions (sélectionnées ou non).",
   "components.PermissionEdit.admin": "Admin",
@@ -397,10 +389,10 @@
   "components.Settings.RadarrModal.syncEnabled": "Activer les scans",
   "components.Settings.RadarrModal.externalUrl": "URL externe",
   "components.MovieDetails.markavailable": "Marquer comme disponible",
-  "components.MovieDetails.mark4kavailable": "Marquer comme Disponible en 4K",
+  "components.MovieDetails.mark4kavailable": "Marquer comme disponible en 4K",
   "components.MovieDetails.playonplex": "Lire sur Plex",
   "components.MovieDetails.play4konplex": "Lire en 4K sur Plex",
-  "components.Settings.trustProxyTip": "Permettre Overseerr à enregistrer correctement les adresses IP des clients derrière un proxy (Overseerr doit être rechargé pour que les modifications prennent effet)",
+  "components.Settings.trustProxyTip": "Permettre Overseerr à enregistrer correctement les adresses IP des clients derrière un proxy",
   "components.Settings.trustProxy": "Activer la prise en charge proxy",
   "components.Settings.SettingsJobsCache.jobsDescription": "Overseerr effectue certaines tâches de maintenance comme des tâches planifiées régulièrement, mais elles peuvent également être déclenchées manuellement ci-dessous. L'exécution manuelle d'une tâche ne modifiera pas sa planification.",
   "components.Settings.SettingsJobsCache.cachemisses": "Manqués",
@@ -434,8 +426,8 @@
   "components.Settings.RadarrModal.validationApplicationUrlTrailingSlash": "L'URL ne doit pas se terminer par une barre oblique finale",
   "components.Settings.RadarrModal.validationApplicationUrl": "Vous devez fournir une URL valide",
   "components.Search.search": "Rechercher",
-  "components.RequestModal.AdvancedRequester.requestas": "Demander comme",
-  "components.PermissionEdit.viewrequestsDescription": "Accorder l'autorisation de consulter les demandes des autres utilisateurs.",
+  "components.RequestModal.AdvancedRequester.requestas": "Demander en tant que",
+  "components.PermissionEdit.viewrequestsDescription": "Autorise à afficher les demandes des autres utilisateurs.",
   "components.PermissionEdit.viewrequests": "Voir les demandes",
   "components.Discover.discover": "Découvrir",
   "components.UserList.validationEmail": "Vous devez fournir un e-mail valide",
@@ -447,9 +439,9 @@
   "components.Settings.Notifications.validationEmail": "Vous devez fournir un e-mail valide",
   "components.Settings.Notifications.NotificationsWebhook.validationWebhookUrl": "Vous devez fournir une URL valide",
   "components.Settings.Notifications.NotificationsSlack.validationWebhookUrl": "Vous devez fournir une URL valide",
-  "components.ResetPassword.validationpasswordrequired": "Vous devez fournir un mot de passe",
-  "components.ResetPassword.validationpasswordminchars": "Le mot de passe est trop court ; il doit comporter au moins 8 caractères",
-  "components.ResetPassword.validationpasswordmatch": "Les mots de passe doivent correspondre",
+  "components.ResetPassword.validationpasswordrequired": "Vous devez renseigner un mot de passe",
+  "components.ResetPassword.validationpasswordminchars": "Le mot de passe est trop court ; il doit comporter au moins 8 caractères",
+  "components.ResetPassword.validationpasswordmatch": "Les mots de passe doivent être les mêmes",
   "components.ResetPassword.validationemailrequired": "Vous devez fournir un e-mail valide",
   "components.ResetPassword.resetpasswordsuccessmessage": "Le mot de passe a été réinitialisé avec succès !",
   "components.ResetPassword.resetpassword": "Réinitialiser votre mot de passe",
@@ -459,7 +451,7 @@
   "components.ResetPassword.emailresetlink": "Envoyer un lien de récupération par e-mail",
   "components.ResetPassword.email": "Adresse e-mail",
   "components.ResetPassword.confirmpassword": "Confirmez le mot de passe",
-  "components.Login.forgotpassword": "Mot de passe oublié ?",
+  "components.Login.forgotpassword": "Mot de passe oublié ?",
   "components.Settings.SettingsJobsCache.process": "Processus",
   "components.Settings.SettingsJobsCache.command": "Commande",
   "components.Settings.validationApplicationTitle": "Vous devez fournir un titre d'application",
@@ -475,13 +467,13 @@
   "components.UserList.sortRequests": "Nombre de demandes",
   "components.UserList.sortDisplayName": "Nom d'Utilisateur affiché",
   "components.UserList.sortCreated": "Date d'inscription",
-  "components.PermissionEdit.autoapprove4kSeriesDescription": "Accorde la validation automatique des demandes de séries 4K faites.",
+  "components.PermissionEdit.autoapprove4kSeriesDescription": "Valide automatiquement les demandes de séries en 4K.",
   "components.PermissionEdit.autoapprove4kSeries": "Validation automatique des séries 4K",
-  "components.PermissionEdit.autoapprove4kMoviesDescription": "Accorde la validation automatique des demandes de films 4K.",
+  "components.PermissionEdit.autoapprove4kMoviesDescription": "Valide automatiquement les demandes de films en 4K.",
   "components.PermissionEdit.autoapprove4kMovies": "Validation automatique des films 4K",
-  "components.PermissionEdit.autoapprove4kDescription": "Accorde la validation automatique pour toutes les demandes de média en 4K.",
+  "components.PermissionEdit.autoapprove4kDescription": "Valide automatiquement toutes les demandes de média en 4K.",
   "components.PermissionEdit.autoapprove4k": "Validation automatique 4K",
-  "components.AppDataWarning.dockerVolumeMissingDescription": "Le montage du volume <code> {appDataPath} </code> n'a pas été configuré correctement. Toutes les données seront effacées lorsque le conteneur est arrêté ou redémarré.",
+  "components.AppDataWarning.dockerVolumeMissingDescription": "Le montage du volume <code>{appDataPath}</code> n'a pas été configuré correctement. Toutes les données seront effacées lorsque le conteneur sera arrêté ou redémarré.",
   "components.UserProfile.UserSettings.UserNotificationSettings.discordId": "Identifiant",
   "components.UserProfile.UserSettings.UserNotificationSettings.notificationsettings": "Paramètres de notification",
   "components.UserProfile.UserSettings.UserPasswordChange.newpassword": "Nouveau mot de passe",
@@ -490,7 +482,7 @@
   "components.UserProfile.UserSettings.UserPermissions.toastSettingsSuccess": "Paramètres enregistrés avec succès !",
   "components.UserProfile.UserSettings.UserPermissions.toastSettingsFailure": "Une erreur s'est produite lors de l'enregistrement des paramètres.",
   "components.UserProfile.recentrequests": "Demandes récentes",
-  "components.UserProfile.UserSettings.menuPermissions": "Autorisations",
+  "components.UserProfile.UserSettings.menuPermissions": "Permissions",
   "components.UserProfile.UserSettings.menuNotifications": "Notifications",
   "components.UserProfile.UserSettings.menuGeneralSettings": "Général",
   "components.UserProfile.UserSettings.menuChangePass": "Mot de passe",
@@ -563,9 +555,9 @@
   "components.RequestList.RequestItem.modified": "Modifiée",
   "components.RequestList.RequestItem.requested": "Demandé",
   "components.RequestList.RequestItem.modifieduserdate": "{date} par {user}",
-  "components.Discover.StudioSlider.studios": "Studio",
+  "components.Discover.StudioSlider.studios": "Studios",
   "components.Discover.DiscoverTvLanguage.languageSeries": "Séries en {language}",
-  "components.Discover.DiscoverMovieLanguage.languageMovies": "Films {language}",
+  "components.Discover.DiscoverMovieLanguage.languageMovies": "Films en {language}",
   "components.Setup.scanbackground": "Le scan s'effectue en arrière-plan. Vous pouvez donc continuer le processus de configuration pendant ce temps.",
   "components.Settings.scanning": "Synchronisation en cours…",
   "components.Settings.scan": "Synchroniser les bibliothèques",
@@ -573,7 +565,7 @@
   "components.Settings.SettingsJobsCache.radarr-scan": "Scan de Radarr",
   "components.Settings.SettingsJobsCache.plex-recently-added-scan": "Scan des ajouts récents aux bibliothèques Plex",
   "components.Settings.SettingsJobsCache.plex-full-scan": "Scan complet des bibliothèques Plex",
-  "components.Settings.Notifications.validationUrl": "Vous devez fournir un URL valide",
+  "components.Settings.Notifications.validationUrl": "Vous devez fournir une URL valide",
   "components.Settings.Notifications.botAvatarUrl": "L'URL de l'avatar de votre Bot",
   "components.Settings.SettingsUsers.userSettingsDescription": "Configurer les paramètres généraux et par défaut de l'utilisateur.",
   "components.Settings.SettingsUsers.toastSettingsFailure": "Un problème est survenu pendant la sauvegarde des paramètres.",
@@ -585,12 +577,11 @@
   "components.Settings.SettingsUsers.userSettings": "Paramètres utilisateur",
   "components.Settings.SettingsUsers.toastSettingsSuccess": "Les paramètres utilisateur ont été enregistrés avec succès !",
   "components.NotificationTypeSelector.mediaAutoApproved": "Demande validée automatiquement",
-  "components.NotificationTypeSelector.mediaAutoApprovedDescription": "Envoie une notification quand un utilisateur envoie une demande pour un nouveau média qui est validée automatiquement.",
+  "components.NotificationTypeSelector.mediaAutoApprovedDescription": "Envoyer des notifications lorsque des utilisateurs soumettent une demande pour un nouveau média qui est validée automatiquement.",
   "components.UserProfile.UserSettings.unauthorizedDescription": "Vous n'avez pas l'autorisation de modifier les paramètres de cet utilisateur.",
   "components.UserProfile.UserSettings.UserPermissions.unauthorizedDescription": "Vous ne pouvez pas modifier vos propres permissions.",
   "components.Settings.Notifications.pgpPrivateKeyTip": "Signer des emails chiffrés en utilisant <OpenPgpLink>OpenPGP</OpenPgpLink>",
   "components.Settings.Notifications.pgpPasswordTip": "Signer des emails chiffrés en utilisant <OpenPgpLink>OpenPGP</OpenPgpLink>",
-  "components.UserProfile.norequests": "Aucune demande.",
   "components.Settings.Notifications.pgpPrivateKey": "PGP Clé privée",
   "components.TvDetails.episodeRuntimeMinutes": "{runtime} minutes",
   "components.TvDetails.episodeRuntime": "Durée d'un épisode",
@@ -630,7 +621,7 @@
   "components.ResetPassword.passwordreset": "Réinitialiser le mot de passe",
   "pages.internalservererror": "Erreur interne du serveur",
   "components.UserProfile.UserSettings.UserPasswordChange.toastSettingsFailureVerifyCurrent": "Un problème est survenu lors de l'enregistrement du mot de passe. Votre mot de passe actuel a-t-il été saisi correctement ?",
-  "components.Settings.cacheImagesTip": "Optimiser et stocker toutes les images localement (consomme une quantité considérable d'espace disque)",
+  "components.Settings.cacheImagesTip": "Met en cache localement et utilise des images optimisées (nécessite une quantité considérable d'espace disque)",
   "components.Settings.cacheImages": "Activer la mise en cache d'image",
   "components.Settings.SettingsLogs.time": "Horodatage",
   "components.Settings.SettingsLogs.resumeLogs": "Résumer",
@@ -642,18 +633,18 @@
   "components.Settings.SettingsJobsCache.jobsandcache": "Tâches et cache",
   "components.UserList.nouserstoimport": "Aucun nouvel utilisateur de Plex à importer.",
   "components.PersonDetails.lifespan": "{birthdate} – {deathdate}",
-  "components.PersonDetails.birthdate": "Né(e) {birthdate}",
-  "components.PersonDetails.alsoknownas": "Aussi connu sous le nom : {names}",
+  "components.PersonDetails.birthdate": "Né(e) le {birthdate}",
+  "components.PersonDetails.alsoknownas": "Aussi connu sous le(s) nom(s) : {names}",
   "i18n.delimitedlist": "{a}, {b}",
   "components.RequestModal.QuotaDisplay.season": "saison",
-  "components.RequestModal.QuotaDisplay.requestsremaining": "{remaining, plural, =0 {Aucune(s)} other {<strong>#</strong>}} {type} {remaining, plural, one {demande} other {demandes}} restante(s)",
-  "components.RequestModal.QuotaDisplay.quotaLinkUser": "Vous pouvez voir un résumé des limites de demandes de cet utilisateur sur leur <ProfileLink>page de profil</ProfileLink>.",
+  "components.RequestModal.QuotaDisplay.requestsremaining": "{remaining, plural, =0 {Aucune} other {<strong>#</strong>}} {remaining, plural, one {demande} other {demandes}} de {type} {remaining, plural, one {restante} other {restantes}}",
+  "components.RequestModal.QuotaDisplay.quotaLinkUser": "Vous pouvez voir un résumé des limites de demandes de cet utilisateur sur sa <ProfileLink>page de profil</ProfileLink>.",
   "components.RequestModal.QuotaDisplay.quotaLink": "Vous pouvez voir un résumé de vos limites de demandes sur votre <ProfileLink>page de profil</ProfileLink>.",
   "components.RequestModal.QuotaDisplay.notenoughseasonrequests": "Pas assez de demandes de saison restantes",
   "components.RequestModal.QuotaDisplay.movielimit": "{limit, plural, one {film} other {films}}",
   "components.RequestModal.QuotaDisplay.movie": "film",
-  "components.RequestModal.QuotaDisplay.allowedRequestsUser": "Cet utilisateur est autorisé à demander <strong>{limit}</strong> {type} tous les <strong>{days}</strong> jours.",
-  "components.RequestModal.QuotaDisplay.allowedRequests": "Vous êtes autorisé à demander <strong>{limit}</strong> {type} tous les <strong>{days}</strong> jours.",
+  "components.RequestModal.QuotaDisplay.allowedRequestsUser": "Cet utilisateur est autorisé à demander <strong>{limit}</strong> {type} tous les <strong>{days}</strong> jour(s).",
+  "components.RequestModal.QuotaDisplay.allowedRequests": "Vous êtes autorisé à demander <strong>{limit}</strong> {type} tous les <strong>{days}</strong> jour(s).",
   "components.QuotaSelector.unlimited": "Illimité",
   "components.UserProfile.unlimited": "Illimité",
   "components.TvDetails.originaltitle": "Titre original",
@@ -720,7 +711,7 @@
   "components.UserProfile.UserSettings.UserNotificationSettings.pgpPublicKey": "Clé Publique PGP",
   "components.UserProfile.UserSettings.UserNotificationSettings.email": "Email",
   "components.UserProfile.UserSettings.UserNotificationSettings.discordsettingsfailed": "Les paramètres de notification Discord n’ont pas pu être enregistrés.",
-  "components.Settings.serviceSettingsDescription": "Configurez votre serveur {serverType} ci-dessous. Vous pouvez connecter plusieurs serveurs {serverType}, mais seulement deux d’entre eux peuvent être marqués par défaut (un non-4K et un 4K). Les administrateurs peuvent outrepasser le serveur utilisé pour traiter les nouvelles demandes avant l’approbation.",
+  "components.Settings.serviceSettingsDescription": "Configurez votre serveur {serverType} ci-dessous. Vous pouvez connecter plusieurs serveurs {serverType}, mais seulement deux d’entre eux peuvent être marqués par défaut (un non-4K et un 4K). Les administrateurs peuvent modifier le serveur utilisé pour traiter les nouvelles demandes avant la validation.",
   "components.Settings.mediaTypeSeries": "série",
   "components.Settings.mediaTypeMovie": "film",
   "components.Settings.SettingsAbout.uptodate": "À jour",
@@ -728,18 +719,17 @@
   "components.Settings.Notifications.validationPgpPrivateKey": "Vous devez fournir une clé privée PGP valide si un mot de passe PGP est entré",
   "components.Settings.Notifications.validationPgpPassword": "Vous devez fournir un mot de passe PGP",
   "components.Settings.Notifications.botUsernameTip": "Permet aux utilisateurs de démarrer également une conversation avec votre bot et de configurer leurs propres notifications personnelles",
-  "components.RequestModal.pendingapproval": "Votre demande est en attente d’approbation.",
-  "components.RequestList.RequestItem.mediaerror": "Le titre associé à cette demande n’est plus disponible.",
+  "components.RequestModal.pendingapproval": "Votre demande est en attente de validation.",
+  "components.RequestList.RequestItem.mediaerror": "{mediaType} non trouvé",
   "components.RequestList.RequestItem.deleterequest": "Supprimer la Demande",
-  "components.RequestList.RequestItem.cancelRequest": "Annuler la Demande",
-  "components.RequestCard.mediaerror": "Le titre associé à cette demande n’est plus disponible.",
+  "components.RequestList.RequestItem.cancelRequest": "Annuler la demande",
+  "components.RequestCard.mediaerror": "{mediaType} non trouvé",
   "components.RequestCard.deleterequest": "Supprimer la Demande",
   "components.NotificationTypeSelector.notificationTypes": "Types de Notification",
   "components.Layout.VersionStatus.streamstable": "Overseerr stable",
   "components.Layout.VersionStatus.streamdevelop": "Développement d'Overseerr",
   "components.Layout.VersionStatus.commitsbehind": "{commitsBehind} {commitsBehind, plural, one {commit} other {commits}} en retard",
   "components.Layout.VersionStatus.outofdate": "Obsolète",
-  "components.Discover.noRequests": "Aucune demande.",
   "components.RequestModal.QuotaDisplay.requiredquota": "Vous devez avoir au moins <strong>{seasons}</strong> {seasons, plural, one {demande de saison} other {demandes de saisons}} afin de soumettre une demande pour cette série.",
   "components.RequestModal.QuotaDisplay.requiredquotaUser": "Cet utilisateur doit avoir au moins <strong>{seasons}</strong> {seasons, plural, one {demande de saison} other {demandes de saisons}} afin de soumettre une demande pour cette série.",
   "components.Settings.noDefaultNon4kServer": "Si vous n’avez qu’un seul serveur {serverType} pour les contenus non-4K et 4K (ou si vous ne téléchargez que du contenu 4K), votre serveur {serverType} ne devrait <strong>PAS</strong> être désigné comme serveur 4K.",
@@ -751,8 +741,8 @@
   "components.UserList.autogeneratepasswordTip": "Envoyer par email un mot de passe généré par le serveur à l’utilisateur",
   "i18n.retrying": "Nouvelle tentative…",
   "components.Settings.serverSecure": "sécurisée",
-  "components.RequestModal.edit": "Modifer la demande",
-  "components.RequestList.RequestItem.editrequest": "Modifer la demande",
+  "components.RequestModal.edit": "Modifier la demande",
+  "components.RequestList.RequestItem.editrequest": "Modifier la demande",
   "components.UserList.usercreatedfailedexisting": "L'adresse électronique fournie est déjà utilisée par un autre utilisateur.",
   "components.UserProfile.UserSettings.UserNotificationSettings.webpush": "Web Push",
   "components.UserProfile.UserSettings.UserGeneralSettings.applanguage": "Langue d'affichage",
@@ -762,28 +752,28 @@
   "components.Settings.Notifications.NotificationsWebPush.webpushsettingssaved": "Les paramètres de la notification Web push ont été enregistrés avec succès !",
   "components.Settings.Notifications.NotificationsWebPush.webpushsettingsfailed": "Les paramètres de la notification Web push n'ont pas été enregistrés.",
   "components.Settings.Notifications.NotificationsWebPush.agentenabled": "Activer l'agent",
-  "components.Settings.Notifications.NotificationsLunaSea.webhookUrl": "URL webhook",
+  "components.Settings.Notifications.NotificationsLunaSea.webhookUrl": "URL de webhook",
   "components.Settings.Notifications.NotificationsLunaSea.validationWebhookUrl": "Vous devez fournir une URL valide",
-  "components.Settings.Notifications.NotificationsLunaSea.settingsSaved": "Les paramètres de notification de LunaSea ont été sauvegardés avec succès !",
-  "components.Settings.Notifications.NotificationsLunaSea.settingsFailed": "Les paramètres de notification de LunaSea n'ont pas été enregistrés.",
+  "components.Settings.Notifications.NotificationsLunaSea.settingsSaved": "Paramètres de notification de LunaSea sauvegardés avec succès !",
+  "components.Settings.Notifications.NotificationsLunaSea.settingsFailed": "Les paramètres de notification LunaSea n'ont pas pu être enregistrés.",
   "components.Settings.Notifications.NotificationsLunaSea.profileNameTip": "Uniquement nécessaire si vous n'utilisez pas le profil <code>default</code>",
   "components.Settings.Notifications.NotificationsLunaSea.profileName": "Nom du Profil",
   "components.Settings.Notifications.NotificationsLunaSea.agentenabled": "Activer l'agent",
-  "components.PermissionEdit.requestMoviesDescription": "Accorde la permission de demander des films non-4K.",
+  "components.PermissionEdit.requestMoviesDescription": "Autorise à demander des films non-4K.",
   "components.Settings.Notifications.NotificationsWebhook.toastWebhookTestFailed": "La notification de test Web Push n’a pas été envoyée.",
   "components.PermissionEdit.requestMovies": "Demander des films",
   "components.PermissionEdit.requestTv": "Demander des séries",
-  "components.PermissionEdit.requestTvDescription": "Accorde la permission de demander des séries non-4K.",
+  "components.PermissionEdit.requestTvDescription": "Autorise à demander des séries non-4K.",
   "components.Settings.Notifications.NotificationsLunaSea.toastLunaSeaTestSuccess": "Notification test LunaSea envoyée !",
-  "components.Settings.Notifications.NotificationsLunaSea.toastLunaSeaTestSending": "Envoi de la notification test pour LunaSea…",
-  "components.Settings.Notifications.NotificationsLunaSea.toastLunaSeaTestFailed": "L'envoi de la notification test de LunaSea a échoué.",
-  "components.Settings.Notifications.NotificationsPushbullet.toastPushbulletTestSending": "Envoi de la notification test à Pushbullet…",
-  "components.Settings.Notifications.NotificationsPushbullet.toastPushbulletTestFailed": "L'envoi de la notification test à Pushbullet a échoué.",
+  "components.Settings.Notifications.NotificationsLunaSea.toastLunaSeaTestSending": "Envoi de la notification test LunaSea…",
+  "components.Settings.Notifications.NotificationsLunaSea.toastLunaSeaTestFailed": "L'envoi de la notification test LunaSea a échoué.",
+  "components.Settings.Notifications.NotificationsPushbullet.toastPushbulletTestSending": "Envoi de la notification test Pushbullet…",
+  "components.Settings.Notifications.NotificationsPushbullet.toastPushbulletTestFailed": "L'envoi de la notification test Pushbullet a échoué.",
   "components.Settings.Notifications.toastTelegramTestFailed": "L'envoi de la notification test à Telegram a échoué.",
-  "components.Settings.Notifications.NotificationsPushbullet.toastPushbulletTestSuccess": "Notification test envoyée à Pushbullet !",
-  "components.Settings.Notifications.NotificationsPushover.toastPushoverTestSending": "Envoi de la notification test à Pushover…",
-  "components.Settings.Notifications.NotificationsPushover.toastPushoverTestFailed": "L'envoi de la notification test à Pushover a échoué.",
-  "components.Settings.Notifications.NotificationsPushover.toastPushoverTestSuccess": "Notification test envoyée à Pushover !",
+  "components.Settings.Notifications.NotificationsPushbullet.toastPushbulletTestSuccess": "Notification test Pushbullet envoyée !",
+  "components.Settings.Notifications.NotificationsPushover.toastPushoverTestSending": "Envoi de la notification test Pushover…",
+  "components.Settings.Notifications.NotificationsPushover.toastPushoverTestFailed": "L'envoi de la notification test Pushover a échoué.",
+  "components.Settings.Notifications.NotificationsPushover.toastPushoverTestSuccess": "Notification test Pushover envoyée !",
   "components.Settings.Notifications.encryptionImplicitTls": "Utiliser TLS implicite",
   "components.Settings.Notifications.encryptionTip": "Dans la majorité des cas, TLS implicite utilise le port 465 et STARTTLS utilise le port 587",
   "components.Settings.Notifications.encryptionNone": "Aucune",
@@ -798,18 +788,18 @@
   "components.UserProfile.UserSettings.UserNotificationSettings.webpushsettingssaved": "Paramètres de notification Web Push enregistrés avec succès !",
   "components.Settings.Notifications.NotificationsWebPush.toastWebPushTestSuccess": "Notification de test web push envoyée !",
   "components.Settings.Notifications.NotificationsWebPush.toastWebPushTestSending": "Envoi d'une notification de test web push…",
-  "components.Settings.Notifications.NotificationsWebPush.httpsRequirement": "Afin de recevoir des notifications web push, Overseerr doit fonctionner en HTTPS.",
+  "components.Settings.Notifications.NotificationsWebPush.httpsRequirement": "Afin de recevoir des notifications push web, Overseerr doit fonctionner en HTTPS.",
   "components.Settings.Notifications.NotificationsWebhook.toastWebhookTestSuccess": "Notification de test Webhook envoyée !",
   "components.Settings.Notifications.NotificationsWebhook.toastWebhookTestSending": "Envoi de notification de test webhook…",
   "components.Settings.Notifications.NotificationsWebPush.toastWebPushTestFailed": "L'envoi de la notification de test Web push a échoué.",
-  "components.Settings.Notifications.NotificationsSlack.toastSlackTestSuccess": "Notification test de Slack envoyée !",
-  "components.Settings.Notifications.NotificationsSlack.toastSlackTestSending": "Envoi de la notification test de Slack…",
-  "components.Settings.Notifications.NotificationsSlack.toastSlackTestFailed": "L'envoi de la notification test de Slack a échoué.",
-  "components.Settings.Notifications.NotificationsPushbullet.accessTokenTip": "Crée un jeton à partir de vos <PushbulletSettingsLink>Paramètres de compte</PushbulletSettingsLink>",
-  "components.Settings.Notifications.NotificationsLunaSea.webhookUrlTip": "Votre <LunaSeaLink>URL webhook de notification </LunaSeaLink> basée sur l'utilisateur ou l'appareil",
+  "components.Settings.Notifications.NotificationsSlack.toastSlackTestSuccess": "Notification test Slack envoyée !",
+  "components.Settings.Notifications.NotificationsSlack.toastSlackTestSending": "Envoi de la notification test Slack…",
+  "components.Settings.Notifications.NotificationsSlack.toastSlackTestFailed": "L'envoi de la notification test Slack a échoué.",
+  "components.Settings.Notifications.NotificationsPushbullet.accessTokenTip": "Créer un jeton à partir de vos <PushbulletSettingsLink>paramètres de compte</PushbulletSettingsLink>",
+  "components.Settings.Notifications.NotificationsLunaSea.webhookUrlTip": "Votre <LunaSeaLink>URL de webhook de notification</LunaSeaLink> basée sur l'utilisateur ou l'appareil",
   "components.QuotaSelector.seasons": "{count, plural, one {saison} other {saisons}}",
   "components.QuotaSelector.movies": "{count, plural, one {film} other {films}}",
-  "components.QuotaSelector.movieRequests": "{quotaLimit} <quotaUnits>{movies} par {quotaDays} {days}</quotaUnits>",
+  "components.QuotaSelector.movieRequests": "{quotaLimit} <quotaUnits>{movies} tous les {quotaDays} {days}</quotaUnits>",
   "components.QuotaSelector.days": "{count, plural, one {jour} other {jours}}",
   "components.Settings.SettingsAbout.betawarning": "Ceci est un logiciel BÊTA. Les fonctionnalités peuvent être non opérationnelles ou instables. Veuillez signaler tout problème sur GitHub !",
   "components.UserProfile.UserSettings.UserNotificationSettings.webpushsettingsfailed": "Échec de l'enregistrement des paramètres de notification Web push.",
@@ -841,29 +831,29 @@
   "components.Settings.Notifications.NotificationsPushover.validationTypes": "Vous devez sélectionner au moins un type de notification",
   "components.Settings.Notifications.NotificationsPushbullet.validationTypes": "Vous devez sélectionner au moins un type de notification",
   "components.Settings.Notifications.NotificationsLunaSea.validationTypes": "Vous devez sélectionner au moins un type de notification",
-  "components.QuotaSelector.tvRequests": "{quotaLimit} <quotaUnits>{seasons} par {quotaDays} {days}</quotaUnits>",
-  "components.NotificationTypeSelector.usermediarequestedDescription": "Soyez averti lorsque d'autres utilisateurs soumettent des demandes de nouveaux médias qui nécessitent une approbation.",
-  "components.NotificationTypeSelector.usermediafailedDescription": "Soyez averti lorsque les demandes de médias ne parviennent pas à être ajoutées à Radarr ou Sonarr.",
-  "components.NotificationTypeSelector.usermediadeclinedDescription": "Recevez une notification lorsque vos demandes de médias sont refusées.",
-  "components.NotificationTypeSelector.usermediaavailableDescription": "Soyez averti lorsque vos demandes de médias deviennent disponibles.",
-  "components.NotificationTypeSelector.usermediaapprovedDescription": "Soyez averti lorsque vos demandes de médias sont approuvées.",
-  "components.NotificationTypeSelector.usermediaAutoApprovedDescription": "Soyez averti lorsque d'autres utilisateurs soumettent de nouvelles demandes de médias qui sont automatiquement approuvées.",
+  "components.QuotaSelector.tvRequests": "{quotaLimit} <quotaUnits>{seasons} tous les {quotaDays} {days}</quotaUnits>",
+  "components.NotificationTypeSelector.usermediarequestedDescription": "Être averti(e) lorsque d'autres utilisateurs soumettent une demande de média qui nécessite une validation.",
+  "components.NotificationTypeSelector.usermediafailedDescription": "Être averti(e) lorsqu'une demande de média n'a pas pu être ajoutée à Radarr ou Sonarr.",
+  "components.NotificationTypeSelector.usermediadeclinedDescription": "Être averti(e) lorsque vos demandes de médias sont refusées.",
+  "components.NotificationTypeSelector.usermediaavailableDescription": "Être averti(e) lorsque vos demandes de médias deviennent disponibles.",
+  "components.NotificationTypeSelector.usermediaapprovedDescription": "Être averti(e) lorsque vos demandes de médias sont validées.",
+  "components.NotificationTypeSelector.usermediaAutoApprovedDescription": "Être averti(e) lorsque des utilisateurs soumettent une demande de média qui est validée automatiquement.",
   "components.MovieDetails.showmore": "Montrer plus",
   "components.MovieDetails.showless": "Montrer moins",
   "components.Layout.LanguagePicker.displaylanguage": "Langue d'affichage",
   "components.UserList.localLoginDisabled": "Le paramètre <strong>Activer la connexion locale</strong> est actuellement désactivé.",
   "components.TvDetails.streamingproviders": "Disponible en streaming sur",
   "components.MovieDetails.streamingproviders": "Actuellement diffusé sur",
-  "components.Settings.Notifications.NotificationsSlack.webhookUrlTip": "Créer une <WebhookLink>Webhook entrant</WebhookLink> intégration",
+  "components.Settings.Notifications.NotificationsSlack.webhookUrlTip": "Créer une intégration <WebhookLink>Webhook entrante</WebhookLink>",
   "components.StatusBadge.status": "{status}",
   "components.Settings.SettingsJobsCache.editJobScheduleSelectorHours": "Toutes les {jobScheduleHours, plural, one {heure} other {{jobScheduleHours} heures}}",
   "components.IssueDetails.IssueComment.areyousuredelete": "Êtes-vous sûr de vouloir supprimer ce commentaire ?",
-  "components.IssueDetails.IssueComment.postedby": "Posté {relativeTime} par {username}",
-  "components.IssueDetails.IssueComment.postedbyedited": "Posté {relativeTime} par {username} (Edité)",
+  "components.IssueDetails.IssueComment.postedby": "Ajouté {relativeTime} par {username}",
+  "components.IssueDetails.IssueComment.postedbyedited": "Ajouté {relativeTime} par {username} (Édité)",
   "components.IssueDetails.IssueComment.validationComment": "Vous devez écrire un message",
   "components.IssueDetails.IssueComment.delete": "Supprimer le commentaire",
   "components.IssueDetails.IssueComment.edit": "Éditer le commentaire",
-  "components.IssueDetails.nocomments": "Aucun commentaires.",
+  "components.IssueDetails.nocomments": "Aucun commentaire.",
   "components.IssueDetails.openedby": "#{issueId} ouvert {relativeTime} par {username}",
   "components.IssueDetails.problemepisode": "Épisode concerné",
   "components.IssueDetails.problemseason": "Saison concernée",
@@ -871,29 +861,28 @@
   "components.IssueDetails.reopenissueandcomment": "Rouvrir avec un commentaire",
   "components.IssueDetails.season": "Saison {seasonNumber}",
   "components.IssueModal.CreateIssueModal.episode": "Épisode {episodeNumber}",
-  "components.IssueModal.CreateIssueModal.issomethingwrong": "Y a-t-il un problème avec {title} ?",
   "components.IssueModal.CreateIssueModal.problemepisode": "Épisode concerné",
   "components.IssueModal.CreateIssueModal.problemseason": "Saison affectée",
   "components.IssueModal.CreateIssueModal.providedetail": "Fournissez une explication détaillée du problème.",
-  "components.NotificationTypeSelector.userissueresolvedDescription": "Recevez une notification lorsque les problèmes que vous avez signalés sont résolus.",
+  "components.NotificationTypeSelector.userissueresolvedDescription": "Être averti(e) lorsqu'un problème que vous avez signalé est résolu.",
   "components.PermissionEdit.manageissues": "Gérer les problèmes",
   "components.PermissionEdit.viewissues": "Afficher les problèmes",
-  "components.PermissionEdit.viewissuesDescription": "Accorder la permission de consulter les problèmes liés aux médias signalés par d'autres utilisateurs.",
+  "components.PermissionEdit.viewissuesDescription": "Autorise à consulter les problèmes liés aux médias signalés par d'autres utilisateurs.",
   "components.IssueModal.CreateIssueModal.toastFailedCreate": "Un problème est survenu lors de la soumission du problème.",
   "components.IssueModal.CreateIssueModal.toastviewissue": "Afficher le problème",
-  "components.IssueModal.CreateIssueModal.toastSuccessCreate": "Le signalement du problème pour <strong>{title}</strong> a bien été effectué !",
+  "components.IssueModal.CreateIssueModal.toastSuccessCreate": "Le signalement du problème pour <strong>{title}</strong> a été soumis avec succès !",
   "components.IssueModal.CreateIssueModal.whatswrong": "Qu’est-ce qui ne va pas ?",
   "components.Layout.Sidebar.issues": "Problèmes",
   "components.ManageSlideOver.downloadstatus": "Téléchargement(s)",
-  "components.ManageSlideOver.manageModalNoRequests": "Aucune demandes.",
+  "components.ManageSlideOver.manageModalNoRequests": "Aucune demande.",
   "components.ManageSlideOver.manageModalRequests": "Demandes",
   "components.ManageSlideOver.manageModalTitle": "Gérer {mediaType}",
-  "components.ManageSlideOver.manageModalClearMediaWarning": "* Ceci supprimera de manière irréversible toutes les données de ce {mediaType}, y compris les demandes éventuelles. Si cet élément existe dans votre bibliothèque Plex, les informations sur le média seront recréées lors de la prochaine analyse.",
-  "components.ManageSlideOver.tvshow": "séries",
-  "components.NotificationTypeSelector.issuecomment": "Les commentaires du problème",
-  "components.NotificationTypeSelector.issuecreatedDescription": "Envoyez des notifications lorsque des problèmes sont signalés.",
+  "components.ManageSlideOver.manageModalClearMediaWarning": "* Ceci supprimera de manière irréversible toutes les données de ce(tte) {mediaType}, y compris les demandes éventuelles. Si cet élément existe dans votre bibliothèque Plex, les informations sur le média seront recréées lors de la prochaine analyse.",
+  "components.ManageSlideOver.tvshow": "série",
+  "components.NotificationTypeSelector.issuecomment": "Commentaires du problème",
+  "components.NotificationTypeSelector.issuecreatedDescription": "Envoyer des notifications lorsqu'un problème est signalé.",
   "components.PermissionEdit.createissues": "Signaler des problèmes",
-  "components.PermissionEdit.createissuesDescription": "Accordez la permission de signaler les problèmes liés aux médias.",
+  "components.PermissionEdit.createissuesDescription": "Autorise à signaler les problèmes liés aux médias.",
   "i18n.resolved": "Résolu",
   "components.IssueDetails.toasteditdescriptionfailed": "Un problème est survenu lors de l'édition de la description du problème.",
   "components.IssueDetails.toastissuedeletefailed": "Un problème est survenu lors de la suppression du problème.",
@@ -901,10 +890,10 @@
   "components.IssueDetails.IssueDescription.description": "Description",
   "components.IssueDetails.IssueDescription.edit": "Éditer la description",
   "components.IssueDetails.allepisodes": "Tous les épisodes",
-  "components.IssueDetails.closeissue": "Clôturer le problème",
+  "components.IssueDetails.closeissue": "Clore le problème",
   "components.IssueDetails.IssueDescription.deleteissue": "Supprimer le problème",
   "components.IssueDetails.episode": "Épisode {episodeNumber}",
-  "components.IssueDetails.closeissueandcomment": "Clôturer avec un commentaire",
+  "components.IssueDetails.closeissueandcomment": "Clore avec un commentaire",
   "components.IssueDetails.lastupdated": "Dernière mise à jour",
   "components.IssueDetails.comments": "Commentaires",
   "components.IssueDetails.deleteissueconfirm": "Êtes-vous sûr de vouloir supprimer ce problème ?",
@@ -913,15 +902,15 @@
   "components.IssueDetails.deleteissue": "Supprimer le problème",
   "components.IssueDetails.leavecomment": "Commenter",
   "components.IssueDetails.openinarr": "Ouvrir dans {arr}",
-  "components.IssueDetails.toasteditdescriptionsuccess": "La modification de la description du problème a bien été réalisée !",
-  "components.IssueDetails.toaststatusupdated": "Le statut du problème a bien été mis à jour !",
-  "components.IssueDetails.toastissuedeleted": "Le problème a été supprimé avec succès !",
+  "components.IssueDetails.toasteditdescriptionsuccess": "La description du problème a été éditée avec succès !",
+  "components.IssueDetails.toaststatusupdated": "Le statut du problème a été mis à jour avec succès !",
+  "components.IssueDetails.toastissuedeleted": "Le problème a été supprimé avec succès !",
   "components.IssueDetails.toaststatusupdatefailed": "Un problème est survenu lors de la mise à jour du statut du problème.",
   "components.IssueDetails.unknownissuetype": "Inconnu",
   "components.IssueList.IssueItem.viewissue": "Afficher le problème",
   "components.IssueList.sortAdded": "Plus récents",
   "components.IssueList.sortModified": "Dernière modification",
-  "components.NotificationTypeSelector.userissuecommentDescription": "Recevez une notification lorsque les problèmes que vous avez signalés reçoivent de nouveaux commentaires.",
+  "components.NotificationTypeSelector.userissuecommentDescription": "Être averti(e) lorsqu'un problème que vous avez signalé reçoit de nouveaux commentaires.",
   "components.IssueList.IssueItem.issuetype": "Type",
   "components.IssueList.IssueItem.issuestatus": "Statut",
   "components.IssueList.IssueItem.opened": "Ouvert",
@@ -946,75 +935,75 @@
   "components.ManageSlideOver.markavailable": "Marquer comme disponible",
   "components.Settings.SettingsAbout.runningDevelop": "Vous utilisez la branche <code>develop</code> d'Overseerr, qui n'est recommandée que pour ceux qui contribuent au développement ou qui aident aux tests et correctifs.",
   "components.ManageSlideOver.openarr": "Ouvrir dans {arr}",
-  "components.NotificationTypeSelector.adminissuecommentDescription": "Soyez averti lorsque d'autres utilisateurs commentent sur les problèmes.",
-  "components.NotificationTypeSelector.issuecommentDescription": "Envoyez des notifications lorsque les problèmes reçoivent de nouveaux commentaires.",
+  "components.NotificationTypeSelector.adminissuecommentDescription": "Être averti(e) lorsque d'autres utilisateurs commentent sur un problème.",
+  "components.NotificationTypeSelector.issuecommentDescription": "Envoyer des notifications lorsqu'un problème reçoit de nouveaux commentaires.",
   "components.NotificationTypeSelector.issueresolved": "Problème résolu",
-  "components.ManageSlideOver.openarr4k": "Ouvrir en 4K {arr}",
+  "components.ManageSlideOver.openarr4k": "Ouvrir dans {arr} 4K",
   "components.NotificationTypeSelector.issuecreated": "Problème signalé",
-  "components.NotificationTypeSelector.issueresolvedDescription": "Envoyez des notifications lorsque les problèmes sont résolus.",
+  "components.NotificationTypeSelector.issueresolvedDescription": "Envoyer des notifications lorsqu'un problème est résolu.",
   "components.Settings.SettingsJobsCache.editJobSchedulePrompt": "Fréquence",
   "components.Settings.SettingsJobsCache.jobScheduleEditSaved": "Tâche modifiée avec succès !",
   "i18n.open": "Ouvert",
   "components.Settings.SettingsJobsCache.editJobSchedule": "Modifier la tâche",
-  "components.NotificationTypeSelector.userissuecreatedDescription": "Recevez une notification lorsque d’autres utilisateurs signalent des problèmes.",
-  "components.PermissionEdit.manageissuesDescription": "Accorder la permission de gérer les problèmes relatifs aux médias.",
+  "components.NotificationTypeSelector.userissuecreatedDescription": "Être averti(e) lorsque d’autres utilisateurs signalent des problèmes.",
+  "components.PermissionEdit.manageissuesDescription": "Autorise à gérer les problèmes liés aux médias.",
   "components.Settings.SettingsJobsCache.jobScheduleEditFailed": "Un problème est survenu lors de l'enregistrement de la tâche.",
   "components.Settings.SettingsJobsCache.editJobScheduleSelectorMinutes": "Toutes les {jobScheduleMinutes, plural, one {minute} other {{jobScheduleMinutes} minutes}}",
-  "components.IssueDetails.openin4karr": "Ouvrir en 4K {arr}",
-  "components.IssueDetails.play4konplex": "Lire sur Plex en 4K",
+  "components.IssueDetails.openin4karr": "Ouvrir dans {arr} 4K",
+  "components.IssueDetails.play4konplex": "Lire en 4K sur Plex",
   "components.IssueDetails.playonplex": "Lire sur Plex",
   "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletAccessToken": "Jeton d'accès",
   "components.IssueList.IssueItem.seasons": "{seasonCount, plural, one {Saison} other {Saisons}}",
-  "components.NotificationTypeSelector.adminissuereopenedDescription": "Être notifié lorsqu'un problème est ré-ouvert par d'autres utilisateurs.",
-  "components.NotificationTypeSelector.adminissueresolvedDescription": "Être notifié lorsqu'un problème est résolu par d'autres utilisateurs.",
-  "components.NotificationTypeSelector.issuereopenedDescription": "Envoyer des notifications lorsqu'un problème est ré-ouvert.",
-  "components.NotificationTypeSelector.userissuereopenedDescription": "Être notifié lorsqu'un problème que vous avez signalé a été ré-ouvert.",
+  "components.NotificationTypeSelector.adminissuereopenedDescription": "Être averti(e) lorsqu'un problème est ré-ouvert par d'autres utilisateurs.",
+  "components.NotificationTypeSelector.adminissueresolvedDescription": "Être averti(e) lorsqu'un problème est résolu par d'autres utilisateurs.",
+  "components.NotificationTypeSelector.issuereopenedDescription": "Envoyer des notifications lorsqu'un problème est rouvert.",
+  "components.NotificationTypeSelector.userissuereopenedDescription": "Être averti(e) lorsqu'un problème que vous avez signalé a été rouvert.",
   "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletsettingsfailed": "Les paramètres de notification Pushbullet n'ont pas été sauvegardés correctement.",
   "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletsettingssaved": "Les paramètres de notification Pushbullet ont été sauvegardés correctement !",
-  "components.UserProfile.UserSettings.UserNotificationSettings.pushoverApplicationToken": "Jeton API de l'application",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoverApplicationToken": "Jeton API d'application",
   "components.UserProfile.UserSettings.UserNotificationSettings.pushoverApplicationTokenTip": "<ApplicationRegistrationLink>Enregistrer une application</ApplicationRegistrationLink> à utiliser avec {applicationTitle}",
   "components.UserProfile.UserSettings.UserNotificationSettings.validationPushoverApplicationToken": "Vous devez fournir un jeton d'application valide",
   "components.IssueModal.CreateIssueModal.extras": "Extras",
-  "components.UserProfile.UserSettings.UserNotificationSettings.pushoversettingsfailed": "Les paramètres de notification Pushover n'ont pas été sauvegardés correctement.",
-  "components.UserProfile.UserSettings.UserNotificationSettings.pushoversettingssaved": "Les paramètres de notification Pushover ont été sauvegardés correctement !",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoversettingsfailed": "Les paramètres de notification Pushover n'ont pas pu être enregistrés.",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoversettingssaved": "Paramètres de notification Pushover enregistrés avec succès !",
   "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletAccessTokenTip": "Créer un jeton depuis les <PushbulletSettingsLink>paramètres de votre compte</PushbulletSettingsLink>",
   "components.ManageSlideOver.manageModalIssues": "Problèmes ouverts",
-  "components.UserProfile.UserSettings.UserNotificationSettings.validationPushoverUserKey": "Vous devez fournir une clef d'utilisateur ou de groupe valide",
-  "components.NotificationTypeSelector.issuereopened": "Problème réouvert",
+  "components.UserProfile.UserSettings.UserNotificationSettings.validationPushoverUserKey": "Vous devez fournir une clé d'utilisateur ou de groupe valide",
+  "components.NotificationTypeSelector.issuereopened": "Problème rouvert",
   "components.UserProfile.UserSettings.UserNotificationSettings.validationPushbulletAccessToken": "Vous devez fournir un jeton d'accès",
   "components.IssueList.IssueItem.episodes": "{episodeCount, plural, one {Épisode} other {Épisodes}}",
-  "components.UserProfile.UserSettings.UserNotificationSettings.pushoverUserKey": "Clef d'utilisateur ou de groupe",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoverUserKey": "Clé d'utilisateur ou de groupe",
   "components.UserProfile.UserSettings.UserNotificationSettings.pushoverUserKeyTip": "Votre <UsersGroupsLink>identifiant d'utilisateur ou de groupe</UsersGroupsLink> à 30 caractères",
-  "components.RequestModal.requestmovies4k": "Demander {count} {count, plural, one {Film} autre {Films}} en 4K",
-  "components.RequestModal.selectmovies": "Selecter Film(s)",
+  "components.RequestModal.requestmovies4k": "Demander {count} {count, plural, one {film} autre {films}} en 4K",
+  "components.RequestModal.selectmovies": "Sélectionner le(s) film(s)",
   "components.IssueDetails.commentplaceholder": "Ajouter un commentaire…",
   "components.MovieDetails.productioncountries": "Pays de production",
   "components.Settings.RadarrModal.announced": "Annoncé",
-  "components.RequestModal.approve": "Approuver la demande",
-  "components.RequestModal.requestseasons4k": "Demander {seasonCount} {seasonCount, plural, one {Saison} other {Saisons}} en 4K",
-  "components.RequestModal.requestmovies": "Demander {count} {count, plural, one {Film} other {Films}}",
-  "components.RequestModal.requestApproved": "Demande de <strong>{title}</strong> approuvée !",
+  "components.RequestModal.approve": "Valider la demande",
+  "components.RequestModal.requestseasons4k": "Demander {seasonCount} {seasonCount, plural, one {saison} other {saisons}} en 4K",
+  "components.RequestModal.requestmovies": "Demander {count} {count, plural, one {film} other {films}}",
+  "components.RequestModal.requestApproved": "Demande pour <strong>{title}</strong> validée !",
   "components.Settings.RadarrModal.inCinemas": "Au cinéma",
   "components.Settings.RadarrModal.released": "Disponible",
   "components.TvDetails.productioncountries": "Pays de production",
   "components.Settings.Notifications.NotificationsGotify.agentenabled": "Activer l'agent",
   "components.Settings.Notifications.NotificationsGotify.gotifysettingsfailed": "Les paramètres de notification Gotify n'ont pas pu être enregistrés.",
-  "components.Settings.Notifications.NotificationsGotify.gotifysettingssaved": "Les paramètres de notification de Gotify ont été sauvegardés avec succès !",
-  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestSending": "Envoi de la notification test pour Gotify…",
+  "components.Settings.Notifications.NotificationsGotify.gotifysettingssaved": "Paramètres de notification de Gotify sauvegardés avec succès !",
+  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestSending": "Envoi de la notification test Gotify…",
   "components.Settings.Notifications.NotificationsGotify.toastGotifyTestSuccess": "Notification test Gotify envoyée !",
-  "components.Settings.Notifications.NotificationsGotify.token": "Jeton d'autorisation de l'application",
+  "components.Settings.Notifications.NotificationsGotify.token": "Jeton d'application",
   "components.Settings.Notifications.NotificationsGotify.url": "URL du serveur",
   "components.Settings.Notifications.NotificationsGotify.validationTypes": "Vous devez sélectionner au moins un type de notification",
   "components.Settings.Notifications.NotificationsGotify.validationUrlRequired": "Vous devez fournir une URL valide",
   "components.Settings.Notifications.enableMentions": "Activer les mentions",
   "i18n.import": "Importer",
   "i18n.importing": "Importation…",
-  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestFailed": "L'envoi de la notification test de Gotify a échoué.",
-  "components.Settings.Notifications.NotificationsGotify.validationTokenRequired": "Vous devez fournir un jeton d'accès pour l'application",
+  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestFailed": "L'envoi de la notification test Gotify a échoué.",
+  "components.Settings.Notifications.NotificationsGotify.validationTokenRequired": "Vous devez fournir un jeton d'application",
   "components.Settings.Notifications.NotificationsGotify.validationUrlTrailingSlash": "L'URL ne doit pas se terminer par un slash",
   "components.ManageSlideOver.manageModalAdvanced": "Avancé",
   "components.ManageSlideOver.manageModalMedia4k": "Média(s) 4K",
-  "components.ManageSlideOver.markallseasons4kavailable": "Marquer toutes les saisons comme disponible en 4K",
+  "components.ManageSlideOver.markallseasons4kavailable": "Marquer toutes les saisons comme disponibles en 4K",
   "components.ManageSlideOver.playedby": "Joué par",
   "components.Settings.validationUrlTrailingSlash": "L'URL ne doit pas ce terminer par un slash",
   "components.Settings.externalUrl": "URL externe",
@@ -1029,16 +1018,103 @@
   "components.UserProfile.recentlywatched": "Vu récemment",
   "components.ManageSlideOver.opentautulli": "Ouvrir dans Tautulli",
   "components.ManageSlideOver.pastdays": "{days, number} derniers jours",
-  "components.ManageSlideOver.plays": "<strong>{playCount, number}</strong> {playCount, plural, one {play} other {plays}}",
-  "components.Settings.Notifications.NotificationsPushbullet.channelTag": "Balise de chaîne",
+  "components.ManageSlideOver.plays": "<strong>{playCount, number}</strong> {playCount, plural, one {lecture} other {lectures}}",
+  "components.Settings.Notifications.NotificationsPushbullet.channelTag": "Étiquette de canal",
   "components.ManageSlideOver.alltime": "Tout le temps",
   "components.ManageSlideOver.manageModalMedia": "Média(s)",
-  "components.ManageSlideOver.markallseasonsavailable": "Marquer toutes les saisons comme disponible",
+  "components.ManageSlideOver.markallseasonsavailable": "Marquer toutes les saisons comme disponibles",
   "components.Settings.validationUrlBaseTrailingSlash": "L'URL de base ne doit pas ce terminer par un slash",
   "components.Settings.tautulliSettingsDescription": "Configuration optionnelle pour votre serveur Tautulli. Overseerr va récupérer l'historique de visionnage de votre Plex depuis Tautulli.",
   "components.UserList.newplexsigninenabled": "L'option <strong>Autoriser nouvelle connexion Plex</strong> est actuellement activée. Les utilisateurs Plex disposant d'un accès à la librairie n'ont pas besoin d'être importés pour pouvoir ce connecter.",
   "components.UserProfile.UserSettings.UserGeneralSettings.discordId": "ID utilisateur Discord",
   "components.UserProfile.UserSettings.UserGeneralSettings.discordIdTip": "Le <FindDiscordIdLink>numéro d'identification à plusieurs chiffres</FindDiscordIdLink> est associé avec votre compte Discord",
   "components.UserProfile.UserSettings.UserGeneralSettings.validationDiscordId": "Vous devez fournir un ID utilisateur Discord valide",
-  "components.Settings.SettingsAbout.appDataPath": "Répertoire de données"
+  "components.Settings.SettingsAbout.appDataPath": "Répertoire de données",
+  "components.MovieDetails.digitalrelease": "Sortie numérique",
+  "components.MovieDetails.physicalrelease": "Sortie physique",
+  "components.PermissionEdit.autorequest": "Demande automatique",
+  "components.Discover.DiscoverWatchlist.discoverwatchlist": "Ta Plex Watchlist",
+  "components.Discover.plexwatchlist": "Ta Plex Watchlist",
+  "components.MovieDetails.theatricalrelease": "Sortie en salles",
+  "components.StatusChecker.reloadApp": "Recharger {applicationTitle}",
+  "components.PermissionEdit.viewrecent": "Voir les ajouts récents",
+  "components.PermissionEdit.viewrecentDescription": "Autorise à voir la liste des médias ajoutés récemment.",
+  "i18n.restartRequired": "Redémarrage nécessaire",
+  "components.RequestCard.tmdbid": "TMDB ID",
+  "components.RequestCard.tvdbid": "TheTVDB ID",
+  "components.RequestList.RequestItem.tmdbid": "TMDB ID",
+  "components.RequestList.RequestItem.tvdbid": "TheTVDB ID",
+  "components.NotificationTypeSelector.mediaautorequested": "Demande soumise automatiquement",
+  "components.PermissionEdit.autorequestMoviesDescription": "Autorise l'envoi de demande automatique pour les médias non-4K via la Plex Watchlist.",
+  "components.PermissionEdit.autorequestSeriesDescription": "Autorise l'envoi de demande automatique pour les médias non-4K via la Plex Watchlist.",
+  "components.StatusChecker.appUpdatedDescription": "Veuillez cliquer sur le bouton ci-dessous pour recharger l'application.",
+  "components.StatusChecker.restartRequiredDescription": "Veuillez redémarrer le serveur pour appliquer les paramètres mis à jour.",
+  "components.TitleCard.cleardata": "Effacer les données",
+  "components.TitleCard.mediaerror": "{mediaType} non trouvé",
+  "components.TitleCard.tmdbid": "TMDB ID",
+  "components.TitleCard.tvdbid": "TheTVDB ID",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmovies": "Demander automatiquement les films",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseries": "Demander automatiquement les Séries",
+  "components.PermissionEdit.autorequestDescription": "Autorise l'envoi de demande automatique pour les médias non-4K via la Plex Watchlist.",
+  "components.PermissionEdit.autorequestMovies": "Demander automatiquement les Films",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseriestip": "Demande automatiquement les séries de ta <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink>",
+  "components.PermissionEdit.autorequestSeries": "Demander automatiquement les Séries",
+  "components.Settings.SettingsJobsCache.plex-watchlist-sync": "Synchronisation de la Plex Watchlist",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmoviestip": "Demande automatiquement les films sur ta <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink>",
+  "components.NotificationTypeSelector.mediaautorequestedDescription": "Recevez une notification lorsque de nouvelles demandes de médias sont automatiquement soumises pour des éléments de votre Plex Watchlist.",
+  "components.StatusChecker.restartRequired": "Redémarrage du serveur requis",
+  "components.StatusChecker.appUpdated": "{applicationTitle} mis à jour",
+  "components.Settings.SettingsLogs.viewdetails": "Voir les détails",
+  "components.Settings.advancedTooltip": "Une configuration incorrecte de ce paramètre peut entraîner un dysfonctionnement",
+  "components.Settings.experimentalTooltip": "L'activation de ce paramètre peut entraîner un comportement inattendu de l'application",
+  "components.Discover.DiscoverWatchlist.watchlist": "Plex Watchlist",
+  "components.PermissionEdit.viewwatchlists": "Voir Plex Watchlists",
+  "components.TvDetails.reportissue": "Signaler un problème",
+  "components.AirDateBadge.airedrelative": "Diffusé {relativeTime}",
+  "components.AirDateBadge.airsrelative": "Diffusion {relativeTime}",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.movierequests": "Demandes de films",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.seriesrequests": "Demandes de séries",
+  "components.Layout.UserDropdown.requests": "Demandes",
+  "components.MovieDetails.managemovie": "Gérer le film",
+  "components.MovieDetails.reportissue": "Signaler un problème",
+  "components.TvDetails.episodeCount": "{episodeCount, plural, one {# épisode} sur {# épisodes}}",
+  "components.TvDetails.manageseries": "Gérer les séries",
+  "components.TvDetails.seasonnumber": "Saison {seasonNumber}",
+  "components.TvDetails.seasonstitle": "Saisons",
+  "components.TvDetails.status4k": "4K {status}",
+  "components.MovieDetails.rtaudiencescore": "Note d'audience de Rotten Tomatoes",
+  "components.MovieDetails.rtcriticsscore": "Rotten Tomatoes Tomatomètre",
+  "components.MovieDetails.tmdbuserscore": "Note des utilisateurs TMDB",
+  "components.PermissionEdit.viewwatchlistsDescription": "Autorise à voir la Plex Watchlist des autres utilisateurs.",
+  "components.RequestBlock.approve": "Approuver la demande",
+  "components.RequestBlock.decline": "Refuser la demande",
+  "components.RequestBlock.delete": "Supprimer la demande",
+  "components.RequestBlock.edit": "Modifier la demande",
+  "components.RequestBlock.languageprofile": "Profil de langue",
+  "components.RequestBlock.lastmodifiedby": "Dernière modification par",
+  "components.RequestBlock.requestdate": "Date de la demande",
+  "components.RequestBlock.requestedby": "Demandé par",
+  "components.RequestCard.approverequest": "Approuver la demande",
+  "components.RequestCard.cancelrequest": "Annuler la demande",
+  "components.RequestCard.declinerequest": "Refuser la demande",
+  "components.StatusBadge.managemedia": "Gérer {mediaType}",
+  "components.StatusBadge.openinarr": "Ouvrir dans {arr}",
+  "components.StatusBadge.playonplex": "Lire sur Plex",
+  "components.TvDetails.Season.somethingwentwrong": "Une erreur s'est produite lors de la récupération des données de la saison.",
+  "components.TvDetails.rtaudiencescore": "Note d'audience de Rotten Tomatoes",
+  "components.TvDetails.rtcriticsscore": "Rotten Tomatoes Tomatomètre",
+  "components.TvDetails.tmdbuserscore": "Note des utilisateurs TMDB",
+  "components.UserProfile.plexwatchlist": "Plex Watchlist",
+  "components.RequestCard.editrequest": "Modifier la demande",
+  "components.Settings.restartrequiredTooltip": "Overseerr doit être redémarré pour que les modifications de ce paramètre prennent effet",
+  "components.Settings.deleteServer": "Supprimer {serverType} serveur",
+  "components.RequestModal.requestcollection4ktitle": "Demander la collection en 4K",
+  "components.Discover.emptywatchlist": "Les médias ajoutés à ta <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink>  apparaîtront ici.",
+  "components.RequestModal.requestcollectiontitle": "Demander la collection",
+  "components.UserProfile.emptywatchlist": "Les médias ajoutés à ta <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink> apparaîtront ici.",
+  "components.RequestModal.SearchByNameModal.nomatches": "Nous n'avons pas pu trouver de correspondance pour cette série.",
+  "components.RequestModal.requestmovie4ktitle": "Demander le film en 4K",
+  "components.RequestModal.requestmovietitle": "Demander le film",
+  "components.RequestModal.requestseries4ktitle": "Demander la série en 4K",
+  "components.RequestModal.requestseriestitle": "Demander la série"
 }
diff --git a/src/i18n/locale/he.json b/src/i18n/locale/he.json
new file mode 100644
index 00000000..4f1942b4
--- /dev/null
+++ b/src/i18n/locale/he.json
@@ -0,0 +1,5 @@
+{
+  "components.ManageSlideOver.alltime": "על הזמן",
+  "components.Login.validationemailrequired": "חובה לספק כתובת מייל חוקית",
+  "components.NotificationTypeSelector.userissuereopenedDescription": "קבל התראה כשבעיות שפתחת נפתחות מחדש."
+}
diff --git a/src/i18n/locale/hi.json b/src/i18n/locale/hi.json
new file mode 100644
index 00000000..0967ef42
--- /dev/null
+++ b/src/i18n/locale/hi.json
@@ -0,0 +1 @@
+{}
diff --git a/src/i18n/locale/hr.json b/src/i18n/locale/hr.json
new file mode 100644
index 00000000..710ba1fb
--- /dev/null
+++ b/src/i18n/locale/hr.json
@@ -0,0 +1,264 @@
+{
+  "components.CollectionDetails.numberofmovies": "{count} Filmovi",
+  "components.CollectionDetails.overview": "Pregled",
+  "components.CollectionDetails.requestcollection4k": "Zahtjev za serijalom u 4K",
+  "components.CollectionDetails.requestcollection": "Zahtjev za serijalom",
+  "components.Discover.DiscoverMovieGenre.genreMovies": "{genre} Filmovi",
+  "components.Discover.DiscoverMovieLanguage.languageMovies": "{language} Filmovi",
+  "components.Discover.DiscoverNetwork.networkSeries": "{network} Serije",
+  "components.Discover.DiscoverStudio.studioMovies": "{studio} Filmovi",
+  "components.Discover.discover": "Otkrivanje",
+  "components.Discover.discovermovies": "Popularni Filmovi",
+  "components.Discover.discovertv": "Popularne Serije",
+  "components.Discover.DiscoverTvGenre.genreSeries": "{genre} Serije",
+  "components.Discover.DiscoverTvLanguage.languageSeries": "{language} Serije",
+  "components.Discover.DiscoverWatchlist.discoverwatchlist": "Vaš Plex popis za gledanje",
+  "components.Discover.MovieGenreList.moviegenres": "Filmski Žanrovi",
+  "components.Discover.StudioSlider.studios": "Studio",
+  "components.Discover.TvGenreList.seriesgenres": "Serijski Žanrovi",
+  "components.Discover.TvGenreSlider.tvgenres": "Serijski Žanrovi",
+  "components.Discover.plexwatchlist": "Vaš Plex popis za gledanje",
+  "components.Discover.popularmovies": "Popularni Filmovi",
+  "components.Discover.recentlyAdded": "Nedavno Dodano",
+  "components.Discover.recentrequests": "Nedavni Zahtjevi",
+  "components.Discover.trending": "Popularno",
+  "components.IssueDetails.IssueComment.edit": "Uredi Komentar",
+  "components.IssueDetails.IssueDescription.deleteissue": "Izbriši problem",
+  "components.IssueDetails.IssueDescription.description": "Opis",
+  "components.IssueDetails.IssueDescription.edit": "Uredi opis",
+  "components.IssueDetails.allepisodes": "Sve Epizode",
+  "components.IssueDetails.closeissue": "Zatvori Problem",
+  "components.IssueDetails.closeissueandcomment": "Zatvori s komentarom",
+  "components.IssueDetails.commentplaceholder": "Dodaj komentar…",
+  "components.IssueDetails.comments": "Komentari",
+  "components.IssueDetails.deleteissue": "Izbriši problem",
+  "components.AirDateBadge.airedrelative": "Emitirano {relativeTime}",
+  "components.AirDateBadge.airsrelative": "Emitiranje {relativeTime}",
+  "components.AppDataWarning.dockerVolumeMissingDescription": "Navedeni <code>{appDataPath}</code> mapirani volumen nije ispravno podešen. Svi podaci će biti izbrisani kada se spremnik (container) zaustavi ili ponovno pokrene.",
+  "components.Discover.DiscoverWatchlist.watchlist": "Plex popis za gledanje",
+  "components.Discover.emptywatchlist": "Filmovi dodani na Vaš <PlexWatchlistSupportLink> popis za gledanje </PlexWatchlistSupportLink> pojaviti će se ovdje.",
+  "components.Discover.MovieGenreSlider.moviegenres": "Filmski Žanrovi",
+  "components.Discover.NetworkSlider.networks": "Striming servisi",
+  "components.Discover.populartv": "Popularne Serije",
+  "components.Discover.upcomingtv": "Nadolazeće Serije",
+  "components.Discover.upcoming": "Nadolazeći Filmovi",
+  "components.Discover.upcomingmovies": "Nadolazeći Filmovi",
+  "components.DownloadBlock.estimatedtime": "Procijenjeno {time}",
+  "components.IssueDetails.IssueComment.areyousuredelete": "Jeste li sigurni da želite izbrisati ovaj komentar?",
+  "components.IssueDetails.IssueComment.delete": "Izbriši Komentar",
+  "components.IssueDetails.IssueComment.postedby": "Objavljeno u {relativeTime} od korisnika {username}",
+  "components.IssueDetails.IssueComment.validationComment": "Morate unijeti poruku",
+  "components.IssueDetails.IssueComment.postedbyedited": "Objavljeno u {relativeTime} od korisnika {username} (Uređeno)",
+  "components.IssueDetails.allseasons": "Sve Sezone",
+  "components.IssueDetails.episode": "Epizode {episodeNumber}",
+  "components.IssueDetails.deleteissueconfirm": "Jeste li sigurni da želite izbrisati ovaj problem?",
+  "components.IssueDetails.lastupdated": "Zadnje ažurirano",
+  "components.IssueDetails.leavecomment": "Komentar",
+  "components.IssueDetails.nocomments": "Bez komentara.",
+  "components.IssueDetails.openedby": "#{issueId} otvoren u {relativeTime} od korisnka {username}",
+  "components.IssueDetails.openin4karr": "Otvoren u 4K {arr}",
+  "components.IssueDetails.openinarr": "Otvoren u {arr}",
+  "components.IssueDetails.toasteditdescriptionfailed": "Nešto nije u redu prilikom uređivanja opisa problema.",
+  "components.IssueModal.CreateIssueModal.allepisodes": "Sve epizode",
+  "components.IssueDetails.toastissuedeleted": "Problem je uspješno izbrisan!",
+  "components.IssueDetails.unknownissuetype": "Nepoznato",
+  "components.IssueList.issues": "Problem",
+  "components.IssueList.IssueItem.openeduserdate": "{date} od korinika {user}",
+  "components.IssueModal.CreateIssueModal.allseasons": "Sve sezone",
+  "components.IssueModal.issueOther": "Ostalo",
+  "components.IssueModal.issueAudio": "Zvuk",
+  "components.IssueModal.issueSubtitles": "Podnaslov",
+  "components.IssueModal.issueVideo": "Video",
+  "components.IssueList.IssueItem.seasons": "{seasonCount, plural, one {Sezona} other {Sezone}}",
+  "components.Layout.UserDropdown.myprofile": "Profil",
+  "components.Layout.UserDropdown.requests": "Zahtjevi",
+  "components.Layout.VersionStatus.streamstable": "Overseerr Stabilan",
+  "components.Login.password": "Zaporka",
+  "components.ManageSlideOver.openarr4k": "Otvori 4K u {arr}-u",
+  "components.ManageSlideOver.pastdays": "Proteklih {days, number} dana",
+  "components.Login.signinwithplex": "Koristite svoj Plex račun",
+  "components.ManageSlideOver.movie": "film",
+  "components.Login.validationemailrequired": "Morate unijeti valjanu adresu e-pošte",
+  "components.ManageSlideOver.manageModalRequests": "Zahtjevi",
+  "components.ManageSlideOver.manageModalClearMediaWarning": "* Ovo će nepovratno ukloniti sve podatke za ovaj {mediaType}, uključujući sve zahtjeve. Ako ova stavka postoji u vašoj Plex biblioteci, informacije o medijima ponovno će se stvoriti tijekom sljedećeg skeniranja.",
+  "components.ManageSlideOver.manageModalMedia4k": "4K Mediji",
+  "components.ManageSlideOver.manageModalNoRequests": "Nema zahtjeva.",
+  "components.ManageSlideOver.manageModalMedia": "Mediji",
+  "components.ManageSlideOver.manageModalTitle": "Upravljanje {mediaType}",
+  "components.ManageSlideOver.mark4kavailable": "Označi kao dostupno u 4K",
+  "components.MovieDetails.originaltitle": "Izvorni naslov",
+  "components.MovieDetails.overview": "Pregled",
+  "components.ManageSlideOver.openarr": "Otvori u {arr}-u",
+  "components.MovieDetails.cast": "Postava",
+  "components.MovieDetails.budget": "Proračun",
+  "components.ManageSlideOver.opentautulli": "Otvori u Tautulli-u",
+  "components.MediaSlider.ShowMoreCard.seemore": "Vidi više",
+  "components.MovieDetails.markavailable": "Označi kao dostupno",
+  "components.ManageSlideOver.tvshow": "serije",
+  "components.MovieDetails.productioncountries": "{countryCount, plural, one {Država produkcije} other {Države produkcije}}",
+  "components.MovieDetails.managemovie": "Upravljanje filmom",
+  "components.MovieDetails.playonplex": "Reproduciraj na Plex-u",
+  "components.MovieDetails.overviewunavailable": "Pregled nedostupan.",
+  "components.MovieDetails.reportissue": "Prijavi problem",
+  "components.MovieDetails.revenue": "Prihod",
+  "components.MovieDetails.rtaudiencescore": "Rotten Tomatoes ocjena publike",
+  "components.MovieDetails.showless": "Prikaži manje",
+  "components.MovieDetails.showmore": "Prikaži više",
+  "components.MovieDetails.similar": "Slični naslovi",
+  "components.MovieDetails.streamingproviders": "Trenutačno se prikacuje na",
+  "components.NotificationTypeSelector.issuecommentDescription": "Pošaljite obavijest kada problemi dobiju nove komentare.",
+  "components.NotificationTypeSelector.issueresolved": "Problem riješen",
+  "components.NotificationTypeSelector.issuereopened": "Problem ponovno otvoren",
+  "components.NotificationTypeSelector.issueresolvedDescription": "Pošalji obavijest kada se problem riješi.",
+  "components.NotificationTypeSelector.issuereopenedDescription": "Pošalji obavijest kada se problem ponovno otvori.",
+  "components.NotificationTypeSelector.mediaAutoApproved": "Automatsko odobravanje zahtjeva",
+  "components.IssueDetails.issuepagetitle": "Problem",
+  "components.IssueDetails.issuetype": "Tip",
+  "components.IssueDetails.play4konplex": "Reproduciraj u 4K na Plex-u",
+  "components.IssueDetails.playonplex": "Reproduciraj na Plex-u",
+  "components.IssueDetails.problemseason": "Zahvaćene Sezone",
+  "components.IssueDetails.problemepisode": "Zahvaćene Epizode",
+  "components.IssueDetails.reopenissue": "Ponovno otvorite problem",
+  "components.IssueDetails.reopenissueandcomment": "Ponovno otvori s komentarom",
+  "components.IssueDetails.season": "Sezona {seasonNumber}",
+  "components.IssueDetails.toasteditdescriptionsuccess": "Opis problema je uspješno uređen!",
+  "components.IssueDetails.toastissuedeletefailed": "Nešto nije u redu prilikom brisanja problema.",
+  "components.IssueDetails.toaststatusupdated": "Status problema je uspješno ažuriran!",
+  "components.IssueDetails.toaststatusupdatefailed": "Nešto nije u redu prilikom ažuriranja statusa problema.",
+  "components.IssueList.IssueItem.issuestatus": "Status",
+  "components.IssueList.IssueItem.issuetype": "Vrsta",
+  "components.IssueList.IssueItem.opened": "Otvoren",
+  "components.IssueList.IssueItem.problemepisode": "Zahvaćene Epizode",
+  "components.IssueList.IssueItem.unknownissuetype": "Nepoznato",
+  "components.IssueList.IssueItem.episodes": "{episodeCount, plural, one {Epizoda} other {Epizode}}",
+  "components.IssueList.IssueItem.viewissue": "Pogledaj problem",
+  "components.IssueList.showallissues": "Prikaži sve probleme",
+  "components.IssueList.sortAdded": "Najnoviji",
+  "components.IssueList.sortModified": "Zadnje promjene",
+  "components.IssueModal.CreateIssueModal.episode": "Epizoda {episodeNumber}",
+  "components.IssueModal.CreateIssueModal.extras": "Dodaci",
+  "components.IssueModal.CreateIssueModal.problemepisode": "Zahvaćene epizode",
+  "components.IssueModal.CreateIssueModal.problemseason": "Zahvaćene sezone",
+  "components.IssueModal.CreateIssueModal.providedetail": "Navedite detaljno objašnjenje problema na koji ste naišli.",
+  "components.IssueModal.CreateIssueModal.reportissue": "Prijavite problem",
+  "components.IssueModal.CreateIssueModal.season": "Sezona {seasonNumber}",
+  "components.IssueModal.CreateIssueModal.submitissue": "Pošalji problem",
+  "components.IssueModal.CreateIssueModal.toastFailedCreate": "Nešto nije u redu prilikom slanja problema.",
+  "components.IssueModal.CreateIssueModal.toastSuccessCreate": "Problem prijavljen za <strong>{title}</strong> je uspješno predan!",
+  "components.IssueModal.CreateIssueModal.toastviewissue": "Pogledaj problem",
+  "components.IssueModal.CreateIssueModal.validationMessageRequired": "Morate unijeti opis",
+  "components.IssueModal.CreateIssueModal.whatswrong": "Što nije u redu?",
+  "components.LanguageSelector.languageServerDefault": "Default ({language})",
+  "components.LanguageSelector.originalLanguageDefault": "Svi jezici",
+  "components.Layout.LanguagePicker.displaylanguage": "Jezik prikaza",
+  "components.Layout.SearchInput.searchPlaceholder": "Pretražite filmove i TV",
+  "components.Layout.Sidebar.dashboard": "Otkrivanje",
+  "components.Layout.Sidebar.issues": "Problemi",
+  "components.Layout.Sidebar.requests": "Zahtjevi",
+  "components.Layout.Sidebar.settings": "Postavke",
+  "components.Layout.Sidebar.users": "Korisnici",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.seriesrequests": "Zahtjevi za serije",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.movierequests": "Zahtjevi za filmove",
+  "components.Layout.UserDropdown.settings": "Postavke",
+  "components.Layout.UserDropdown.signout": "Odjavi se",
+  "components.Layout.VersionStatus.outofdate": "Zastarjelo",
+  "components.Layout.VersionStatus.streamdevelop": "Overseerr Razvoj",
+  "components.Login.email": "Adresa e-pošte",
+  "components.Login.forgotpassword": "Zaboravljena lozinka?",
+  "components.Login.loginerror": "Nešto nije u redu prilikom pokušaja prijave.",
+  "components.Login.signin": "Prijavite se",
+  "components.Login.signingin": "Prijava…",
+  "components.Layout.VersionStatus.commitsbehind": "",
+  "components.Login.signinheader": "Prijavite se za nastavak",
+  "components.Login.signinwithoverseerr": "Koristite svoj {applicationTitle} račun",
+  "components.Login.validationpasswordrequired": "Morate unijeti lozinku",
+  "components.ManageSlideOver.alltime": "Cijelo vrijeme",
+  "components.ManageSlideOver.downloadstatus": "Preuzimanja",
+  "components.ManageSlideOver.manageModalAdvanced": "Napredna",
+  "components.ManageSlideOver.manageModalClearMedia": "Obriši podatke",
+  "components.ManageSlideOver.manageModalIssues": "Otvoreni problemi",
+  "components.ManageSlideOver.markallseasons4kavailable": "Označi sve sezone kao dostupne u 4K",
+  "components.ManageSlideOver.markallseasonsavailable": "Označi sve sezone kao dostupne",
+  "components.ManageSlideOver.markavailable": "Označi kao dostupno",
+  "components.ManageSlideOver.playedby": "Reproducirano od",
+  "components.ManageSlideOver.plays": "<strong>{playCount, broj}</strong> {playCount, plural, one {reproducirano} other {reproducirano}}",
+  "components.MovieDetails.MovieCast.fullcast": "Glumačka postava",
+  "components.MovieDetails.digitalrelease": "Digitalno izdanje",
+  "components.MovieDetails.mark4kavailable": "Označi kao dostupno u 4K",
+  "components.MovieDetails.originallanguage": "Izvorni jezik",
+  "components.MovieDetails.MovieCrew.fullcrew": "Filmska postava",
+  "components.MovieDetails.physicalrelease": "Fizičko izdanje",
+  "components.MovieDetails.play4konplex": "Reproduciraj u 4K na Plex-u",
+  "components.MovieDetails.recommendations": "Preporuke",
+  "components.MovieDetails.releasedate": "{releaseCount, plural, one {Datum Izlaska} other {Datumi izlaska}}",
+  "components.MovieDetails.rtcriticsscore": "Rotten Tomatoes Tomatometer",
+  "components.MovieDetails.runtime": "{minutes} minute",
+  "components.MovieDetails.studio": "{studioCount, plural, one {Studio} other {Studiji}}",
+  "components.MovieDetails.theatricalrelease": "Izdanje u kinima",
+  "components.MovieDetails.tmdbuserscore": "Ocjena korisnika TMDB-a",
+  "components.MovieDetails.viewfullcrew": "Pogledajte cijelu filmsku postavu",
+  "components.MovieDetails.watchtrailer": "Pogledajte najavu",
+  "components.NotificationTypeSelector.adminissuecommentDescription": "Primite obavijest kada drugi korisnici komentiraju probleme.",
+  "components.NotificationTypeSelector.adminissuereopenedDescription": "Primite obavijest kada problem ponovno otvore drugi korisnici.",
+  "components.NotificationTypeSelector.adminissueresolvedDescription": "Primite obavijest kada drugi korisnici riješe probleme.",
+  "components.NotificationTypeSelector.issuecomment": "Komentiraj problem",
+  "components.NotificationTypeSelector.issuecreated": "Problem prijavljen",
+  "components.NotificationTypeSelector.issuecreatedDescription": "Pošalji obavijest kada se problem prijavi.",
+  "components.NotificationTypeSelector.userissueresolvedDescription": "Primite obavijest kada problemi koje ste prijavili budu riješeni.",
+  "components.NotificationTypeSelector.mediaavailableDescription": "Slanje obavijesti kada medijski zahtjevi postanu dostupni.",
+  "components.NotificationTypeSelector.mediadeclinedDescription": "Slanje obavijesti kada su medijski zahtjevi odbijeni.",
+  "components.NotificationTypeSelector.mediarequested": "Zahtjev čeka odobrenje",
+  "components.NotificationTypeSelector.mediarequestedDescription": "Slanje obavijesti kada korisnici pošalju nove medijske zahtjeve koji zahtijevaju odobrenje.",
+  "components.NotificationTypeSelector.mediaautorequested": "Zahtjev je automatski poslan",
+  "components.NotificationTypeSelector.mediaavailable": "Zahtjev dostupan",
+  "components.NotificationTypeSelector.mediafailedDescription": "Slanje obavijesti kada se medijski zahtjevi ne uspiju dodati u Radarr ili Sonarr.",
+  "components.NotificationTypeSelector.userissuecommentDescription": "Primite obavijest kada problemi koje ste prijavili dobiju nove komentare.",
+  "components.PermissionEdit.autoapprove4kSeries": "Automatsko odobravanje serija u 4K",
+  "components.NotificationTypeSelector.usermediafailedDescription": "Primite obavijest kada se medijski zahtjevi ne uspiju dodati u Radarr ili Sonarr.",
+  "components.NotificationTypeSelector.usermediarequestedDescription": "Primite obavijest kada drugi korisnici pošalju nove medijske zahtjeve koji zahtijevaju odobrenje.",
+  "components.NotificationTypeSelector.usermediaAutoApprovedDescription": "Primite obavijest kada drugi korisnici pošalju nove medijske zahtjeve koji se automatski odobravaju.",
+  "components.NotificationTypeSelector.usermediadeclinedDescription": "Primite obavijest kada vaši medijski zahtjevi budu odbijeni.",
+  "components.PermissionEdit.adminDescription": "Potpuni administratorski pristup. Zaobilazi sve druge provjere dopuštenja.",
+  "components.PermissionEdit.advancedrequest": "Napredni zahtjevi",
+  "components.PermissionEdit.autoapprove4k": "Automatsko odobravanje 4K",
+  "components.PermissionEdit.autoapproveSeriesDescription": "Dozvolite automatsko odobravanje zahtjeva za serijale koji nisu u 4K.",
+  "components.PermissionEdit.autoapprove4kMoviesDescription": "Dozvolite automatsko odobravanje zahtjeva za filmove u 4K.",
+  "components.PermissionEdit.autoapprove4kSeriesDescription": "Dozvolite automatsko odobravanje zahtjeva za serije u 4K.",
+  "components.QuotaSelector.days": "{count, plural, one {danu} other {danu}}",
+  "components.QuotaSelector.movies": "{count, plural, one {film} other {filmova}}",
+  "components.PermissionEdit.autoapproveMoviesDescription": "Dozvolite automatsko odobravanje zahtjeva za filmove koji nisu u 4K.",
+  "components.RequestButton.approve4krequests": "Odobriti {requestCount, plural, one {4K Zahtjev} other {{requestCount} 4K Zahtjeve}}",
+  "components.RequestModal.QuotaDisplay.movielimit": "{limit, plural, one {film} other {filmova}}",
+  "components.RequestButton.approverequests": "Odobriti {requestCount, plural, one {Zatjev} other {{requestCount} Zahtjeve}}",
+  "components.QuotaSelector.seasons": "{count, plural, one {sezona} other {sezone}}",
+  "components.RequestCard.seasons": "{seasonCount, plural, one {Sezona} other {Sezone}}",
+  "components.RequestList.RequestItem.seasons": "{seasonCount, plural, one {Sezona} other {Sezone}}",
+  "components.RequestBlock.seasons": "{seasonCount, plural, one {Sezona} other {Sezone}}",
+  "components.RequestButton.decline4krequests": "Odbiti {requestCount, plural, one {4K Zahtjev} other {{requestCount} 4K Zahtjeve}}",
+  "components.RequestModal.QuotaDisplay.requiredquotaUser": "Ovaj korisnik treba imati još barem <strong>{seasons}</strong> {seasons, plural, one {jedan zahtjev za sezonu} other {nekoliko zahtjeva za sezone}} kako bi mogao preadti zahtjev za ovu seriju.",
+  "components.RequestModal.QuotaDisplay.requiredquota": "Morate imati još barem <strong>{seasons}</strong> {seasons, plural, one {jedan zahtjev za sezonu} other {nekoliko zahtjeva za sezone}} kako bi mogli preadti zahtjev za ovu seriju.",
+  "components.RequestModal.QuotaDisplay.seasonlimit": "{limit, plural, one {sezona} other {sezona/e}}",
+  "components.RequestModal.requestmovies": "{count} {count, plural, one {Zahtjev za film} other {Zahtjevi za filmove}}",
+  "components.RequestModal.requestmovies4k": "{count} {count, plural, one {Zahtjev za film} other {Zahtejvi za filmove}} u 4K",
+  "components.NotificationTypeSelector.mediaAutoApprovedDescription": "Slanje obavijesti kada korisnici pošalju novi medijski zahtjev koji se automatski odobrava.",
+  "components.NotificationTypeSelector.mediaapproved": "Zahtjev odobren",
+  "components.NotificationTypeSelector.mediaapprovedDescription": "Slanje obavijesti kada se medijski zahtjev ručno odobri.",
+  "components.NotificationTypeSelector.mediaautorequestedDescription": "Primite obavijest kada se automatski pošalje novi medijski zahtjevi za stavke na vašoj Plex listi koju pratite.",
+  "components.NotificationTypeSelector.mediadeclined": "Zahtjev je odbijen",
+  "components.NotificationTypeSelector.mediafailed": "Obrada zahtjeva nije uspjela",
+  "components.NotificationTypeSelector.notificationTypes": "Vrste obavijesti",
+  "components.NotificationTypeSelector.userissuecreatedDescription": "Primite obavijest kada drugi korisnici prijave probleme.",
+  "components.NotificationTypeSelector.userissuereopenedDescription": "Primite obavijest kada se problemi koje ste prijavili ponovno otvore.",
+  "components.NotificationTypeSelector.usermediaapprovedDescription": "Primite obavijest kada vaši zahtjevi za medije budu odobreni.",
+  "components.NotificationTypeSelector.usermediaavailableDescription": "Primite obavijest kada vaši medijski zahtjevi postanu dostupni.",
+  "components.PermissionEdit.admin": "Administrator",
+  "components.PermissionEdit.advancedrequestDescription": "Dodajte dozvolu za izmjenu naprednih opcija zahtjeva za medije.",
+  "components.PermissionEdit.autoapprove": "Automatsko odobravanje",
+  "components.PermissionEdit.autoapprove4kMovies": "Automatsko odobravanje 4K filmova",
+  "components.PermissionEdit.autoapprove4kDescription": "Dozvolite automatsko odobravanje svih zahtjeva za 4K medije.",
+  "components.PermissionEdit.autoapproveDescription": "Dozvolite automatsko odobravanje svih zahtjeva koji nisu u 4K mediji.",
+  "components.PermissionEdit.autoapproveMovies": "Automatsko odobravanje filmova",
+  "components.PermissionEdit.autoapproveSeries": "Automatsko odobravanje serijala",
+  "components.RequestButton.declinerequests": "Odbiti {requestCount, plural, one {Zahtjev} other {{requestCount} Zahtjeve}}",
+  "components.RequestModal.QuotaDisplay.requestsremaining": "{remaining, plural, =0 {No} other {<strong>#</strong>}} {type} {remaining, plural, one {zahtjev preostalo} other {zahtjeva preostala}}"
+}
diff --git a/src/i18n/locale/hu.json b/src/i18n/locale/hu.json
index aeda2952..56b05269 100644
--- a/src/i18n/locale/hu.json
+++ b/src/i18n/locale/hu.json
@@ -28,8 +28,6 @@
   "components.PersonDetails.appearsin": "Szerepel a következőkben",
   "components.PermissionEdit.usersDescription": "Engedélyt ad az Overseerr-nek felhasználók kezelésére. Az ezzel az engedéllyel rendelkező felhasználók nem módosíthatják a rendszergazdai jogosultsággal rendelkező felhasználókat, és nem adhatják meg a jogosultságot más felhasználónak.",
   "components.PermissionEdit.users": "Felhasználók kezelése",
-  "components.PermissionEdit.settingsDescription": "Engedélyt ad az Overseerr-nek összes beállításának módosítására. A felhasználónak rendelkeznie kell ezzel az engedéllyel ahhoz, hogy másoknak megadja.",
-  "components.PermissionEdit.settings": "Beállítások kezelése",
   "components.PermissionEdit.requestDescription": "Engedélyt ad filmek és sorozatok kérésére.",
   "components.PermissionEdit.request4kTvDescription": "Engedélyt ad 4K-s sorozatok kérésére.",
   "components.PermissionEdit.request4kTv": "Kérés - 4K sorozatok",
@@ -68,7 +66,7 @@
   "components.MediaSlider.ShowMoreCard.seemore": "Még több",
   "components.Login.validationpasswordrequired": "Meg kell adnia egy jelszót",
   "components.Login.validationemailrequired": "Érvényes email címet kell megadnod",
-  "components.Login.signinwithplex": "Használd a Plex fiókat",
+  "components.Login.signinwithplex": "Használd a Plex fiókod",
   "components.Login.signinwithoverseerr": "Bejelentkezés {applicationTitle} fiókkal",
   "components.Login.signinheader": "Jelentkezz be a folytatáshoz",
   "components.Login.signingin": "Bejelentkezés…",
@@ -105,7 +103,6 @@
   "components.RequestModal.extras": "Extrák",
   "components.RequestModal.errorediting": "Hiba történt a kérés szerkesztése közben.",
   "components.RequestModal.cancel": "Kérés visszavonása",
-  "components.RequestModal.SearchByNameModal.nosummary": "Nem található összefoglaló ehhez a címhez.",
   "components.RequestModal.AdvancedRequester.rootfolder": "Root könyvtár",
   "components.RequestModal.AdvancedRequester.qualityprofile": "Minőség profil",
   "components.RequestModal.AdvancedRequester.destinationserver": "Cél szerver",
@@ -114,10 +111,10 @@
   "components.MovieDetails.markavailable": "Megjelölés elérhetőként",
   "components.MovieDetails.mark4kavailable": "Megjelölés elérhetőként - 4K",
   "components.Layout.Sidebar.dashboard": "Felfedezés",
-  "components.NotificationTypeSelector.mediarequested": "Kérés elküldve",
+  "components.NotificationTypeSelector.mediarequested": "Kérés elfogadásra vár",
   "components.NotificationTypeSelector.mediafailedDescription": "Értesítést küld amikor a kérést nem sikerül hozzáadni a menedzser app-okhoz (Radarr/Sonarr).",
-  "components.NotificationTypeSelector.mediafailed": "Kérés sikertelen",
-  "components.NotificationTypeSelector.mediaapprovedDescription": "Értesítést küld a kérések elfogadásakor.",
+  "components.NotificationTypeSelector.mediafailed": "Kérés feldolgozás sikertelen",
+  "components.NotificationTypeSelector.mediaapprovedDescription": "Értesítések küldése kérések manuális elfogadásakor.",
   "components.NotificationTypeSelector.mediadeclinedDescription": "Értesítést küld a kérések elutasításakor.",
   "components.NotificationTypeSelector.mediadeclined": "Kérés elutasítva",
   "components.NotificationTypeSelector.mediaavailableDescription": "Értesítést küld amikor a kért tartalom elérhetővé válik.",
@@ -193,9 +190,6 @@
   "components.TvDetails.anime": "Anime",
   "components.TvDetails.TvCrew.fullseriescrew": "Sorozat teljes stábja",
   "components.TvDetails.TvCast.fullseriescast": "Sorozat teljes szereposztása",
-  "components.StatusChacker.reloadOverseerr": "Újratöltés",
-  "components.StatusChacker.newversionavailable": "Alkalmazásfrissítés",
-  "components.StatusChacker.newversionDescription": "Az Overseerr frissült! Az oldal újratöltéséhez kattintson az alábbi gombra.",
   "components.StatusBadge.status4k": "4K {status}",
   "components.Setup.welcome": "Üdv az Overseerr-ben",
   "components.Setup.signinMessage": "Kezdésnek lépj be a Plex fiókoddal",
@@ -206,17 +200,15 @@
   "components.Setup.configureservices": "Szolgáltatások beállítása",
   "components.Setup.configureplex": "Plex beállítása",
   "components.RequestModal.requestfrom": "Jelenleg van egy folyamatban lévő kérés {username} felhasználótól.",
-  "components.RequestModal.requesttitle": "{title} kérése",
   "components.RequestModal.requestseasons": "{seasonCount} évad kérése",
   "components.RequestModal.requestSuccess": "<strong>{title}</strong> kérés elküldve!",
   "components.RequestModal.requestCancel": "<strong>{title}</strong> kérése visszavonva.",
-  "components.RequestModal.request4ktitle": "{title} kérése - 4K-ban",
-  "components.RequestModal.pendingrequest": "Függőben lévő kérés {title} - hez",
-  "components.RequestModal.pending4krequest": "Függőben lévő 4k-s kérés a {title}-hoz",
+  "components.RequestModal.pendingrequest": "Elbírálásra váró kérelem",
+  "components.RequestModal.pending4krequest": "",
   "components.RequestModal.autoapproval": "Automatikus jóváhagyás",
   "components.RequestModal.SearchByNameModal.notvdbiddescription": "Nem sikerült azonosítani a kérésed. Kérlek, válaszd ki a megfelelő találatot az alábbi listából.",
   "components.RequestBlock.profilechanged": "Minőség profil",
-  "components.NotificationTypeSelector.mediarequestedDescription": "Értesítést küld ,amikor a felhasználók új kérések küldenek ,amik automatikusan elfogadásra kerülnek..",
+  "components.NotificationTypeSelector.mediarequestedDescription": "Értesítések küldése amikor a felhasználók olyan új média kéréseket nyújtanak be, amelyeknél elfogadásra van szükség.",
   "components.PermissionEdit.viewrequests": "Kérések megtekintése",
   "components.Discover.discover": "Felfedezés",
   "components.Login.forgotpassword": "Elfelejtett jelszó?",
@@ -313,7 +305,7 @@
   "components.Settings.validationApplicationUrlTrailingSlash": "Az URL-nek nem lehet vége perjellel",
   "components.Settings.validationApplicationUrl": "Érvényes URL-t kell megadnia",
   "components.Settings.validationApplicationTitle": "Meg kell adnia egy alkalmazás címet",
-  "components.Settings.trustProxyTip": "Lehetővé teszi az Overseerr számára, hogy helyesen regisztrálja az ügyfelek IP-címeit proxy mögött (az Overseerr-t újra kell tölteni a változások érvénybe lépéséhez)",
+  "components.Settings.trustProxyTip": "Lehetővé teszi az Overseerr számára, hogy helyesen regisztrálja az ügyfelek IP-címeit proxy mögött",
   "components.Settings.trustProxy": "Proxy-támogatás engedélyezése",
   "components.Settings.toastSettingsSuccess": "A beállítások sikeresen mentve!",
   "components.Settings.toastSettingsFailure": "Valami elromlott a beállítások mentése közben.",
@@ -384,7 +376,7 @@
   "components.Settings.default4k": "Alapértelmezett 4K",
   "components.Settings.default": "Alapértelmezett",
   "components.Settings.currentlibrary": "Jelenlegi könyvtár: {name}",
-  "components.Settings.csrfProtectionTip": "Külső API-hozzáférés beállítása csak olvashatóra (HTTPS szükséges, és az Overseerr-t újra kell tölteni a módosítások érvénybe lépéséhez)",
+  "components.Settings.csrfProtectionTip": "Külső API-hozzáférés beállítása csak olvashatóra (HTTPS szükséges)",
   "components.Settings.csrfProtectionHoverTip": "NE engedélyezze ezt a beállítást, csak ha megérti, mit csinál!",
   "components.Settings.csrfProtection": "Engedélyezze a CSRF-védelmet",
   "components.Settings.copied": "API-kulcs másolva a vágólapra.",
@@ -495,7 +487,7 @@
   "components.Settings.SettingsAbout.Releases.viewchangelog": "Változásnapló megtekintése",
   "components.Settings.SettingsAbout.Releases.versionChangelog": "Verzió változásnapló",
   "components.Settings.SettingsAbout.Releases.releases": "Kiadások",
-  "components.Settings.SettingsAbout.Releases.releasedataMissing": "Kiadási adatok nem állnak rendelkezésre. A GitHub nem elérhető?",
+  "components.Settings.SettingsAbout.Releases.releasedataMissing": "Kiadási adatok nem állnak rendelkezésre.",
   "components.Settings.SettingsAbout.Releases.latestversion": "Legújabb",
   "components.Settings.SettingsAbout.Releases.currentversion": "Jelenlegi verzió",
   "components.Settings.RadarrModal.validationRootFolderRequired": "Ki kell választania egy root mappát",
@@ -650,7 +642,6 @@
   "components.UserProfile.seriesrequest": "Sorozatkérések",
   "components.UserProfile.requestsperdays": "{limit} maradt",
   "components.UserProfile.recentrequests": "Legutóbbi kérések",
-  "components.UserProfile.norequests": "Nincs kérés.",
   "components.UserProfile.movierequests": "Filmkérések",
   "components.UserProfile.limit": "{remaining} a {limit}-ből",
   "components.UserProfile.UserSettings.unauthorizedDescription": "Nincs jogosultsága a felhasználó beállításainak módosítására.",
@@ -734,13 +725,13 @@
   "components.PermissionEdit.autoapprove4k": "Automatikus jóváhagyás 4k",
   "components.NotificationTypeSelector.usermediarequestedDescription": "Értesítést kap, ha más felhasználók új média kéréseket nyújtanak be, amelyek jóváhagyást igényelnek.",
   "components.NotificationTypeSelector.usermediafailedDescription": "Értesítést kap, ha a média kéréseket nem sikerült hozzáadni a Radarrhoz vagy a Sonarrhoz.",
-  "components.NotificationTypeSelector.usermediadeclinedDescription": "Értesítést kap,amikor a média kérését visszautasították.",
+  "components.NotificationTypeSelector.usermediadeclinedDescription": "Értesítést kap, amikor a média kérését visszautasították.",
   "components.NotificationTypeSelector.usermediaavailableDescription": "Értesítést kap, amikor elérhetővé válnak a kérései.",
   "components.NotificationTypeSelector.usermediaapprovedDescription": "Értesítést kap, ha a média kérelmeket jóváhagyják.",
   "components.NotificationTypeSelector.usermediaAutoApprovedDescription": "Értesítést kap, ha más felhasználók új média kéréseket nyújtanak be, amelyeket automatikusan jóváhagynak.",
   "components.NotificationTypeSelector.notificationTypes": "Értesítési típusok",
-  "components.NotificationTypeSelector.mediaAutoApprovedDescription": "Értesítéseket küldése, amikor a felhasználók új média kéréseket nyújtanak be, amelyeket automatikusan jóváhagynak.",
-  "components.NotificationTypeSelector.mediaAutoApproved": "A média automatikusan jóváhagyva",
+  "components.NotificationTypeSelector.mediaAutoApprovedDescription": "Értesítések küldése amikor a felhasználók olyan új média kéréseket nyújtanak be, amelyek automatikusan jóvá vannak hagyva.",
+  "components.NotificationTypeSelector.mediaAutoApproved": "Kérés Automatikusan Jóváhagyva",
   "components.MovieDetails.showmore": "Mutass többet",
   "components.MovieDetails.showless": "Mutass kevesebbet",
   "components.MovieDetails.originaltitle": "Eredeti cím",
@@ -755,7 +746,6 @@
   "components.LanguageSelector.languageServerDefault": "Alap ({language})",
   "components.DownloadBlock.estimatedtime": "Becsült {time}",
   "components.Discover.upcomingtv": "Hamarosan megjelenő sorozatok",
-  "components.Discover.noRequests": "Nincs kérések.",
   "components.Discover.TvGenreSlider.tvgenres": "Sorozat műfajok",
   "components.Discover.TvGenreList.seriesgenres": "Sorozat műfajok",
   "components.Discover.StudioSlider.studios": "Studiók",
@@ -853,5 +843,200 @@
   "components.ResetPassword.emailresetlink": "Email visszaállítási link",
   "components.ResetPassword.email": "Email cím",
   "components.ResetPassword.confirmpassword": "Jelszó megerősítése",
-  "components.StatusBadge.status": "{status}"
+  "components.StatusBadge.status": "{status}",
+  "components.IssueDetails.closeissue": "Probléma Lezárása",
+  "components.IssueDetails.closeissueandcomment": "Lezárás Hozzászólással",
+  "components.IssueModal.CreateIssueModal.toastFailedCreate": "Valami hiba történt a probléma elküldése során.",
+  "components.IssueDetails.play4konplex": "Lejátszás Plexen 4K-ban",
+  "components.IssueModal.CreateIssueModal.toastviewissue": "Probléma Megtekintése",
+  "components.ManageSlideOver.manageModalClearMediaWarning": "* Ez visszafordíthatatlanul eltávolítja az összes adatot ehhez a {mediaType}-hez, beleértve a kéréseket is. Ha ez az elem létezik a Plex könyvtárában, a médiainformáció a következő beolvasás során újra létrejön.",
+  "components.IssueDetails.commentplaceholder": "Hozzászólás írása…",
+  "components.IssueDetails.comments": "Hozzászólások",
+  "components.IssueDetails.deleteissue": "Probléma Törlése",
+  "components.IssueDetails.deleteissueconfirm": "Biztos, hogy ki akarja törölni ezt a problémát?",
+  "components.IssueDetails.episode": "{episodeNumber}. Epizód",
+  "components.IssueDetails.issuepagetitle": "Probléma",
+  "components.IssueDetails.issuetype": "Típus",
+  "components.IssueDetails.lastupdated": "Utoljára Frissítve",
+  "components.IssueDetails.leavecomment": "Hozzászólás",
+  "components.IssueDetails.nocomments": "Nincsenek hozzászólások.",
+  "components.IssueDetails.openedby": "#{issueId} bejelentve {relativeTime} {username} által",
+  "components.IssueDetails.openin4karr": "Megnyitás 4K-ban itt: {arr}",
+  "components.IssueDetails.playonplex": "Lejátszás Plexen",
+  "components.IssueDetails.problemepisode": "Érintett Epizód",
+  "components.IssueDetails.problemseason": "Érintett Évad",
+  "components.IssueDetails.reopenissueandcomment": "Újranyitás Hozzászólással",
+  "components.IssueDetails.season": "{seasonNumber}. Évad",
+  "components.IssueDetails.toasteditdescriptionsuccess": "A probléma leírása sikeresen szerkesztve!",
+  "components.IssueDetails.toaststatusupdated": "A probléma állapota sikeresen frissítve!",
+  "components.IssueDetails.toaststatusupdatefailed": "Valami hiba történt a probléma állapotának frissítése közben.",
+  "components.IssueList.IssueItem.issuetype": "Típus",
+  "components.IssueList.IssueItem.opened": "Bejelentve",
+  "components.IssueList.IssueItem.openeduserdate": "{date} {user} által",
+  "components.IssueList.IssueItem.problemepisode": "Érintett Epizód",
+  "components.IssueList.showallissues": "Minden Probléma Mutatása",
+  "components.IssueList.sortModified": "Utoljára Módosítva",
+  "components.IssueModal.CreateIssueModal.allepisodes": "Minden Epizód",
+  "components.IssueModal.CreateIssueModal.allseasons": "Minden Évad",
+  "components.IssueModal.CreateIssueModal.episode": "{episodeNumber}. Epizód",
+  "components.IssueModal.CreateIssueModal.extras": "Extrák",
+  "components.IssueModal.CreateIssueModal.problemepisode": "Érintett Epizód",
+  "components.IssueModal.CreateIssueModal.problemseason": "Érintett Évad",
+  "components.IssueModal.CreateIssueModal.providedetail": "Kérjük, adjon részletes magyarázatot a felmerült problémára.",
+  "components.IssueModal.CreateIssueModal.reportissue": "Probléma Jelentése",
+  "components.IssueModal.CreateIssueModal.season": "{seasonNumber}. Évad",
+  "components.IssueModal.CreateIssueModal.submitissue": "Probléma Bejelentése",
+  "components.IssueModal.CreateIssueModal.validationMessageRequired": "Adnia kell egy leírást",
+  "components.IssueModal.CreateIssueModal.whatswrong": "Mi a probléma?",
+  "components.IssueModal.issueAudio": "Hang",
+  "components.IssueModal.issueOther": "Egyéb",
+  "components.IssueModal.issueSubtitles": "Felirat",
+  "components.IssueModal.issueVideo": "Kép",
+  "components.Layout.Sidebar.issues": "Problémák",
+  "components.ManageSlideOver.alltime": "Mindenkori",
+  "components.ManageSlideOver.downloadstatus": "Letöltések",
+  "components.ManageSlideOver.manageModalAdvanced": "Speciális",
+  "components.ManageSlideOver.manageModalClearMedia": "Adatok Törlése",
+  "components.ManageSlideOver.manageModalIssues": "Megoldatlan Problémák",
+  "components.ManageSlideOver.manageModalMedia4k": "4K Média",
+  "components.ManageSlideOver.manageModalNoRequests": "Nincsenek kérések.",
+  "components.ManageSlideOver.manageModalMedia": "Média",
+  "components.ManageSlideOver.manageModalRequests": "Kérések",
+  "components.ManageSlideOver.manageModalTitle": "{mediaType} Kezelése",
+  "components.ManageSlideOver.mark4kavailable": "Megjelölés 4K-ban elérhetőként",
+  "components.ManageSlideOver.markallseasons4kavailable": "Az Összes Évad Megjelölése 4K-ban Elérhetőként",
+  "components.ManageSlideOver.markavailable": "Megjelölés Elérhetőként",
+  "components.ManageSlideOver.movie": "film",
+  "components.ManageSlideOver.markallseasonsavailable": "Az Összes Évad Megjelölése Elérhetőként",
+  "components.ManageSlideOver.openarr": "Megnyitás itt: {arr}",
+  "components.ManageSlideOver.openarr4k": "Megnyitás 4K-ban itt: {arr}",
+  "components.ManageSlideOver.opentautulli": "Megnyitás itt: Tautulli",
+  "components.ManageSlideOver.pastdays": "Elmúlt {days, number} Napban",
+  "components.ManageSlideOver.tvshow": "sorozat",
+  "components.MovieDetails.streamingproviders": "Jelenleg Streamelhető",
+  "components.NotificationTypeSelector.userissuecommentDescription": "Értesítést kap, ha az Ön által jelentett problémákhoz új hozzászólások érkeznek.",
+  "components.NotificationTypeSelector.userissuecreatedDescription": "Értesítést kap, ha más felhasználók problémákat jelentenek.",
+  "components.NotificationTypeSelector.userissuereopenedDescription": "Értesítést kap, ha az Ön által bejelentett problémákat újra megnyitják.",
+  "components.NotificationTypeSelector.userissueresolvedDescription": "Értesítést kap, ha az Ön által bejelentett problémák megoldódnak.",
+  "components.IssueDetails.IssueComment.edit": "Hozzászólás Szerkesztése",
+  "components.IssueDetails.IssueComment.areyousuredelete": "Biztos, hogy ki akarja törölni ezt a hozzászólást?",
+  "components.IssueDetails.IssueComment.delete": "Hozzászólás Törlése",
+  "components.IssueDetails.IssueComment.postedby": "Közzétéve {relativeTime} {username} által",
+  "components.IssueDetails.IssueDescription.deleteissue": "Probléma Törlése",
+  "components.IssueDetails.IssueComment.postedbyedited": "Közzétéve {relativeTime} {username} által (Szerkesztve)",
+  "components.IssueDetails.IssueDescription.edit": "Leírás Szerkesztése",
+  "components.IssueDetails.allepisodes": "Minden Epizód",
+  "components.IssueDetails.reopenissue": "Probléma Újranyitása",
+  "components.IssueDetails.toastissuedeletefailed": "Valami hiba történt a probléma törlése során.",
+  "components.IssueList.IssueItem.issuestatus": "Állapot",
+  "components.IssueList.IssueItem.unknownissuetype": "Ismeretlen",
+  "components.IssueList.issues": "Problémák",
+  "components.IssueList.IssueItem.viewissue": "Probléma Megtekintése",
+  "components.IssueDetails.IssueDescription.description": "Leírás",
+  "components.IssueDetails.allseasons": "Minden Évad",
+  "components.IssueDetails.openinarr": "Megnyitás itt: {arr}",
+  "components.IssueDetails.toasteditdescriptionfailed": "Valami hiba történt a probléma leírásának szerkesztése közben.",
+  "components.IssueDetails.toastissuedeleted": "A probléma sikeresen törölve!",
+  "components.IssueDetails.unknownissuetype": "Ismeretlen",
+  "components.IssueList.sortAdded": "Legfrissebb",
+  "components.IssueDetails.IssueComment.validationComment": "Be kell írnia egy üzenetet",
+  "components.NotificationTypeSelector.issuecreated": "Probléma Jelentve",
+  "components.NotificationTypeSelector.issuereopened": "Probléma Újranyitva",
+  "components.PermissionEdit.manageissuesDescription": "Engedélyt ad média problémák kezelésére.",
+  "components.Settings.SettingsJobsCache.jobScheduleEditFailed": "Valami hiba történt a feladat mentése közben.",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoverApplicationToken": "Alkalmazás API Token",
+  "components.Settings.Notifications.NotificationsGotify.agentenabled": "Ügynök Engedélyezése",
+  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestFailed": "A Gotify teszt értesítést nem sikerült elküldeni.",
+  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestSending": "Gotify teszt értesítés küldése…",
+  "components.Settings.Notifications.NotificationsGotify.validationTypes": "Legalább egy értesítési típust ki kell választania",
+  "components.Settings.Notifications.NotificationsGotify.validationUrlRequired": "Érvényes URL-t kell megadnia",
+  "i18n.open": "Megnyitás",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletAccessToken": "Hozzáférési Token",
+  "components.Settings.Notifications.NotificationsGotify.gotifysettingssaved": "Gotify értesítési beállítások sikeresen mentve!",
+  "components.UserProfile.UserSettings.UserGeneralSettings.discordIdTip": "A <FindDiscordIdLink>többjegyű azonosítószám</FindDiscordIdLink>, amely az Ön Discord felhasználói fiókjához kapcsolódik",
+  "components.Settings.RadarrModal.released": "Megjelent",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletAccessTokenTip": "Hozzon létre egy tokent a <PushbulletSettingsLink>Fiókbeállításokban</PushbulletSettingsLink>",
+  "components.UserProfile.UserSettings.UserGeneralSettings.validationDiscordId": "Egy érvényes Discord felhasználói azonosítót kell megadnia",
+  "components.RequestModal.selectmovies": "Film(ek) Kiválasztása",
+  "components.UserProfile.UserSettings.UserGeneralSettings.discordId": "Discord Felhasználó ID",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletsettingssaved": "A Pushbullet értesítési beállításai sikeresen mentve lettek!",
+  "components.ManageSlideOver.playedby": "Lejátszotta",
+  "components.NotificationTypeSelector.adminissuecommentDescription": "Értesítést kap, ha más felhasználók hozzászólnak a problémákhoz.",
+  "components.NotificationTypeSelector.adminissuereopenedDescription": "Értesítést kap, ha más felhasználók újranyitják a problémákat.",
+  "components.NotificationTypeSelector.adminissueresolvedDescription": "Értesítést kap, ha más felhasználók megoldják a problémákat.",
+  "components.NotificationTypeSelector.issuecommentDescription": "Értesítések küldése, ha a problémákhoz új hozzászólások érkeznek.",
+  "components.NotificationTypeSelector.issuereopenedDescription": "Értesítések küldése a problémák újranyitásakor.",
+  "components.PermissionEdit.createissuesDescription": "Engedélyt ad média problémák bejelentésére.",
+  "components.PermissionEdit.manageissues": "Problémák Kezelése",
+  "components.PermissionEdit.createissues": "Problémák Bejelentése",
+  "components.PermissionEdit.viewissuesDescription": "Engedélyt ad más felhasználók által bejelentett média problémák megtekintésére.",
+  "components.Settings.tautulliApiKey": "API Kulcs",
+  "components.Settings.tautulliSettings": "Tautulli Beállítások",
+  "components.Settings.toastTautulliSettingsFailure": "Valami hiba történt a Tautulli beállítások mentése közben.",
+  "components.Settings.urlBase": "Alap URL",
+  "components.Settings.validationUrl": "Érvényes URL-t kell megadnia",
+  "components.Settings.validationUrlBaseLeadingSlash": "Az Alap URL perjellel kell, hogy kezdődjön",
+  "components.Settings.validationUrlTrailingSlash": "Az URL-nek nem szabad perjellel végződnie",
+  "components.Settings.Notifications.NotificationsPushbullet.channelTag": "Csatorna Címke",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoversettingsfailed": "A Pushover értesítési beállításait nem sikerült elmenteni.",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoversettingssaved": "A Pushover értesítési beállításai sikeresen mentve lettek!",
+  "components.NotificationTypeSelector.issueresolvedDescription": "Értesítések küldése problémák megoldása esetén.",
+  "components.NotificationTypeSelector.issuecreatedDescription": "Értesítések küldése problémák bejelentésekor.",
+  "components.NotificationTypeSelector.issueresolved": "Probléma Megoldva",
+  "components.RequestModal.approve": "Kérés Jóváhagyása",
+  "i18n.resolved": "Megoldva",
+  "components.Settings.RadarrModal.inCinemas": "Mozikban",
+  "components.Settings.SettingsJobsCache.editJobSchedule": "Feladat Módosítása",
+  "components.Settings.SettingsJobsCache.editJobSchedulePrompt": "Gyakoriság",
+  "components.RequestBlock.languageprofile": "Nyelv Profil",
+  "components.RequestModal.requestApproved": "Kérés elfogadva: <strong>{title}</strong>",
+  "components.Settings.Notifications.NotificationsGotify.gotifysettingsfailed": "A Gotify értesítési beállításait nem sikerült elmenteni.",
+  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestSuccess": "Gotify teszt értesítés elküldve!",
+  "components.Settings.Notifications.NotificationsGotify.token": "Alkalmazás Token",
+  "components.Settings.Notifications.NotificationsGotify.url": "Szerver URL",
+  "components.Settings.Notifications.NotificationsGotify.validationTokenRequired": "Meg kell adnia egy alkalmazás tokent",
+  "components.Settings.Notifications.NotificationsGotify.validationUrlTrailingSlash": "Az URL nem végződhet perjellel",
+  "components.Settings.Notifications.enableMentions": "Említések Engedélyezése",
+  "components.Settings.RadarrModal.announced": "Bejelentve",
+  "components.Settings.SettingsAbout.appDataPath": "Adat Könyvtár",
+  "components.Settings.SettingsAbout.runningDevelop": "Ön az Overseerr <code>develop</code> ágát futtatja, ami csak azoknak ajánlott, akik hozzájárulnak a fejlesztéshez vagy segítenek a tesztelésben.",
+  "components.Settings.SettingsJobsCache.jobScheduleEditSaved": "Feladat sikeresen szerkesztve!",
+  "components.Settings.tautulliSettingsDescription": "Opcionálisan konfigurálja a Tautulli szerver beállításait. Az Overseerr lekérdezi a Plex média nézési előzményeinek adatait a Tautulliból.",
+  "components.Settings.toastTautulliSettingsSuccess": "Tautulli beállítások sikeresen mentve!",
+  "components.Settings.validationApiKey": "Meg kell adnia egy API-kulcsot",
+  "components.Settings.validationUrlBaseTrailingSlash": "Az Alap URL-nek nem szabad perjellel végződnie",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletsettingsfailed": "A Pushbullet értesítési beállításait nem sikerült elmenteni.",
+  "components.UserProfile.UserSettings.UserNotificationSettings.validationPushbulletAccessToken": "Meg kell adnia egy hozzáférési tokent",
+  "components.UserProfile.UserSettings.UserNotificationSettings.validationPushoverApplicationToken": "Érvényes alkalmazás tokent kell megadnia",
+  "components.UserProfile.recentlywatched": "Mostanában Nézett",
+  "i18n.importing": "Importálás…",
+  "i18n.import": "Importálás",
+  "components.PermissionEdit.viewissues": "Problémák Megtekintése",
+  "components.Settings.externalUrl": "Külső URL",
+  "components.MovieDetails.physicalrelease": "Fizikai kiadás",
+  "components.MovieDetails.digitalrelease": "Digitális kiadás",
+  "components.RequestCard.cancelrequest": "Kérés visszavonása",
+  "components.RequestCard.declinerequest": "Kérelem elutasítása",
+  "components.RequestCard.editrequest": "Kérelem szerkesztése",
+  "components.Discover.DiscoverWatchlist.discoverwatchlist": "",
+  "components.PermissionEdit.autorequest": "Automatikus kérés",
+  "components.NotificationTypeSelector.mediaautorequested": "A kérelem automatikusan elküldve",
+  "components.MovieDetails.reportissue": "Probléma bejelentése",
+  "components.PermissionEdit.autorequestMovies": "Filmek automatikus kérése",
+  "components.NotificationTypeSelector.issuecomment": "Probléma Megjegyzés",
+  "components.PermissionEdit.autorequestSeries": "Automatikus kérés sorozatok",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.seriesrequests": "Sorozatkérések",
+  "components.MovieDetails.managemovie": "Film kezelése",
+  "components.MovieDetails.rtaudiencescore": "Rotten Tomatoes közönségpontszám",
+  "components.MovieDetails.tmdbuserscore": "TMDB felhasználói pontszám",
+  "components.RequestBlock.delete": "Kérelem törlése",
+  "components.RequestBlock.edit": "Kérelem szerkesztése",
+  "components.RequestBlock.approve": "Kérelem jóváhagyása",
+  "components.RequestBlock.decline": "Kérelem elutasítása",
+  "components.RequestBlock.lastmodifiedby": "Utoljára módosította",
+  "components.RequestBlock.requestdate": "Igénylés dátuma",
+  "components.RequestCard.approverequest": "Kérelem jóváhagyása",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.movierequests": "Filmkérések",
+  "components.Layout.UserDropdown.requests": "Kérések",
+  "components.RequestModal.requestcollectiontitle": "Gyűjtemény kérése"
 }
diff --git a/src/i18n/locale/it.json b/src/i18n/locale/it.json
index e739ce4a..f7ff46a7 100644
--- a/src/i18n/locale/it.json
+++ b/src/i18n/locale/it.json
@@ -90,9 +90,8 @@
   "components.Settings.RadarrModal.apiKey": "Chiave API",
   "components.Settings.RadarrModal.add": "Aggiungi un server",
   "components.Settings.Notifications.discordsettingsfailed": "Impossibile salvare le impostazioni di Discord.",
-  "components.RequestModal.requesttitle": "Richiedi {title}",
   "components.RequestModal.requestfrom": "La richiesta di {username} è in attesa di approvazione.",
-  "components.RequestModal.pendingrequest": "Richiesta in sospeso per {title}",
+  "components.RequestModal.pendingrequest": "Richiesta in sospeso",
   "components.Layout.Sidebar.dashboard": "Esplora",
   "components.TvDetails.cast": "Cast",
   "components.TvDetails.anime": "Anime",
@@ -252,9 +251,6 @@
   "components.Settings.Notifications.senderName": "Nome del mittente",
   "components.Settings.Notifications.chatId": "ID chat",
   "components.Settings.Notifications.botAPI": "Token di autorizzazione bot",
-  "components.StatusChacker.reloadOverseerr": "Ricarica",
-  "components.StatusChacker.newversionavailable": "Aggiornamento Applicazione",
-  "components.StatusChacker.newversionDescription": "Overseerr è stato aggiornato! Premi il pulsante qui sotto per ricaricare la pagina.",
   "components.Settings.SettingsAbout.documentation": "Documentazione",
   "components.NotificationTypeSelector.mediarequestedDescription": "Invia notifiche quando gli utenti presentano nuove richieste di media che richiedono approvazione.",
   "components.NotificationTypeSelector.mediarequested": "Richiesta in attesa di approvazione",
@@ -305,7 +301,6 @@
   "components.Login.email": "Indirizzo e-mail",
   "components.Settings.Notifications.NotificationsWebhook.templatevariablehelp": "Guida per variabili di modello",
   "components.Settings.Notifications.NotificationsWebhook.agentenabled": "Abilita Agente",
-  "components.RequestModal.request4ktitle": "Richiedi {title} in 4K",
   "components.Settings.Notifications.NotificationsWebhook.authheader": "Intestazione di autorizzazione",
   "components.MediaSlider.ShowMoreCard.seemore": "Vedi altro",
   "components.RequestBlock.server": "Server di destinazione",
@@ -326,7 +321,7 @@
   "components.Settings.Notifications.NotificationsWebhook.customJson": "Payload JSON",
   "components.RequestModal.requestedited": "Richiesta di <strong>{title}</strong> modificata correttamente!",
   "components.RequestModal.requestcancelled": "Richiesta per <strong>{title}</strong> eliminata.",
-  "components.RequestModal.pending4krequest": "Richiesta 4K in sospeso per {title}",
+  "components.RequestModal.pending4krequest": "Richiesta 4K in sospeso",
   "components.RequestModal.errorediting": "Qualcosa è andato storto durante la modifica della richiesta.",
   "components.RequestModal.autoapproval": "Approvazione automatica",
   "components.RequestModal.AdvancedRequester.rootfolder": "Cartella principale",
@@ -340,7 +335,6 @@
   "components.UserList.bulkedit": "Modifica collettiva",
   "components.UserList.userssaved": "Permessi salvati con successo!",
   "components.PermissionEdit.users": "Gestisci gli utenti",
-  "components.PermissionEdit.settings": "Gestisci le impostazioni",
   "components.PermissionEdit.request4kTv": "Richiedi serie in 4K",
   "components.PermissionEdit.request4kMovies": "Rechiedi film in 4K",
   "components.PermissionEdit.managerequests": "Gestisci Richieste",
@@ -366,7 +360,7 @@
   "components.Settings.serverRemote": "remoto",
   "components.Settings.serverLocal": "locale",
   "components.Settings.notificationAgentSettingsDescription": "Configura e abilita gli agenti di notifica.",
-  "components.Settings.csrfProtectionTip": "Imposta l'accesso alle API esterne in sola lettura (richiede HTTPS e Overseerr deve essere ricaricato affinché le modifiche abbiano effetto)",
+  "components.Settings.csrfProtectionTip": "Imposta l'accesso alle API esterne in sola lettura (richiede HTTPS)",
   "components.Settings.csrfProtectionHoverTip": "NON abilitate questa opzione se non sapete cosa state facendo!",
   "components.Settings.csrfProtection": "Abilita protezione CSRF",
   "components.Settings.applicationTitle": "Titolo dell'applicazione",
@@ -430,7 +424,6 @@
   "components.ResetPassword.confirmpassword": "Conferma la password",
   "components.RequestModal.requesterror": "Qualcosa è andato storto durante l'invio della richiesta.",
   "components.RequestModal.SearchByNameModal.notvdbiddescription": "Non siamo riusciti a soddisfare automaticamente la tua richiesta. Seleziona la corrispondenza corretta dall'elenco seguente.",
-  "components.RequestModal.SearchByNameModal.nosummary": "Non è stato trovato alcun riassunto per questo titolo.",
   "components.RequestModal.AdvancedRequester.requestas": "Richiedi come",
   "components.RequestModal.AdvancedRequester.languageprofile": "Profilo lingua",
   "components.PlexLoginButton.signinwithplex": "Accedi",
@@ -439,7 +432,6 @@
   "components.PermissionEdit.viewrequests": "Visualizza le richieste",
   "components.PermissionEdit.usersDescription": "Concede il permesso di gestire gli utenti. Gli utenti con questo permesso non possono modificare gli utenti con privilegio di Amministratore, o concederlo.",
   "components.PermissionEdit.requestDescription": "Concedere l'autorizzazione per richiedere media non 4K.",
-  "components.PermissionEdit.settingsDescription": "Permette di modificare le impostazioni globali. Un utente deve avere questa autorizzazione per poterla concedere ad altri.",
   "components.PermissionEdit.request4kTvDescription": "Concede l'autorizzazione per richiedere serie in 4K.",
   "components.PermissionEdit.request4kMoviesDescription": "Concede l'autorizzazione per richiedere film in 4K.",
   "components.PermissionEdit.request4kDescription": "Concede l'autorizzazione per richiedere media in 4K.",
@@ -469,7 +461,7 @@
   "components.Settings.serverpresetRefreshing": "Recupero di server…",
   "components.Settings.serverpresetManualMessage": "Configurazione manuale",
   "components.TvDetails.nextAirDate": "Prossima data di messa in onda",
-  "components.Settings.trustProxyTip": "Permette a Overseerr di registrare correttamente gli indirizzi IP dei client dietro un proxy (Overseerr deve essere ricaricato perché le modifiche abbiano effetto)",
+  "components.Settings.trustProxyTip": "Permette a Overseerr di registrare correttamente gli indirizzi IP dei client dietro un proxy",
   "components.Settings.settingUpPlexDescription": "Per impostare Plex, potete inserire i dati manualmente o selezionare un server recuperato da <RegisterPlexTVLink>plex.tv</RegisterPlexTVLink>. Premi il pulsante a destra del menu a tendina per recuperare la lista di server disponibili.",
   "components.Settings.Notifications.sendSilentlyTip": "Invia notifiche senza suono",
   "components.Settings.Notifications.sendSilently": "Invia silenziosamente",
@@ -592,7 +584,6 @@
   "components.RequestModal.AdvancedRequester.folder": "{path} ({space})",
   "components.Discover.TvGenreSlider.tvgenres": "Generi Serie",
   "components.Discover.MovieGenreSlider.moviegenres": "Generi film",
-  "components.UserProfile.norequests": "Nessuna richiesta.",
   "components.UserProfile.UserSettings.unauthorizedDescription": "Non hai l'autorizzazione per modificare le impostazioni di questo utente.",
   "components.UserProfile.UserSettings.UserPermissions.unauthorizedDescription": "Non è possibile modificare le proprie autorizzazioni.",
   "components.TvDetails.episodeRuntimeMinutes": "{runtime} minuti",
@@ -714,7 +705,6 @@
   "components.RequestModal.AdvancedRequester.tags": "Tag",
   "components.RequestModal.AdvancedRequester.selecttags": "Seleziona i tag",
   "components.RequestModal.AdvancedRequester.notagoptions": "Nessun tag.",
-  "components.Discover.noRequests": "Nessuna richiesta.",
   "components.Layout.VersionStatus.outofdate": "Non aggiornato",
   "components.Layout.VersionStatus.commitsbehind": "{commitsBehind} {commitsBehind, plural, one {versione} other {versioni}} indietro",
   "components.Settings.serviceSettingsDescription": "Configura i tuoi server {serverType} qui sotto. Puoi collegare più server {serverType}, ma solo due possono essere contrassegnati come predefiniti (uno non-4K e uno 4K). Gli amministratori possono selezionare il server usato per elaborare le nuove richieste prima dell'approvazione.",
@@ -876,7 +866,6 @@
   "components.IssueDetails.toaststatusupdated": "Stato segnalazione aggiornato correttamente!",
   "components.IssueDetails.toaststatusupdatefailed": "Qualcosa è andato storto durante l'aggiornamento dello stato della segnalazione.",
   "components.IssueList.IssueItem.problemepisode": "Episodio coinvolto",
-  "components.IssueModal.CreateIssueModal.issomethingwrong": "C'è un problema con {title}?",
   "components.IssueModal.CreateIssueModal.problemepisode": "Episodio coinvolto",
   "components.IssueModal.CreateIssueModal.problemseason": "Stagione coinvolta",
   "components.IssueModal.CreateIssueModal.toastFailedCreate": "Qualcosa è andato storto durante l'invio della segnalazione.",
@@ -1039,5 +1028,16 @@
   "components.Settings.Notifications.NotificationsPushbullet.channelTag": "Tag del canale",
   "components.UserProfile.UserSettings.UserGeneralSettings.validationDiscordId": "È necessario fornire un ID Utente Discord valido",
   "components.UserProfile.UserSettings.UserGeneralSettings.discordId": "ID Utente Discord",
-  "components.UserProfile.UserSettings.UserGeneralSettings.discordIdTip": "Il <FindDiscordIdLink>numero ID a più cifre</FindDiscordIdLink> associato al tuo account utente Discord"
+  "components.UserProfile.UserSettings.UserGeneralSettings.discordIdTip": "Il <FindDiscordIdLink>numero ID a più cifre</FindDiscordIdLink> associato al tuo account utente Discord",
+  "components.Settings.SettingsAbout.appDataPath": "Cartella applicazione",
+  "components.RequestBlock.languageprofile": "Lingua Profilo",
+  "components.MovieDetails.digitalrelease": "Uscita versione digitale",
+  "components.Discover.DiscoverWatchlist.discoverwatchlist": "La tua lista da guardare Plex",
+  "components.Discover.plexwatchlist": "La tua lista da guardare Plex",
+  "components.PermissionEdit.autorequest": "Richiesta automatica",
+  "components.Discover.DiscoverWatchlist.watchlist": "Lista da guardare Plex",
+  "components.MovieDetails.managemovie": "Gestisci Film",
+  "components.MovieDetails.physicalrelease": "Uscita versione fisica",
+  "components.MovieDetails.theatricalrelease": "Uscita nelle sale",
+  "components.MovieDetails.reportissue": "Segnala un problema"
 }
diff --git a/src/i18n/locale/ja.json b/src/i18n/locale/ja.json
index efb23ca1..db85347b 100644
--- a/src/i18n/locale/ja.json
+++ b/src/i18n/locale/ja.json
@@ -33,13 +33,12 @@
   "components.RequestModal.cancel": "キャンセルリクエスト",
   "components.RequestModal.extras": "おまけ",
   "components.RequestModal.numberofepisodes": "エピソード数",
-  "components.RequestModal.pendingrequest": "{title} がリクエスト中",
+  "components.RequestModal.pendingrequest": "",
   "components.RequestModal.requestCancel": "<strong>{title}</strong> のリクエストは取り消されました。",
   "components.RequestModal.requestSuccess": "<strong>{title}</strong> のリクエストは完了しました。",
   "components.RequestModal.requestadmin": "このリクエストは今すぐ承認されます。",
   "components.RequestModal.requestfrom": "{username} はすでにリクエストを上げています。",
   "components.RequestModal.requestseasons": "{seasonCount} シーズンをリクエスト",
-  "components.RequestModal.requesttitle": "{title}をリクエスト",
   "components.RequestModal.season": "シーズン",
   "components.RequestModal.seasonnumber": "シーズン {number}",
   "components.RequestModal.selectseason": "シーズンを選ぶ",
@@ -55,7 +54,7 @@
   "components.Settings.Notifications.webhookUrl": "ウェブフック URL",
   "components.Settings.RadarrModal.add": "サーバーを追加",
   "components.Settings.RadarrModal.apiKey": "API キー",
-  "components.Settings.RadarrModal.baseUrl": "ベース URL",
+  "components.Settings.RadarrModal.baseUrl": "URL のベース",
   "components.Settings.RadarrModal.createradarr": "Radarr サーバーを追加",
   "components.Settings.RadarrModal.defaultserver": "デフォルトサーバー",
   "components.Settings.RadarrModal.editradarr": "Radarr サーバーを編集",
@@ -79,7 +78,7 @@
   "components.Settings.RadarrModal.validationRootFolderRequired": "ルートフォルダーを選択してください",
   "components.Settings.SonarrModal.add": "サーバーを追加",
   "components.Settings.SonarrModal.apiKey": "API キー",
-  "components.Settings.SonarrModal.baseUrl": "ベース URL",
+  "components.Settings.SonarrModal.baseUrl": "URL のベース",
   "components.Settings.SonarrModal.createsonarr": "Sonarr サーバーを追加",
   "components.Settings.SonarrModal.defaultserver": "デフォルトサーバー",
   "components.Settings.SonarrModal.editsonarr": "Sonarr サーバーを編集",
@@ -157,17 +156,17 @@
   "components.UserList.userlist": "ユーザーリスト",
   "i18n.approve": "承認",
   "i18n.approved": "承認済み",
-  "i18n.available": "鑑賞可能",
+  "i18n.available": "視聴可能",
   "i18n.cancel": "キャンセル",
   "i18n.decline": "拒否する",
   "i18n.declined": "拒否済み",
   "i18n.delete": "削除",
   "i18n.movies": "映画",
-  "i18n.partiallyavailable": "一部鑑賞可能",
+  "i18n.partiallyavailable": "一部視聴可能",
   "i18n.pending": "リクエスト中",
   "i18n.processing": "処理中",
   "i18n.tvshows": "シリーズ",
-  "i18n.unavailable": "鑑賞不可",
+  "i18n.unavailable": "視聴不可",
   "pages.oops": "ああ",
   "pages.returnHome": "ホームへ戻る",
   "components.TvDetails.TvCast.fullseriescast": "すべての出演者",
@@ -230,8 +229,8 @@
   "i18n.requested": "リクエスト済み",
   "components.TvDetails.watchtrailer": "予告編を見る",
   "components.MovieDetails.watchtrailer": "予告編を見る",
-  "components.UserList.importfromplexerror": "Plexからユーザーをインポート中に問題が発生しました。",
-  "components.UserList.importfromplex": "Plexからユーザーをインポート",
+  "components.UserList.importfromplexerror": "Plex からユーザーをインポート中に問題が発生しました。",
+  "components.UserList.importfromplex": "Plex からユーザーをインポート",
   "components.UserList.importedfromplex": "Plex から新ユーザー {userCount} 名をインポートしました。",
   "components.TvDetails.viewfullcrew": "フルクルーを表示",
   "components.TvDetails.firstAirDate": "初放送日",
@@ -289,7 +288,7 @@
   "components.UserProfile.UserSettings.UserGeneralSettings.general": "一般",
   "components.Settings.general": "一般",
   "pages.internalservererror": "内部サーバーエラー",
-  "pages.somethingwentwrong": "問題が発生しました",
+  "pages.somethingwentwrong": "チケットが発生しました",
   "pages.serviceunavailable": "サービスが利用できません",
   "pages.pagenotfound": "ページが見つかりません",
   "pages.errormessagewithcode": "{statusCode}-{error}",
@@ -345,7 +344,6 @@
   "components.LanguageSelector.languageServerDefault": "デフォルト言語({language})",
   "components.DownloadBlock.estimatedtime": "所要時間:{time}",
   "components.Discover.upcomingtv": "今後リリースされるシリーズ",
-  "components.Discover.noRequests": "リクエストが有りません。",
   "components.Discover.TvGenreSlider.tvgenres": "シリーズのジャンル",
   "components.Discover.DiscoverTvGenre.genreSeries": "{genre}シリーズ",
   "components.Discover.DiscoverTvLanguage.languageSeries": "{language}のシリーズ",
@@ -356,17 +354,16 @@
   "components.Discover.DiscoverNetwork.networkSeries": "{network}シーリーズ",
   "components.Discover.DiscoverMovieLanguage.languageMovies": "{language}の映画",
   "components.Discover.DiscoverMovieGenre.genreMovies": "{genre}映画",
-  "components.RequestModal.pending4krequest": "{title} が 4K リクエスト中",
+  "components.RequestModal.pending4krequest": "",
   "components.RequestModal.errorediting": "リクエストを編集するときに問題が発生しました。",
   "components.RequestModal.edit": "リクエストを編集",
   "components.RequestModal.autoapproval": "自動承認",
   "components.RequestModal.alreadyrequested": "すでにリクエスト済み",
   "components.RequestModal.SearchByNameModal.notvdbiddescription": "リクエストは自動的にマッチできませんでした。以下のリストから正しいマッチングを選択してください。",
-  "components.RequestModal.SearchByNameModal.nosummary": "このタイトルの概要は見つかりませんでした。",
   "components.RequestModal.QuotaDisplay.seasonlimit": "シーズン",
   "components.RequestModal.QuotaDisplay.season": "シーズン",
-  "components.RequestModal.QuotaDisplay.requiredquotaUser": "このユーザーはこのシリーズをリクエストするには、最低でも <strong>{seasons}</strong> シーズンリクエストが残っている必要があります。",
-  "components.RequestModal.QuotaDisplay.requiredquota": "このシリーズをリクエストするには、最低でも <strong>{seasons}</strong> シーズンリクエストが残っている必要があります。",
+  "components.RequestModal.QuotaDisplay.requiredquotaUser": "このユーザーはこのシーズンをリクエストするには、最低でも <strong>{seasons}</strong> シーズンリクエストが残っている必要があります。",
+  "components.RequestModal.QuotaDisplay.requiredquota": "このシーズンをリクエストするには、最低でも <strong>{seasons}</strong> シーズンリクエストが残っている必要があります。",
   "components.RequestModal.QuotaDisplay.requestsremaining": "残り <strong>{remaining}</strong> {type}リクエスト",
   "components.RequestModal.QuotaDisplay.quotaLinkUser": "このユーザーのリクエスト制限は<ProfileLink>プロフィールページ</ProfileLink>で確認できます。",
   "components.RequestModal.QuotaDisplay.quotaLink": "リクエスト制限は<ProfileLink>プロフィールページ</ProfileLink>で確認できます。",
@@ -390,7 +387,7 @@
   "components.RequestButton.viewrequest": "リクエストを表示",
   "components.PermissionEdit.viewrequestsDescription": "他のユーザーのリクエストを表示する権限を付与する。",
   "components.RequestList.sortModified": "最終更新日",
-  "components.RequestList.sortAdded": "リクエスト日",
+  "components.RequestList.sortAdded": "最新リクエスト",
   "components.RequestList.showallrequests": "すべてのリクエストを表示",
   "components.RequestList.RequestItem.requesteddate": "リクエストユーザー",
   "components.RequestList.RequestItem.requested": "リクエスト",
@@ -422,7 +419,7 @@
   "components.RegionSelector.regionDefault": "全地域",
   "components.QuotaSelector.unlimited": "無制限",
   "components.QuotaSelector.tvRequests": "<quotaUnits>{quotaDays} {days}に </quotaUnits>{quotaLimit} {seasons}",
-  "components.QuotaSelector.seasons": "シーズン",
+  "components.QuotaSelector.seasons": "{count, plural, one {シーズン} other {シーズン}}",
   "components.QuotaSelector.movies": "映画",
   "components.QuotaSelector.movieRequests": "<quotaUnits>{quotaDays} {days}に </quotaUnits>{quotaLimit} {movies}",
   "components.QuotaSelector.days": "日",
@@ -430,8 +427,6 @@
   "components.PermissionEdit.usersDescription": "ユーザーを管理する権限を付与する。この権限を持つユーザーは、Admin 権限を持つユーザーの変更や、Admin 権限を付与することはできません。",
   "components.NotificationTypeSelector.mediarequestedDescription": "ユーザーが承認を必要とする新メディアリクエストをすると通知する。",
   "components.PermissionEdit.users": "ユーザー管理",
-  "components.PermissionEdit.settingsDescription": "設定を変更する権限を付与する。他の人にこの権限を付与するには、ユーザーがこの権限を持っていなければなりません。",
-  "components.PermissionEdit.settings": "設定の管理",
   "components.PermissionEdit.requestTvDescription": "4K 以外のシリーズをリクエストする権限を与える。",
   "components.PermissionEdit.requestTv": "シリーズをリクエスト",
   "components.PermissionEdit.requestMoviesDescription": "4K 以外の映画をリクエストする権限を与える。",
@@ -461,7 +456,7 @@
   "components.PermissionEdit.autoapprove4kDescription": "すべての4Kリクエストを自動的に承認する。",
   "components.PermissionEdit.autoapprove4k": "4Kの自動承認",
   "components.PermissionEdit.autoapprove": "自動承認",
-  "components.PermissionEdit.advancedrequestDescription": "高度なリクエストオプションを使用する権限を付与します。",
+  "components.PermissionEdit.advancedrequestDescription": "高度なメディアリクエスト設定を変更する権限を付与する",
   "components.PermissionEdit.advancedrequest": "アドバンスド・リクエスト",
   "components.PermissionEdit.adminDescription": "管理者のフルアクセス。すべての権限チェックをバイパスします。",
   "components.PermissionEdit.admin": "管理者",
@@ -472,17 +467,17 @@
   "components.NotificationTypeSelector.usermediaapprovedDescription": "メディアリクエストが承認されると通知する。",
   "components.NotificationTypeSelector.usermediaAutoApprovedDescription": "他のユーザーの新メディアリクエストが自動的に承認されると通知する。",
   "components.NotificationTypeSelector.notificationTypes": "通知タイプ",
-  "components.NotificationTypeSelector.mediarequested": "メディアのリクエスト",
+  "components.NotificationTypeSelector.mediarequested": "リクエストは未承認",
   "components.NotificationTypeSelector.mediafailedDescription": "RadarrまたはSonarrへのメディアリクエストの追加に失敗したときに通知をする。",
-  "components.NotificationTypeSelector.mediafailed": "メディアの失敗",
+  "components.NotificationTypeSelector.mediafailed": "リクエストの処理が失敗した",
   "components.NotificationTypeSelector.mediadeclinedDescription": "メディアリクエストが拒否されると通知する。",
-  "components.NotificationTypeSelector.mediadeclined": "メディア拒否",
+  "components.NotificationTypeSelector.mediadeclined": "リクエストは拒否された",
   "components.NotificationTypeSelector.mediaavailableDescription": "メディアリクエストが視聴可能になりますと通知する。",
-  "components.NotificationTypeSelector.mediaavailable": "メディア視聴可能",
+  "components.NotificationTypeSelector.mediaavailable": "リクエスト視聴可能",
   "components.NotificationTypeSelector.mediaapprovedDescription": "ユーザーのメディアリクエストが手動に承認されると通知する。",
-  "components.NotificationTypeSelector.mediaapproved": "メディアが承認された",
+  "components.NotificationTypeSelector.mediaapproved": "リクエストが承認された",
   "components.NotificationTypeSelector.mediaAutoApprovedDescription": "ユーザーの新メディアリクエストが自動的に承認されると通知する。",
-  "components.NotificationTypeSelector.mediaAutoApproved": "メディアを自動的に承認",
+  "components.NotificationTypeSelector.mediaAutoApproved": "リクエストを自動的に承認",
   "components.MovieDetails.showmore": "もっと表示",
   "components.MovieDetails.showless": "少なく表示",
   "components.MovieDetails.playonplex": "Plexで再生",
@@ -504,9 +499,8 @@
   "components.UserProfile.UserSettings.UserGeneralSettings.applanguage": "表示言語",
   "components.Settings.locale": "表示言語",
   "components.StatusBadge.status": "{status}",
-  "components.UserProfile.norequests": "リクエストが有りません。",
-  "components.ManageSlideOver.downloadstatus": "ダウンロード状況",
-  "components.ManageSlideOver.manageModalClearMedia": "メディアのデータを消去",
+  "components.ManageSlideOver.downloadstatus": "ダウンロード",
+  "components.ManageSlideOver.manageModalClearMedia": "データを消去",
   "components.ManageSlideOver.manageModalRequests": "リクエスト",
   "components.ManageSlideOver.openarr": "{arr} を開く",
   "components.ManageSlideOver.manageModalClearMediaWarning": "※リクエストを含め、すべての詳細情報が消去されます。この操作は元に戻すことができません。この作品が Plex ライブラリに存在する場合、詳細情報は次のスキャンで再作成されます。",
@@ -514,5 +508,168 @@
   "components.ManageSlideOver.manageModalNoRequests": "リクエストが有りません。",
   "components.ManageSlideOver.manageModalTitle": "{mediaType}を管理",
   "components.ManageSlideOver.movie": "映画",
-  "components.ManageSlideOver.tvshow": "シリーズ"
+  "components.ManageSlideOver.tvshow": "シリーズ",
+  "components.IssueDetails.IssueDescription.edit": "チケット内容を編集",
+  "components.IssueDetails.allepisodes": "全エピソード",
+  "components.IssueDetails.allseasons": "全シーリーズ",
+  "components.IssueDetails.closeissue": "チケットをクローズ",
+  "components.IssueDetails.deleteissue": "チケットの削除",
+  "components.IssueDetails.commentplaceholder": "コメントを追加",
+  "components.IssueDetails.deleteissueconfirm": "こちらのチケットを削除しますか?",
+  "components.IssueDetails.openinarr": "{arr} を開く",
+  "components.IssueDetails.season": "シーズン {seasonNumber}",
+  "components.IssueDetails.toaststatusupdated": "課題のステータスが正常に更新されました!",
+  "components.IssueDetails.toaststatusupdatefailed": "チケットステータスを更新する際に、問題が発生しました。",
+  "components.IssueDetails.unknownissuetype": "不明",
+  "components.IssueDetails.IssueComment.validationComment": "メッセージの入力が必要です",
+  "components.IssueDetails.IssueComment.areyousuredelete": "こちらのコメントを削除しますか?",
+  "components.IssueDetails.IssueComment.delete": "コメントを削除",
+  "components.IssueDetails.IssueComment.edit": "コメントを編集",
+  "components.IssueDetails.IssueComment.postedbyedited": "{username}による{relativeTime}に投稿(編集済み)",
+  "components.IssueDetails.IssueComment.postedby": "{username}による{relativeTime}に投稿",
+  "components.IssueDetails.nocomments": "コメントはありません。",
+  "components.IssueDetails.reopenissue": "チケットを再度開く",
+  "components.IssueDetails.problemseason": "該当シーリーズ",
+  "components.IssueDetails.IssueDescription.deleteissue": "チケットを削除",
+  "components.IssueDetails.IssueDescription.description": "チケット内容",
+  "components.IssueDetails.comments": "コメント一覧",
+  "components.IssueDetails.issuetype": "チケット種類",
+  "components.IssueDetails.lastupdated": "最終更新日",
+  "components.IssueDetails.leavecomment": "コメント",
+  "components.IssueDetails.openin4karr": "4K {arr} を開く",
+  "components.IssueDetails.play4konplex": "Plexで4K再生",
+  "components.IssueDetails.reopenissueandcomment": "コメント追加して再度開く",
+  "components.IssueDetails.playonplex": "Plexで再生する",
+  "components.IssueDetails.problemepisode": "該当エピソード",
+  "components.IssueDetails.closeissueandcomment": "コメント追加してクローズ",
+  "components.IssueDetails.episode": "エピソード {episodeNumber}",
+  "components.IssueDetails.issuepagetitle": "チケット",
+  "components.IssueDetails.openedby": "{username}は#{issueId}を{relativeTime}に開きました",
+  "components.IssueDetails.toasteditdescriptionfailed": "チケット内容編集中に問題が発生しました。",
+  "components.IssueDetails.toasteditdescriptionsuccess": "チケット内容の編集に成功しました!",
+  "components.IssueDetails.toastissuedeleted": "チケットの削除に成功しました!",
+  "components.IssueDetails.toastissuedeletefailed": "チケットの削除する時に問題が発生しました。",
+  "components.ManageSlideOver.mark4kavailable": "4Kで視聴可能にする",
+  "components.MovieDetails.streamingproviders": "現在ストリーミング配信可能なプラットフォーム",
+  "components.NotificationTypeSelector.issuecreated": "チケット報告した",
+  "components.RequestModal.requestseasons4k": "4Kで{seasonCount}{seasonCount, plural, one {シーズン} other {シーズン}}をリクエスト",
+  "components.RequestModal.selectmovies": "映画を選択する",
+  "components.ResetPassword.confirmpassword": "パスワードを確認",
+  "components.ResetPassword.passwordreset": "パスワードをリセット",
+  "components.ResetPassword.requestresetlinksuccessmessage": "パスワードリセットリンクは、有効なユーザーの場合のみ、提供されたメールアドレスに送信されます。",
+  "components.Settings.Notifications.NotificationsGotify.gotifysettingsfailed": "Gotify の通知設定の保存に失敗しました。",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pgpPublicKeyTip": "メールを <OpenPgpLink>OpenPGP</OpenPgpLink> で暗号化する",
+  "components.IssueList.IssueItem.episodes": "{episodeCount, plural, one {エピソード} other {エピソード}}",
+  "components.IssueList.IssueItem.unknownissuetype": "不明",
+  "components.IssueList.sortAdded": "最新",
+  "components.IssueModal.CreateIssueModal.allseasons": "すべてのシーズン",
+  "components.IssueList.showallissues": "すべてのチケットを表示",
+  "components.IssueModal.CreateIssueModal.episode": "エピソード {episodeNumber}",
+  "components.IssueModal.CreateIssueModal.extras": "特典",
+  "components.IssueModal.CreateIssueModal.problemseason": "該当シーズン",
+  "components.IssueModal.CreateIssueModal.providedetail": "チケットの詳細をご記入ください。",
+  "components.IssueModal.CreateIssueModal.submitissue": "報告を送信",
+  "components.IssueModal.CreateIssueModal.toastFailedCreate": "報告送信時に問題が発生した。",
+  "components.IssueModal.CreateIssueModal.toastSuccessCreate": "<strong>{title}</strong> の報告が送信されました!",
+  "components.IssueModal.CreateIssueModal.toastviewissue": "チケットを表示",
+  "components.IssueModal.CreateIssueModal.whatswrong": "どうしましたか?",
+  "components.IssueModal.issueOther": "その他",
+  "components.IssueModal.issueSubtitles": "字幕",
+  "components.IssueModal.issueVideo": "映像",
+  "components.IssueModal.CreateIssueModal.validationMessageRequired": "チケットの詳細を記入する必要があります",
+  "components.Layout.Sidebar.issues": "チケット",
+  "components.ManageSlideOver.manageModalIssues": "未解決チケット",
+  "components.NotificationTypeSelector.issuecomment": "チケットのコメント",
+  "components.NotificationTypeSelector.userissueresolvedDescription": "自分が報告したチケットが解決された際に通知を受ける",
+  "components.PermissionEdit.viewissuesDescription": "他ユーザーが作成されたチケットを確認できる",
+  "components.Settings.Notifications.NotificationsLunaSea.agentenabled": "エージェントを有効にする",
+  "components.TvDetails.seasons": "{seasonCount, plural, one {#シーズン} other {#シーズン}}",
+  "components.Search.search": "検索",
+  "components.ManageSlideOver.opentautulli": "Tautulliで開く",
+  "components.ManageSlideOver.alltime": "現在まで",
+  "components.ManageSlideOver.manageModalAdvanced": "高度設定",
+  "components.ManageSlideOver.manageModalMedia": "メディア",
+  "components.ManageSlideOver.pastdays": "過去{days, number}日",
+  "components.ManageSlideOver.plays": "<strong>{playCount, number}</strong>{playCount, plural, one {回} other {回}}",
+  "components.ManageSlideOver.markallseasons4kavailable": "すべてのシーズンを4Kで視聴可能にする",
+  "components.NotificationTypeSelector.issuecommentDescription": "チケットにコメントが追加される際に通知を受ける",
+  "components.NotificationTypeSelector.issuereopened": "チケットを再度開いた",
+  "components.NotificationTypeSelector.userissuecreatedDescription": "他ユーザーがチケットを報告する際に通知を受ける",
+  "components.NotificationTypeSelector.userissuereopenedDescription": "自ら報告したチケットが再度開いた際に通知を受ける",
+  "components.PermissionEdit.manageissuesDescription": "メディアのチケットを管理する権限を付与する",
+  "components.Settings.Notifications.NotificationsGotify.validationUrlTrailingSlash": "URL の末尾にスラッシュ( / )を入力してないでください",
+  "components.Settings.Notifications.NotificationsLunaSea.profileName": "プロフィール名",
+  "components.IssueList.sortModified": "最終更新",
+  "components.IssueModal.CreateIssueModal.allepisodes": "すべてのエピソード",
+  "components.IssueModal.CreateIssueModal.problemepisode": "該当エピソード",
+  "components.NotificationTypeSelector.issueresolved": "チケット解決済み",
+  "components.NotificationTypeSelector.issueresolvedDescription": "チケットが解決される際に通知を受ける",
+  "components.NotificationTypeSelector.userissuecommentDescription": "自分が報告したチケットにコメントが追加した際に通知を受ける",
+  "components.PermissionEdit.createissues": "チケットを報告",
+  "components.PermissionEdit.manageissues": "チケットを管理",
+  "components.PermissionEdit.viewissues": "チケットを表示",
+  "components.RequestModal.approve": "リクエストを承認",
+  "i18n.open": "未解決",
+  "components.RequestBlock.languageprofile": "言語プロフィール",
+  "components.RequestModal.requestApproved": "<strong>{title}</strong> のリクエストは承認されました!",
+  "components.RequestModal.requestcancelled": "<strong>{title}</strong> のリクエストはキャンセルされました。",
+  "components.RequestModal.requestmovies": "{count}{count, plural, one {映画} other {映画}}をリクエスト",
+  "components.RequestModal.requestmovies4k": "{count}{count, plural, one {映画} other {映画}}を4Kでリクエスト",
+  "components.ResetPassword.emailresetlink": "パスワードリセットリンクを送信",
+  "components.ResetPassword.gobacklogin": "ログインページへ戻る",
+  "components.ResetPassword.resetpassword": "パスワードをリセットする",
+  "components.ResetPassword.resetpasswordsuccessmessage": "パスワードリセットが成功しました!",
+  "components.ResetPassword.validationpasswordmatch": "パスワードは一致する必要があります",
+  "components.ResetPassword.validationpasswordminchars": "8文字以上のパスワードを入力してください",
+  "components.Settings.Notifications.NotificationsGotify.gotifysettingssaved": "Gotify の通知設定が保存されました!",
+  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestSending": "Gotify のテスト通知を送信中…",
+  "components.Settings.Notifications.NotificationsGotify.validationTypes": "通知の種類は一つ以上を選択してください",
+  "components.Settings.Notifications.NotificationsGotify.validationUrlRequired": "有効な URL を入力してください",
+  "components.Settings.Notifications.pgpPasswordTip": "<OpenPgpLink>OpenPGP</OpenPgpLink> を利用してメールを送信",
+  "components.IssueList.IssueItem.issuestatus": "ステータス",
+  "components.IssueList.IssueItem.opened": "報告者/報告日時:",
+  "components.IssueList.IssueItem.openeduserdate": "{user}・{date}",
+  "components.IssueList.IssueItem.problemepisode": "該当エピソード",
+  "components.IssueList.IssueItem.issuetype": "種類",
+  "components.IssueModal.issueAudio": "オーディオ",
+  "components.IssueModal.CreateIssueModal.reportissue": "チケットを報告",
+  "components.IssueModal.CreateIssueModal.season": "シーズン {seasonNumber}",
+  "components.ManageSlideOver.markallseasonsavailable": "すべてのシーズンを視聴可能にする",
+  "components.IssueList.issues": "チケット",
+  "components.IssueList.IssueItem.viewissue": "チケットを閲覧",
+  "components.IssueList.IssueItem.seasons": "{seasonCount, plural, one {シーズン} other {シーズン}}",
+  "components.ManageSlideOver.playedby": "再生者",
+  "components.Settings.Notifications.pgpPrivateKeyTip": "<OpenPgpLink>OpenPGP</OpenPgpLink> を利用して暗号化されたメールを署名",
+  "components.ManageSlideOver.manageModalMedia4k": "4Kメディア",
+  "components.MovieDetails.productioncountries": "制作{countryCount, plural, one {国} other {国}}",
+  "components.NotificationTypeSelector.issuecreatedDescription": "チケットが報告される際に通知を送信",
+  "components.PermissionEdit.createissuesDescription": "チケットを報告できる権限を付与する",
+  "components.NotificationTypeSelector.adminissuecommentDescription": "他のユーザーがチケットにコメントした際に通知を受ける",
+  "components.NotificationTypeSelector.adminissuereopenedDescription": "他ユーザーがチケットを報告する際に通知を受ける",
+  "components.NotificationTypeSelector.adminissueresolvedDescription": "他ユーザーがチケットを解決した際に通知を受ける",
+  "components.NotificationTypeSelector.issuereopenedDescription": "チケットが再度開く際に通知を受ける",
+  "components.ManageSlideOver.markavailable": "視聴可能にする",
+  "components.RequestModal.requestedited": "<strong>{title}</strong>のリクエストは編集に成功しました!",
+  "components.RequestModal.requesterror": "リクエストの送信中に問題が発生しました。",
+  "components.Settings.Notifications.NotificationsGotify.validationTokenRequired": "アプリケーショントークンを入力してください",
+  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestFailed": "Gotify のテスト通知の送信に失敗しました。",
+  "components.Settings.Notifications.NotificationsGotify.agentenabled": "エージェントを有効にする",
+  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestSuccess": "Gotify のテスト通知を送信しました!",
+  "components.Settings.Notifications.NotificationsGotify.token": "アプリケーショントークン",
+  "components.Settings.Notifications.NotificationsGotify.url": "サーバーの URL",
+  "components.Settings.Notifications.NotificationsLunaSea.validationTypes": "通知の種類は一つ以上を選択してください",
+  "components.Settings.Notifications.NotificationsLunaSea.webhookUrlTip": "ユーザーまたはデバイスベースの <LunaSeaLink>notification webhook URL</LunaSeaLink> を指定します。",
+  "components.Settings.Notifications.NotificationsLunaSea.validationWebhookUrl": "有効な URL を入力してください",
+  "components.Settings.Notifications.NotificationsLunaSea.profileNameTip": "<code>default</code> プロファイルを使用しない場合のみ必要です。",
+  "components.Settings.Notifications.NotificationsLunaSea.toastLunaSeaTestSending": "LunaSea テスト通知送信中…",
+  "components.Settings.Notifications.NotificationsLunaSea.webhookUrl": "ウェブフック URL",
+  "components.Settings.Notifications.NotificationsLunaSea.toastLunaSeaTestFailed": "LunaSea のテスト通知の送信に失敗しました。",
+  "components.Settings.Notifications.NotificationsSlack.validationWebhookUrl": "有効な URL を入力してください",
+  "components.Settings.RadarrModal.validationApplicationUrl": "有効な URL を入力してください",
+  "components.Settings.Notifications.validationUrl": "有効な URL を入力してください",
+  "components.Settings.SonarrModal.validationApplicationUrl": "有効な URL を入力してください",
+  "components.Settings.urlBase": "URL のベース",
+  "components.Settings.validationApplicationUrl": "有効な URL を入力してください",
+  "components.Settings.validationUrl": "有効な URL を入力してください",
+  "components.Settings.Notifications.NotificationsWebhook.validationWebhookUrl": "有効な URL を入力してください"
 }
diff --git a/src/i18n/locale/lt.json b/src/i18n/locale/lt.json
new file mode 100644
index 00000000..951e20cf
--- /dev/null
+++ b/src/i18n/locale/lt.json
@@ -0,0 +1,540 @@
+{
+  "components.Discover.DiscoverMovieGenre.genreMovies": "{genre} filmai",
+  "components.CollectionDetails.overview": "Apžvalga",
+  "components.CollectionDetails.requestcollection": "Rezervacijų kolekcija",
+  "components.Discover.DiscoverMovieLanguage.languageMovies": "{language} filmai",
+  "components.Discover.DiscoverNetwork.networkSeries": "{network} serialai",
+  "components.Discover.DiscoverTvLanguage.languageSeries": "{language} serialai",
+  "components.Discover.StudioSlider.studios": "Studijos",
+  "components.Discover.TvGenreList.seriesgenres": "Serialų žanrai",
+  "components.Discover.popularmovies": "Populiarūs filmai",
+  "components.Discover.populartv": "Populiarūs serialai",
+  "components.Discover.recentlyAdded": "Paskutiniai pridėti",
+  "components.Discover.TvGenreSlider.tvgenres": "Serialų žanrai",
+  "components.Discover.trending": "Populiarėjantys",
+  "components.DownloadBlock.estimatedtime": "Liko {time}",
+  "components.IssueDetails.IssueComment.areyousuredelete": "Ar tikrai norite ištrinti šį komentarą?",
+  "components.IssueDetails.IssueComment.delete": "Ištrinti komentarą",
+  "components.IssueDetails.IssueComment.edit": "Redaguoti komentarą",
+  "components.IssueDetails.IssueComment.postedby": "{username} paskelbė {relativeTime}",
+  "components.IssueDetails.IssueComment.postedbyedited": "{username} paskelbė {relativeTime} (Redaguota)",
+  "components.IssueDetails.IssueComment.validationComment": "Privalote įrašyti tekstą",
+  "components.IssueDetails.IssueDescription.deleteissue": "Pašalinti problemą",
+  "components.IssueDetails.comments": "Komentarai",
+  "components.IssueDetails.closeissue": "Užbaigta problema",
+  "components.IssueDetails.closeissueandcomment": "Uždaryti su komentaru",
+  "components.IssueDetails.commentplaceholder": "Pridėti komentarą…",
+  "components.IssueDetails.deleteissue": "Pašalinti problemą",
+  "components.IssueDetails.deleteissueconfirm": "Ar tikrai norite pašalinti šią problemą?",
+  "components.IssueDetails.episode": "{episodeNumber} epizodas",
+  "components.IssueDetails.issuepagetitle": "Problema",
+  "components.IssueDetails.nocomments": "Nėra komentarų.",
+  "components.IssueDetails.play4konplex": "Groti 4k per Plex",
+  "components.IssueModal.CreateIssueModal.allseasons": "Visi sezonai",
+  "components.IssueModal.CreateIssueModal.episode": "{episodeNumber} epizodai",
+  "components.IssueList.issues": "Problemos",
+  "components.Layout.Sidebar.requests": "Rezervacijos",
+  "components.Layout.Sidebar.settings": "Nustatymai",
+  "components.Layout.Sidebar.users": "Vartotojai",
+  "components.Layout.UserDropdown.myprofile": "Profilis",
+  "components.IssueModal.issueAudio": "Audio",
+  "components.IssueModal.issueSubtitles": "Subtitrai",
+  "components.Layout.SearchInput.searchPlaceholder": "Ieškoti filmų ir laidų",
+  "components.LanguageSelector.originalLanguageDefault": "Visos kalbos",
+  "components.Layout.LanguagePicker.displaylanguage": "Rodoma kalba",
+  "components.Login.forgotpassword": "Ar pamiršai slaptažodį?",
+  "components.Login.email": "El. paštas",
+  "components.Login.signinheader": "Prisijunkite, kad tęsti",
+  "components.Login.signinwithplex": "Naudokite savo Plex prisijungimą",
+  "components.Login.validationpasswordrequired": "Prašau pateikti slaptažodį",
+  "components.ManageSlideOver.alltime": "Visi",
+  "components.ManageSlideOver.downloadstatus": "Parsisiuntimai",
+  "components.ManageSlideOver.movie": "filmas",
+  "components.ManageSlideOver.tvshow": "serialas",
+  "components.MovieDetails.MovieCast.fullcast": "Visi aktoriai",
+  "components.MovieDetails.budget": "Biudžetas",
+  "components.MovieDetails.originaltitle": "Originalus pavadinimas",
+  "components.MovieDetails.overview": "Apžvalga",
+  "components.MovieDetails.revenue": "Pajamos",
+  "components.MovieDetails.play4konplex": "Groti 4k per Plex",
+  "components.MovieDetails.playonplex": "Groti per Plex",
+  "components.MovieDetails.viewfullcrew": "Visa komanda",
+  "components.MovieDetails.similar": "Panašūs",
+  "components.MovieDetails.streamingproviders": "Šiuo metu transliuojama per",
+  "components.MovieDetails.studio": "{studioCount, plural, one {Studija} other {Studijos}}",
+  "components.PermissionEdit.request": "Rezervuoti",
+  "components.PersonDetails.crewmember": "Komanda",
+  "components.PersonDetails.appearsin": "Vaidino",
+  "components.PlexLoginButton.signingin": "Prisijungiama…",
+  "components.QuotaSelector.unlimited": "Neriboti",
+  "components.RequestButton.viewrequest": "Peržiūrėti rezervacijas",
+  "components.RequestCard.deleterequest": "Šalinti rezervacijas",
+  "components.RequestList.RequestItem.cancelRequest": "Atšaukti rezervaciją",
+  "components.RequestList.RequestItem.deleterequest": "Ištrinti rezervaciją",
+  "components.RequestList.RequestItem.editrequest": "Redaguoti rezervaciją",
+  "components.RequestList.RequestItem.requesteddate": "Rezervuota",
+  "components.RequestModal.AdvancedRequester.advancedoptions": "Detaliau",
+  "components.RequestModal.AdvancedRequester.default": "{name} (Numatytasis)",
+  "components.RequestModal.AdvancedRequester.qualityprofile": "Kokybės profilis",
+  "components.RequestModal.AdvancedRequester.destinationserver": "Serveris",
+  "components.RequestModal.edit": "Redaguoti rezervaciją",
+  "components.ResetPassword.email": "El. paštas",
+  "components.TvDetails.TvCrew.fullseriescrew": "Visa serialo komanda",
+  "components.TvDetails.cast": "Aktoriai",
+  "components.TvDetails.episodeRuntime": "Epizodo trukmė",
+  "components.TvDetails.episodeRuntimeMinutes": "{runtime} minutės",
+  "components.TvDetails.firstAirDate": "Pirmą kartą transliuota",
+  "components.TvDetails.network": "{networkCount, plural, one {Tinklas} other {Tinklai}}",
+  "components.TvDetails.nextAirDate": "Artimiausia transliacija",
+  "components.TvDetails.play4konplex": "Groti 4K raiška per Plex",
+  "components.TvDetails.playonplex": "Groti per Plex",
+  "components.TvDetails.productioncountries": "Kurta {countryCount, plural, one {šalyje} other {šalyse}}",
+  "components.TvDetails.recommendations": "Rekomendacijos",
+  "components.TvDetails.seasons": "{seasonCount, plural, one {# Sezonas} other {# Sezonai}}",
+  "components.TvDetails.showtype": "Serialo tipas",
+  "components.TvDetails.similar": "Panašūs serialai",
+  "components.TvDetails.streamingproviders": "Šiuo metu transliuoja",
+  "components.UserList.admin": "Administratorius",
+  "i18n.approve": "Patvirtinti",
+  "i18n.approved": "Patvirtintas",
+  "i18n.available": "Paruoštas",
+  "i18n.back": "Atgal",
+  "i18n.decline": "Atmesti",
+  "i18n.declined": "Atmestas",
+  "i18n.delete": "Ištrinti",
+  "i18n.deleting": "Trinama…",
+  "i18n.edit": "Redaguoti",
+  "i18n.failed": "Nepavyko",
+  "i18n.import": "Importuoti",
+  "i18n.importing": "Importuojama…",
+  "i18n.loading": "Kraunasi…",
+  "i18n.movie": "Filmas",
+  "i18n.noresults": "Nėra rezultatų.",
+  "i18n.notrequested": "Nerezervuotas",
+  "i18n.open": "Atidaryti",
+  "i18n.partiallyavailable": "Dalinai prieinamas",
+  "i18n.processing": "Apdorojama",
+  "i18n.resolved": "Išspręsta",
+  "i18n.resultsperpage": "{pageSize} rezultatų puslapyje",
+  "i18n.retry": "Bandyti iš naujo",
+  "i18n.retrying": "Bandoma iš naujo…",
+  "i18n.save": "Išsaugoti",
+  "i18n.showingresults": "Rodoma nuo <strong>{from}</strong> iki <strong>{to}</strong> iš <strong>{total}</strong> rezultatų",
+  "i18n.status": "Statusas",
+  "i18n.test": "Testas",
+  "i18n.testing": "Testuojama…",
+  "i18n.tvshow": "Serialas",
+  "i18n.tvshows": "Serialai",
+  "i18n.unavailable": "Neprieinamas",
+  "i18n.usersettings": "Vartotojo nustatymai",
+  "i18n.view": "Žiūrėti",
+  "pages.errormessagewithcode": "{statusCode} - {error}",
+  "pages.internalservererror": "Vidinė serverio klaida",
+  "pages.serviceunavailable": "Paslauga nepasiekiama",
+  "pages.somethingwentwrong": "Kažkas nepavyko",
+  "components.CollectionDetails.numberofmovies": "{count} filmai",
+  "components.Discover.NetworkSlider.networks": "Tinklai",
+  "components.Discover.discover": "Naršyti",
+  "components.IssueDetails.IssueDescription.description": "Aprašymas",
+  "components.IssueDetails.allseasons": "Visi sezonai",
+  "components.CollectionDetails.requestcollection4k": "4k rezervacijų kolekcija",
+  "components.Discover.discovertv": "Populiarūs serialai",
+  "components.IssueDetails.allepisodes": "Visi epizodai",
+  "components.IssueDetails.issuetype": "Tipas",
+  "components.IssueDetails.playonplex": "Groti per Plex",
+  "components.IssueDetails.lastupdated": "Paskutinį kartą atnaujinta",
+  "components.Discover.DiscoverStudio.studioMovies": "{studio} filmai",
+  "components.IssueDetails.leavecomment": "Komentaras",
+  "components.IssueDetails.openinarr": "Atverti {arr}",
+  "components.AppDataWarning.dockerVolumeMissingDescription": "Neteisingai sukonfigūruotas <code>{appDataPath}</code> disko prisijungimas. Visi duomenys bus išvalyti kai konteineris bus sustabdytas ir perkrautas.",
+  "components.Discover.upcomingtv": "Greit pasirodysiantys serialai",
+  "components.Discover.DiscoverTvGenre.genreSeries": "{genre} serialai",
+  "components.Discover.MovieGenreList.moviegenres": "Filmų žanrai",
+  "components.Discover.discovermovies": "Populiarūs filmai",
+  "components.Discover.recentrequests": "Paskutinės rezervacijos",
+  "components.Discover.MovieGenreSlider.moviegenres": "Filmų žanrai",
+  "components.Discover.upcoming": "Greit pasirodysiantys filmai",
+  "components.Discover.upcomingmovies": "Greit pasirodysiantys filmai",
+  "components.IssueDetails.IssueDescription.edit": "Redaguoti aprašymą",
+  "components.IssueDetails.openin4karr": "Atverti 4k {arr}",
+  "components.Layout.UserDropdown.signout": "Atsijungti",
+  "components.IssueDetails.season": "{seasonNumber} sezonas",
+  "components.Layout.Sidebar.dashboard": "Naršyti",
+  "components.Layout.Sidebar.issues": "Problemos",
+  "components.Layout.UserDropdown.settings": "Nustatymai",
+  "components.Login.password": "Slaptažodis",
+  "components.Login.signin": "Prisijungti",
+  "components.Login.signingin": "Prisijungia…",
+  "components.Layout.VersionStatus.outofdate": "Nebegaliojantis",
+  "components.Login.loginerror": "Kažkas nepavyko bandant prisijungti.",
+  "components.Login.signinwithoverseerr": "Naudokite {applicationTitle} prisijungimą",
+  "components.Login.validationemailrequired": "Prašau pateikti validų el. paštą",
+  "components.ManageSlideOver.manageModalMedia4k": "4k medija",
+  "components.MovieDetails.cast": "Aktoriai",
+  "components.MovieDetails.recommendations": "Rekomendacijos",
+  "components.ManageSlideOver.manageModalMedia": "Medija",
+  "components.ManageSlideOver.openarr4k": "Atverti 4k {arr}",
+  "components.ManageSlideOver.pastdays": "Per {days, number} dienas",
+  "components.MediaSlider.ShowMoreCard.seemore": "Daugiau",
+  "components.MovieDetails.originallanguage": "Originalo kalba",
+  "components.ManageSlideOver.openarr": "Atverti {arr}",
+  "components.MovieDetails.runtime": "{minutes} minutės",
+  "components.MovieDetails.showless": "Mažiau",
+  "components.MovieDetails.showmore": "Rodyti daugiau",
+  "components.MovieDetails.releasedate": "{releaseCount, plural, one {Išleidimo data} other {Išleidimo datos}}",
+  "components.MovieDetails.watchtrailer": "Žiūrėti trailerį",
+  "components.PermissionEdit.admin": "Administratorius",
+  "components.PermissionEdit.autoapprove": "Auto patvirtinti",
+  "components.IssueModal.CreateIssueModal.allepisodes": "Visi epizodai",
+  "components.MovieDetails.productioncountries": "Kurta {countryCount, plural, one {Šalyje} other {Šalyse}}",
+  "components.PermissionEdit.request4k": "Rezervuoti 4k",
+  "components.PermissionEdit.viewrequests": "Peržiūrėti rezervacijas",
+  "components.PersonDetails.birthdate": "Gimtadienis {birthdate}",
+  "components.QuotaSelector.movies": "{count, plural, one {filmas} other {filmai}}",
+  "components.MovieDetails.MovieCrew.fullcrew": "Visa komanda",
+  "components.PersonDetails.ascharacter": "kaip {character}",
+  "components.PersonDetails.alsoknownas": "Žinomas kaip: {names}",
+  "components.PersonDetails.lifespan": "{birthdate} – {deathdate}",
+  "components.PlexLoginButton.signinwithplex": "Prisijungti",
+  "components.QuotaSelector.days": "{count, plural, one {diena} other {dienos}}",
+  "components.RequestBlock.seasons": "{seasonCount, plural, one {Sezonas} other {Sezonai}}",
+  "components.RequestButton.requestmore": "Rezervuoti daugiau",
+  "components.RequestCard.failedretry": "Kažkas nepavyko kartojant rezervacijos užklausą.",
+  "components.QuotaSelector.seasons": "{count, plural, one {sezonas} other {sezonai}}",
+  "components.RequestBlock.languageprofile": "Kalbų profilis",
+  "components.RegionSelector.regionDefault": "Visi regionai",
+  "components.RegionSelector.regionServerDefault": "Numatytasis ({region})",
+  "components.RequestButton.requestmore4k": "Rezervuoti daugiau 4K raiška",
+  "components.RequestList.RequestItem.failedretry": "Kažkas nepavyko kartojant rezervacijos užklausą.",
+  "components.RequestList.RequestItem.modifieduserdate": "{date} - {user}",
+  "components.RequestList.showallrequests": "Rodyti visas rezervacijas",
+  "components.RequestCard.seasons": "{seasonCount, plural, one {Sezonas} other {Sezonai}}",
+  "components.RequestList.RequestItem.requested": "Rezervuota",
+  "components.RequestList.RequestItem.modified": "Redaguota",
+  "components.RequestModal.requesterror": "Kažkas nepavyko teikiant rezervaciją.",
+  "components.RequestList.RequestItem.seasons": "{seasonCount, plural, one {Sezonas} other {Sezonai}}",
+  "components.RequestList.requests": "Rezervacijos",
+  "components.RequestList.sortAdded": "Naujausi",
+  "components.RequestList.sortModified": "Seniausi",
+  "components.RequestModal.alreadyrequested": "Jau rezervuotas",
+  "i18n.request4k": "Rezervuoti 4K raiška",
+  "components.RequestModal.QuotaDisplay.movie": "filmas",
+  "components.RequestModal.requestedited": "<strong>{title}</strong> rezervacija redaguota sėkmingai!",
+  "components.ResetPassword.confirmpassword": "Patvirtinkite slaptažodį",
+  "components.RequestModal.AdvancedRequester.rootfolder": "Aplankas",
+  "components.RequestModal.cancel": "Atšaukti rezervaciją",
+  "components.RequestModal.numberofepisodes": "# iš epizodų",
+  "components.RequestModal.errorediting": "Kažkas nepavyko redaguojant rezervaciją.",
+  "components.RequestModal.requestcancelled": "<strong>{title}</strong> rezervacija atšaukta.",
+  "components.RequestModal.requestmovies": "Rezervuota {count} {count, plural, one {filmas} other {filmų}}",
+  "components.RequestModal.season": "Sezonas",
+  "components.RequestModal.requestApproved": "<strong>{title}</strong> rezervacija patvirtinta!",
+  "components.RequestModal.requestadmin": "Rezervacija bus automatiškai patvirtinta.",
+  "components.RequestModal.selectmovies": "Pasirinkite filmą(-us)",
+  "components.RequestModal.selectseason": "Pasirinkite sezoną(-us)",
+  "components.Search.searchresults": "Paieškos rezultatai",
+  "components.RequestModal.requestCancel": "<strong>{title}</strong> rezervacija atšaukta.",
+  "components.RequestModal.requestSuccess": "<strong>{title}</strong> rezervuota sėkmingai!",
+  "components.RequestModal.requestfrom": "Rezervacija iš {username} laukia patvirtinimo.",
+  "components.Search.search": "Paieška",
+  "components.TvDetails.TvCast.fullseriescast": "Visi serialo aktoriai",
+  "components.RequestModal.seasonnumber": "{number} sezonas",
+  "components.TvDetails.anime": "Anime",
+  "components.TvDetails.originallanguage": "Originalo kalba",
+  "components.TvDetails.viewfullcrew": "Visa komanda",
+  "components.TvDetails.watchtrailer": "Žiūrėti trailerį",
+  "components.TvDetails.originaltitle": "Originalus pavadinimas",
+  "components.TvDetails.overview": "Santrauka",
+  "components.TvDetails.overviewunavailable": "Nėra santraukos.",
+  "i18n.requested": "Rezervuotas",
+  "i18n.advanced": "Pažangu",
+  "i18n.canceling": "Atšaukiama…",
+  "i18n.close": "Uždaryti",
+  "i18n.requesting": "Rezervuojama…",
+  "i18n.saving": "Saugoma…",
+  "i18n.settings": "Nustatymai",
+  "components.UserList.accounttype": "Tipas",
+  "i18n.areyousure": "Ar tu tikras?",
+  "i18n.cancel": "Atšaukti",
+  "i18n.all": "Visi",
+  "i18n.movies": "Filmai",
+  "i18n.next": "Kitas",
+  "i18n.pending": "Eilėje",
+  "i18n.previous": "Ankstesnis",
+  "i18n.request": "Rezervuoti",
+  "pages.oops": "Ups...",
+  "pages.returnHome": "Grįžti į pradžią",
+  "pages.pagenotfound": "Puslapis nerastas",
+  "components.IssueDetails.problemepisode": "Paveikti epizodai",
+  "components.IssueDetails.reopenissueandcomment": "Atverti su komentaru",
+  "components.IssueList.IssueItem.problemepisode": "Paveiktas epizodas",
+  "components.IssueList.IssueItem.seasons": "{seasonCount, plural, one {Sezonas} other {Sezonai}}",
+  "components.IssueList.IssueItem.unknownissuetype": "Nežinoma",
+  "components.IssueList.IssueItem.viewissue": "Peržiūrėti problemą",
+  "components.ManageSlideOver.manageModalAdvanced": "Pažangiau",
+  "components.ManageSlideOver.manageModalClearMedia": "Išvalyti duomenis",
+  "components.ManageSlideOver.opentautulli": "Atverti per Tautulli",
+  "components.ManageSlideOver.playedby": "Vaidino",
+  "components.MovieDetails.mark4kavailable": "Pažymėk kaip prieinamą 4k raiška",
+  "components.MovieDetails.markavailable": "Pažymėti kaip prieinamą",
+  "components.MovieDetails.overviewunavailable": "Apžvalgos nėra.",
+  "components.NotificationTypeSelector.mediaavailable": "Rezervacija išpildyta",
+  "components.NotificationTypeSelector.mediadeclined": "Rezervacija atšaukta",
+  "components.NotificationTypeSelector.mediaapproved": "Rezervacija patvirtinta",
+  "components.NotificationTypeSelector.mediafailed": "Rezervacijos procesas nepavyko",
+  "components.NotificationTypeSelector.mediarequested": "Rezervacija laukia patvirtinimo",
+  "components.IssueDetails.problemseason": "Paveikti sezonai",
+  "components.IssueList.IssueItem.episodes": "{episodeCount, plural, one {Epizodas} other {Epizodai}}",
+  "components.IssueList.IssueItem.issuestatus": "Statusas",
+  "components.IssueDetails.reopenissue": "Iš naujo atverti problemą",
+  "components.IssueList.IssueItem.opened": "Atviros",
+  "components.IssueList.IssueItem.issuetype": "Tipas",
+  "components.IssueList.IssueItem.openeduserdate": "{date} - {user}",
+  "components.PermissionEdit.autoapprove4k": "Auto patvirtinti 4K",
+  "components.IssueDetails.toasteditdescriptionfailed": "Įvyko klaida redaguojant problemos aprašymą.",
+  "components.IssueDetails.toasteditdescriptionsuccess": "Problemos aprašas redaguotas sėkmingai!",
+  "components.IssueDetails.toastissuedeletefailed": "Įsivėlė klaida šalinant problemą.",
+  "components.IssueDetails.toaststatusupdated": "Problemos statusas sėkmingai atnaujintas!",
+  "components.IssueDetails.toaststatusupdatefailed": "Įvyko klaida atnaujinant problemos statusą.",
+  "components.IssueDetails.unknownissuetype": "Nežinoma",
+  "components.IssueList.showallissues": "Rodyti visas problemas",
+  "components.IssueList.sortAdded": "Naujausi",
+  "components.IssueList.sortModified": "Paskutinės redaguotos",
+  "components.IssueModal.CreateIssueModal.extras": "Papildomos",
+  "components.IssueModal.CreateIssueModal.problemepisode": "Paveikti epizodai",
+  "components.IssueModal.CreateIssueModal.providedetail": "Prašome pateikti detalų kilusios problemos aprašą.",
+  "components.IssueModal.CreateIssueModal.reportissue": "Pranešti apie problemą",
+  "components.IssueModal.CreateIssueModal.season": "Sezonas {seasonNumber}",
+  "components.IssueModal.CreateIssueModal.submitissue": "Pateikti problemą",
+  "components.IssueModal.CreateIssueModal.toastFailedCreate": "Įvyko klaida pateikiant problemą.",
+  "components.IssueModal.CreateIssueModal.toastSuccessCreate": "Problema <strong>{title}</strong> pateikta sėkmingai!",
+  "components.IssueModal.CreateIssueModal.toastviewissue": "Peržiūrėti problemą",
+  "components.IssueModal.CreateIssueModal.validationMessageRequired": "Prašome pateikti aprašą",
+  "components.IssueModal.CreateIssueModal.whatswrong": "Kas negerai?",
+  "components.IssueModal.issueOther": "Kita",
+  "components.IssueModal.issueVideo": "Video",
+  "components.LanguageSelector.languageServerDefault": "Numatytoji ({language})",
+  "components.Layout.VersionStatus.streamdevelop": "Overseerr kūrimas",
+  "components.Layout.VersionStatus.streamstable": "Overseerr Stabili",
+  "components.ManageSlideOver.manageModalIssues": "Atviros problemos",
+  "components.ManageSlideOver.manageModalNoRequests": "Nėra rezervacijų.",
+  "components.ManageSlideOver.manageModalRequests": "Rezervacijos",
+  "components.ManageSlideOver.manageModalTitle": "Valdyti {mediaType}",
+  "components.ManageSlideOver.mark4kavailable": "Pažymėti kaip prieinamą 4K raiška",
+  "components.ManageSlideOver.markallseasons4kavailable": "Pažymėti, kad visi sezonai prieinami 4K raiška",
+  "components.ManageSlideOver.markallseasonsavailable": "Pažymėti, kad visi sezonai prieinami",
+  "components.ManageSlideOver.markavailable": "Pažymėti, kaip prieinamą",
+  "components.ManageSlideOver.plays": "<strong>{playCount, number}</strong> {playCount, plural, one {peržiūra} other {peržiūros}}",
+  "components.IssueDetails.toastissuedeleted": "Problema pašalinta sėkmingai!",
+  "components.IssueModal.CreateIssueModal.problemseason": "Paveikti sezonai",
+  "components.IssueDetails.openedby": "#{issueId} problema atverta {relativeTime}, {username}",
+  "components.Layout.VersionStatus.commitsbehind": "{commitsBehind} {commitsBehind, plural, one {komitas} other {komitai}} behind",
+  "components.ManageSlideOver.manageModalClearMediaWarning": "* Tai negyžtamai pašalins {mediaType} tipo duomenis, įskaitant rezervacijas. Plex bibliotekoje esančios medijos informacija bus atkurta kito skanavimo metu.",
+  "components.NotificationTypeSelector.adminissuecommentDescription": "Gauti pranešimus kai kiti vartotojai komentuoja problemą.",
+  "components.NotificationTypeSelector.adminissueresolvedDescription": "Gauti pranešimus kai kiti vartotojai uždaro problemą.",
+  "components.NotificationTypeSelector.issuecomment": "Problemos komentaras",
+  "components.NotificationTypeSelector.issuecommentDescription": "Siųsti pranešimus kai problema gauna nauja komentarą.",
+  "components.NotificationTypeSelector.issuecreated": "Problema iš naujo atverta",
+  "components.NotificationTypeSelector.issuecreatedDescription": "Siųsti pranešimus, kai problemos iš naujo atveriamos.",
+  "components.NotificationTypeSelector.issuereopened": "Problema iš naujo atverta",
+  "components.NotificationTypeSelector.issuereopenedDescription": "Siųsti pranešimus, kai problema iš naujo atveriamos.",
+  "components.NotificationTypeSelector.issueresolved": "Problema išspręsta",
+  "components.NotificationTypeSelector.issueresolvedDescription": "Siųsti pranešimus, kai problemos išspręstos.",
+  "components.NotificationTypeSelector.mediaAutoApprovedDescription": "Siųsti pranešimus, kai vartotojai pateikia naują medijos rezervaciją, kuri automatiškai patvirtina.",
+  "components.NotificationTypeSelector.mediaapprovedDescription": "Siųsti pranešimus, medijos rezervacijos patvirtinamos ranka.",
+  "components.NotificationTypeSelector.mediaavailableDescription": "Siųsti pranešimą, kai medijos rezervacijos tampa prieinamos.",
+  "components.NotificationTypeSelector.mediadeclinedDescription": "Siųsti pranešimą, kai medijos rezervacijos atmetamos.",
+  "components.NotificationTypeSelector.mediafailedDescription": "Siųsti pranešimą, kai medijos rezervacijos neišeina pridėti Radarr ar Sonarr.",
+  "components.NotificationTypeSelector.notificationTypes": "Pranešimų tipai",
+  "components.NotificationTypeSelector.userissuereopenedDescription": "Gauti pranešimą, kai problemos, kurias tu pateikei iš naujo atveriamos.",
+  "components.NotificationTypeSelector.usermediaAutoApprovedDescription": "Gauti pranešimą, kai kiti vartotojai pateikia naują medijos rezervaciją, kurie automatiškai patvirtinami.",
+  "components.NotificationTypeSelector.usermediaapprovedDescription": "Gauti pranešimą, kai tavo medijos rezervacija patirtinta.",
+  "components.NotificationTypeSelector.userissueresolvedDescription": "Gauti pranešimą kai problema, kurią tu pateikei išsprendžiama.",
+  "components.NotificationTypeSelector.usermediaavailableDescription": "Gauti pranešimą kai tavo medijos rezervacija tampa prieinama.",
+  "components.NotificationTypeSelector.usermediadeclinedDescription": "Gauti rezervaciją, kai tavo medijos rezervacija atšaukiama.",
+  "components.NotificationTypeSelector.usermediafailedDescription": "Gauti pranešimą, kai medijos rezervacijos nepavyksta pridėti Radarr ar Sonarr.",
+  "components.NotificationTypeSelector.usermediarequestedDescription": "Gauti pranešimą kai kiti vartotojai pateikia naują medijos prašymą, kuriam reikalingas patvirtinimas.",
+  "components.PermissionEdit.adminDescription": "Pilnas administracinis rėžimas. Ignoruoti visus leidimų reikalavimus.",
+  "components.PermissionEdit.advancedrequest": "Detalesnės rezervacijos",
+  "components.PermissionEdit.advancedrequestDescription": "Sutiekti leidimus modifikuoti detalios rezervacijos pasirinkimus.",
+  "components.PermissionEdit.createissues": "Pateikti problemas",
+  "components.PermissionEdit.manageissues": "Valdyti problemas",
+  "components.PermissionEdit.managerequests": "Valdyti rezervacijas",
+  "components.PermissionEdit.request4kMovies": "Rezervuoti 4K filmus",
+  "components.PermissionEdit.request4kMoviesDescription": "Sutiekti leidimus pateikti rezervacijas 4K filmams.",
+  "components.PermissionEdit.request4kTv": "Rezervuoti 4K Serialus",
+  "components.PermissionEdit.requestMovies": "Rezervuoti filmus",
+  "components.PermissionEdit.requestTv": "Rezervuoti serialus",
+  "components.PermissionEdit.users": "Valdyti vartotojus",
+  "components.PermissionEdit.viewissues": "Peržiūrėti problemas",
+  "components.RequestBlock.profilechanged": "Kokybės profilis",
+  "components.RequestBlock.requestoverrides": "Rezervacijos pakeitimai",
+  "components.RequestBlock.rootfolder": "Pirminis aplankas",
+  "components.RequestBlock.server": "Numatytasis serveris",
+  "components.RequestButton.approve4krequests": "Tvirtinti {requestCount, plural, one {4K rezervacijas} other {{requestCount} 4K rezervacijas}}",
+  "components.RequestButton.approverequest4k": "Tvirtinti 4K rezervacijas",
+  "components.RequestButton.approverequests": "Tvirtinti {requestCount, plural, one {Rezervaciją} other {{requestCount} Rezervacijas}}",
+  "components.RequestButton.decline4krequests": "Atmesti {requestCount, plural, one {4K rezervaciją} other {{requestCount} 4K rezervacijas}}",
+  "components.RequestButton.declinerequests": "Atmesti {requestCount, plural, one {rezervaciją} other {{requestCount} rezervacijas}}",
+  "components.RequestButton.viewrequest4k": "Peržiūrėti 4K rezervacijas",
+  "components.RequestCard.mediaerror": "Susijusio pavadinimo rezervacija nebeprieinama.",
+  "components.RequestList.RequestItem.mediaerror": "Susijusio pavadinimo nebeprieinama rezervacijai.",
+  "components.RequestModal.AdvancedRequester.animenote": "* Šis serialas yra anime.",
+  "components.RequestModal.AdvancedRequester.folder": "{path} ({space})",
+  "components.RequestModal.AdvancedRequester.languageprofile": "Kalbų profilis",
+  "components.RequestModal.AdvancedRequester.notagoptions": "Nėra žymių.",
+  "components.RequestModal.AdvancedRequester.requestas": "Rezervuoti kaip",
+  "components.RequestModal.AdvancedRequester.selecttags": "Pasirinkti žymę",
+  "components.RequestModal.AdvancedRequester.tags": "Žymės",
+  "components.RequestModal.QuotaDisplay.allowedRequestsUser": "Šiam vartotojui leidžiama rezervuoti iki <strong>{limit}</strong> {type} kas <strong>{days}</strong> dienas.",
+  "components.RequestModal.QuotaDisplay.movielimit": "{limit, plural, one {filmas} other {filmai}}",
+  "components.RequestModal.QuotaDisplay.notenoughseasonrequests": "Nepakankamai sezonų rezervacijų liko",
+  "components.RequestModal.QuotaDisplay.quotaLink": "Galite peržiūrėti rezervacijų limitų apžvalgą savo <ProfileLink>profilio puslapyje</ProfileLink>.",
+  "components.RequestModal.QuotaDisplay.quotaLinkUser": "Galima peržiūrėti vartotojo rezervacijų limitų santrauką jų <ProfileLink>profilio puslapyje</ProfileLink>.",
+  "components.RequestModal.QuotaDisplay.requestsremaining": "{remaining, plural, =0 {No} other {<strong>#</strong>}} {type} {remaining, plural, one {rezervacija} other {rezervacijų}} liko",
+  "components.RequestModal.QuotaDisplay.requiredquota": "Jums reikia bent <strong>{seasons}</strong> {seasons, plural, one {sezono rezervacijos} other {sezonų rezervacijos}} likučio, kad rezervuoti šį serialą.",
+  "components.RequestModal.QuotaDisplay.requiredquotaUser": "Šiam vartootjui reikia <strong>{seasons}</strong> {seasons, plural, one {sezono rezervacijos} other {sezonų rezervacijų}}, kad rezervuoti šį serialą.",
+  "components.RequestModal.QuotaDisplay.season": "sezonas",
+  "components.RequestModal.QuotaDisplay.seasonlimit": "{limit, plural, one {sezonas} other {sezonai}}",
+  "components.RequestModal.SearchByNameModal.notvdbiddescription": "Negalėjome automatiškai surasti jūsų rezervacijos. Prašau pasirinkti tinkamą variantą iš galimų.",
+  "components.RequestModal.approve": "Tvirtinti rezervaciją",
+  "components.RequestModal.autoapproval": "Automatinis patvirtinimas",
+  "components.RequestModal.pending4krequest": "",
+  "components.RequestModal.pendingrequest": "",
+  "components.RequestModal.requestmovies4k": "Rezervacijos {count} {count, plural, one {filmo} other {filmų}} 4K raiška",
+  "components.RequestModal.requestseasons4k": "Rezervuoti {seasonCount} {seasonCount, plural, one {sezoną} other {sezonus}} 4K raiška",
+  "components.ResetPassword.emailresetlink": "El. pašto atkūrimo nuoroda",
+  "components.ResetPassword.gobacklogin": "Grįžti į prisijungimo puslapį",
+  "components.ResetPassword.password": "Slaptažodis",
+  "components.ResetPassword.passwordreset": "Slaptažodžio atstatymas",
+  "components.ResetPassword.requestresetlinksuccessmessage": "Slaptažodžio atkūrimo nuoroda bus atsiųsta pateiktu el. paštu, jei yra paskyra su kuria susijęs vartotojas.",
+  "components.ResetPassword.resetpassword": "Atstatyti slaptažodį",
+  "components.ResetPassword.resetpasswordsuccessmessage": "Slaptažodis atstatytas sėkmingai!",
+  "components.ResetPassword.validationemailrequired": "Prašome pateikti el. pašto adresą",
+  "components.ResetPassword.validationpasswordmatch": "Slaptažodžiai turi sutapti",
+  "components.ResetPassword.validationpasswordminchars": "Slaptažodis per trumpas; jis turėtų būti mažiai 8 simbolių",
+  "components.ResetPassword.validationpasswordrequired": "Privalote pateikti slaptažodį",
+  "components.Settings.SettingsAbout.about": "Apie",
+  "components.Settings.SettingsAbout.appDataPath": "Duomenų aplankas",
+  "components.Settings.SettingsAbout.documentation": "Dokumentacija",
+  "components.Settings.SettingsAbout.totalrequests": "Viso rezervacijų",
+  "components.Settings.SettingsAbout.timezone": "Laiko zona",
+  "components.Settings.SettingsAbout.totalmedia": "Viso medijos",
+  "components.Settings.SettingsAbout.uptodate": "Atnaujinta",
+  "components.Settings.SettingsJobsCache.cacheflushed": "{cachename} kešo valdymas.",
+  "components.Settings.SettingsAbout.version": "Versija",
+  "components.Settings.SettingsJobsCache.cache": "Kešas",
+  "components.Settings.SettingsJobsCache.cachehits": "Kvietimai",
+  "components.Settings.SettingsJobsCache.cachekeys": "Viso raktų",
+  "components.Settings.SettingsJobsCache.cacheksize": "Rakto dydis",
+  "components.Settings.SettingsJobsCache.cachemisses": "Praleisti",
+  "components.Settings.SettingsJobsCache.cachename": "Kešo vardas",
+  "components.Settings.SettingsJobsCache.cachevsize": "Dydis",
+  "components.Settings.SettingsJobsCache.runnow": "Paleisti dabar",
+  "components.Settings.SettingsLogs.filterError": "Klaida",
+  "components.Settings.SettingsLogs.filterInfo": "Informacija",
+  "components.Settings.SettingsLogs.filterWarn": "Perspėjimas",
+  "components.Settings.SettingsLogs.label": "Etiketė",
+  "components.Settings.SettingsLogs.level": "Rimtumas",
+  "components.NotificationTypeSelector.mediaAutoApproved": "Rezervacija automatiškai patvirtina",
+  "components.NotificationTypeSelector.adminissuereopenedDescription": "Gauti pranešimus kai kiti vartotojai atveria problemą.",
+  "components.NotificationTypeSelector.mediarequestedDescription": "Siųsti pranešimą, kai vartotojas patiekia naują medijos rezervaciją, kuriai reikalingas patvirtinimas.",
+  "components.NotificationTypeSelector.userissuecommentDescription": "Gauti pranešimą, kai problemas, kurias tu pateikei naujai pakomentuojamos.",
+  "components.NotificationTypeSelector.userissuecreatedDescription": "Gauti pranešimą, kai kiti vartotojai pateikia problemą.",
+  "components.QuotaSelector.movieRequests": "{quotaLimit} <quotaUnits>{movies} per {quotaDays} {days}</quotaUnits>",
+  "components.RequestButton.approverequest": "Tvirtinti rezervacijas",
+  "components.RequestButton.declinerequest": "Atmesti rezervacijas",
+  "components.RequestButton.declinerequest4k": "Atmesti 4K rezervacijas",
+  "components.RequestModal.QuotaDisplay.allowedRequests": "Jūs galite rezervuoti iki <strong>{limit}</strong> {type} kas <strong>{days}</strong> dienas.",
+  "components.RequestModal.extras": "Ekstros",
+  "components.RequestModal.pendingapproval": "Rezervacija laukia patvirtinimo.",
+  "components.RequestModal.requestseasons": "Rezervuoti {seasonCount} {seasonCount, plural, one {sezoną} other {sezonus}}",
+  "components.PermissionEdit.autoapprove4kDescription": "Suteikti automatinius patvirtinimus visoms 4K medijos rezervacijoms.",
+  "components.PermissionEdit.autoapprove4kMovies": "Auto-patvirtinti 4K filmus",
+  "components.Settings.Notifications.NotificationsGotify.agentenabled": "Įgalinti agentą",
+  "components.Settings.RadarrModal.add": "Pridėti serverį",
+  "components.Settings.RadarrModal.baseUrl": "URL pagrindas",
+  "components.Settings.RadarrModal.create4kradarr": "Pridėti naują 4K Radarr serverį",
+  "components.Settings.RadarrModal.createradarr": "Pridėti naują Radarr serverį",
+  "components.Settings.RadarrModal.defaultserver": "Numatytasis serveris",
+  "components.Settings.RadarrModal.edit4kradarr": "Redaguoti 4K Radarr serverį",
+  "components.Settings.RadarrModal.enableSearch": "Numatyti automatinę paiešką",
+  "components.Settings.RadarrModal.externalUrl": "Išorinė nuoroda",
+  "components.Settings.RadarrModal.hostname": "Domenas ar IP adresas",
+  "components.Settings.RadarrModal.inCinemas": "Kinuose",
+  "components.Settings.RadarrModal.loadingTags": "Kraunamos žymos…",
+  "components.Settings.RadarrModal.loadingprofiles": "Kraunami kokybės profiliai…",
+  "components.Settings.RadarrModal.loadingrootfolders": "Kraunami šakniniai aplankai…",
+  "components.Settings.RadarrModal.minimumAvailability": "Minimalus prieinamumas",
+  "components.Settings.RadarrModal.notagoptions": "Nėra žymių.",
+  "components.Settings.RadarrModal.port": "Portas",
+  "components.Settings.RadarrModal.qualityprofile": "Kokybės profilis",
+  "components.Settings.RadarrModal.released": "Išleisti",
+  "components.Settings.RadarrModal.rootfolder": "Šakninis aplankas",
+  "components.Settings.RadarrModal.selectMinimumAvailability": "Pasirinkti minimalų prieinamumą",
+  "components.Settings.RadarrModal.selectQualityProfile": "Pasirinkti kokybės profilį",
+  "components.Settings.RadarrModal.selectRootFolder": "Pasirinkti šakinį aplanką",
+  "components.Settings.RadarrModal.selecttags": "Pasirinkti žymes",
+  "components.Settings.SettingsAbout.Releases.currentversion": "Esama",
+  "components.Settings.SettingsAbout.Releases.latestversion": "Vėliausia",
+  "components.Settings.SettingsAbout.Releases.releasedataMissing": "Išleidimo data šiuo metu neprieinama.",
+  "components.Settings.SettingsAbout.Releases.releases": "Leidimai",
+  "components.Settings.SettingsJobsCache.download-sync-reset": "Parsiuntimų sinchronizacijos atstatymas",
+  "components.Settings.SettingsJobsCache.editJobSchedule": "Modifikuoti darbą",
+  "components.Settings.SettingsJobsCache.download-sync": "Parsisiuntimų sinchronizavimas",
+  "components.Settings.SettingsJobsCache.editJobSchedulePrompt": "Dažnis",
+  "components.Settings.SettingsJobsCache.process": "Procesas",
+  "components.Settings.SettingsLogs.logs": "Logai",
+  "components.Settings.SettingsUsers.defaultPermissions": "Numatytieji leidimai",
+  "components.Settings.SettingsUsers.defaultPermissionsTip": "Pradiniai leidimai numatyti naujiems vartotojams",
+  "components.Settings.SettingsUsers.localLogin": "Įgalinti lokalų prisijungimą",
+  "components.Settings.SettingsUsers.localLoginTip": "Leisti vartotojams prisijungti naudojantis jų el.paštu ir slaptažodžiu, vietoje Plex OAuth",
+  "components.Settings.SettingsUsers.movieRequestLimitLabel": "Globalus filmų rezervacijos limitas",
+  "components.Settings.SettingsUsers.newPlexLogin": "Įgalinti naujus Plex prisijungimus",
+  "components.Settings.SettingsUsers.newPlexLoginTip": "Leisti Plex vadotojams prisijungti praleidžiant jų importavimą",
+  "components.Settings.SettingsUsers.toastSettingsFailure": "Kažkas nepavyko išsaugant nustatymus.",
+  "components.Settings.SettingsUsers.toastSettingsSuccess": "Vartotojos nustatymai sėkmingai išsaugoti!",
+  "components.Settings.SettingsUsers.userSettingsDescription": "Konfigūruoti globalius ir numatytuosius vartojų nustatymus.",
+  "components.Settings.SettingsUsers.users": "Vartotojai",
+  "components.Settings.SonarrModal.add": "Pridėti serverį",
+  "components.Settings.SonarrModal.animeTags": "Anime žymos",
+  "components.Settings.SonarrModal.animelanguageprofile": "Anime kalbos profilis",
+  "components.Settings.SonarrModal.animequalityprofile": "Anime kokybės profilis",
+  "components.Settings.SonarrModal.animerootfolder": "Anime šakninis aplankas",
+  "components.Settings.SonarrModal.apiKey": "API raktas",
+  "components.Settings.SonarrModal.baseUrl": "URL pagrindas",
+  "components.Settings.SonarrModal.default4kserver": "Numatytasis 4K serveris",
+  "components.Settings.SonarrModal.defaultserver": "Numatytasis serveris",
+  "components.Settings.SonarrModal.edit4ksonarr": "Redaguoti 4K Sonarr serverį",
+  "components.Settings.SonarrModal.editsonarr": "Redaguoti Sonarr serverį",
+  "components.Settings.SonarrModal.externalUrl": "Išorinė nuoroda",
+  "components.Settings.SonarrModal.hostname": "Domenas ar IP adresas",
+  "components.Settings.SonarrModal.languageprofile": "Kalbų profilis",
+  "components.Settings.SonarrModal.loadingTags": "Kraunamos žymos…",
+  "components.Settings.SonarrModal.loadinglanguageprofiles": "Įkeliami kalbų profiliai…",
+  "components.Settings.SonarrModal.loadingprofiles": "Kraunami kokybės profiliai…",
+  "components.Settings.SonarrModal.loadingrootfolders": "Kraunami šakniniai aplankai…",
+  "components.Settings.SonarrModal.notagoptions": "Nėra žymių.",
+  "components.Settings.SonarrModal.port": "Portas",
+  "components.Settings.SonarrModal.rootfolder": "Šakninis aplankas",
+  "components.Settings.SonarrModal.selectLanguageProfile": "Pasirinkite kalbos profilį",
+  "components.Settings.SonarrModal.selectQualityProfile": "Pasirinkti kokybės profilį",
+  "components.Settings.SonarrModal.selectRootFolder": "Pasirinkti šakinį aplanką",
+  "components.Settings.SonarrModal.selecttags": "Pasirinkti žymes",
+  "components.Settings.SonarrModal.server4k": "4K serveris",
+  "components.Settings.SonarrModal.servername": "Serverio pavadinimas",
+  "components.Settings.SonarrModal.ssl": "Naudokite SSL",
+  "components.Settings.SettingsUsers.userSettings": "Vartotojo nustatymai",
+  "components.Settings.SettingsUsers.tvRequestLimitLabel": "Globalus serialų rezervacijos limitas",
+  "components.Settings.SonarrModal.createsonarr": "Pridėti naują Sonarr serverį",
+  "components.Settings.SonarrModal.tags": "Žymės",
+  "components.Settings.RadarrModal.announced": "Paskelbti",
+  "components.Settings.RadarrModal.apiKey": "API raktas",
+  "components.Settings.RadarrModal.default4kserver": "Numatytasis 4K serveris",
+  "components.Settings.RadarrModal.editradarr": "Redaguoti Radarr serverį",
+  "components.Settings.SonarrModal.enableSearch": "Įjungti automatinę paiešką",
+  "components.Settings.SonarrModal.create4ksonarr": "Pridėti naują 4K Sonarr serverį",
+  "components.Settings.SonarrModal.qualityprofile": "Kokybės profilis",
+  "components.Settings.SonarrModal.seasonfolders": "Sezono aplankai",
+  "components.Settings.SonarrModal.syncEnabled": "Įjungti nuskaitymą"
+}
diff --git a/src/i18n/locale/nb_NO.json b/src/i18n/locale/nb_NO.json
index 0bdd06ea..d9b78a44 100644
--- a/src/i18n/locale/nb_NO.json
+++ b/src/i18n/locale/nb_NO.json
@@ -30,16 +30,15 @@
   "components.RequestCard.seasons": "{seasonCount, plural, one {Sesong} other {Sesonger}}",
   "components.RequestList.RequestItem.seasons": "{seasonCount, plural, one {Sesong} other {Sesonger}}",
   "components.RequestList.requests": "Forespørsler",
-  "components.RequestModal.cancel": "Slett forespørsel",
+  "components.RequestModal.cancel": "Avbryt Forespørsel",
   "components.RequestModal.extras": "Ekstra",
   "components.RequestModal.numberofepisodes": "Antall episoder",
-  "components.RequestModal.pendingrequest": "Ventende forespørsel for {title}",
+  "components.RequestModal.pendingrequest": "Ventende forespørsel",
   "components.RequestModal.requestCancel": "Forespørsel for <strong>{title}</strong> kansellert.",
   "components.RequestModal.requestSuccess": "<strong>{title}</strong> forespurt!",
-  "components.RequestModal.requestadmin": "Din forespørsel vil bli godkjent automatisk.",
+  "components.RequestModal.requestadmin": "Denne forespørselen vil bli godkjent automagisk.",
   "components.RequestModal.requestfrom": "{username} sin forespørsel venter på godkjenning.",
   "components.RequestModal.requestseasons": "Forespør {seasonCount} {seasonCount, plural, one {Sesong} other {Sesonger}}",
-  "components.RequestModal.requesttitle": "Forespør {title}",
   "components.RequestModal.season": "Sesong",
   "components.RequestModal.seasonnumber": "Sesong {number}",
   "components.RequestModal.selectseason": "Velg sesong(er)",
@@ -181,7 +180,7 @@
   "components.UserProfile.UserSettings.UserGeneralSettings.role": "Rolle",
   "components.UserProfile.UserSettings.UserGeneralSettings.regionTip": "Filtrer innhold basert på regiontilgjengelighet",
   "components.UserProfile.UserSettings.UserGeneralSettings.region": "Utforskelsesregion",
-  "components.UserProfile.UserSettings.UserGeneralSettings.plexuser": "Plexbruker",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexuser": "Plex-bruker",
   "components.UserProfile.UserSettings.UserGeneralSettings.owner": "Eier",
   "components.UserProfile.UserSettings.UserGeneralSettings.originallanguageTip": "Filtrer innhold basert på originalspråk",
   "components.UserProfile.UserSettings.UserGeneralSettings.originallanguage": "Utforskelsesspråk",
@@ -255,11 +254,9 @@
   "components.ResetPassword.confirmpassword": "Verifiser passord",
   "components.RequestModal.requesterror": "Noe gikk galt ved sending av forespørsel.",
   "components.RequestModal.requestcancelled": "Forespørsel for <strong>{title}</strong> kansellert.",
-  "components.RequestModal.request4ktitle": "Forespør {title} i 4K",
-  "components.RequestModal.pending4krequest": "Ventende forespørsel i 4K for {title}",
+  "components.RequestModal.pending4krequest": "Ventende forespørsel i 4K",
   "components.RequestModal.errorediting": "Noe gikk galt under endring av forespørselen.",
-  "components.RequestModal.autoapproval": "Automatisk Godkjenning",
-  "components.RequestModal.SearchByNameModal.nosummary": "Fant ingen sammendrag.",
+  "components.RequestModal.autoapproval": "Automagisk Godkjenning",
   "components.RequestModal.AdvancedRequester.rootfolder": "Grunnmappe",
   "components.RequestModal.AdvancedRequester.requestas": "Forespør som",
   "components.RequestModal.AdvancedRequester.qualityprofile": "Kvalitetsprofil",
@@ -274,7 +271,7 @@
   "components.RequestList.showallrequests": "Vis Alle Forespørsler",
   "components.RequestList.RequestItem.modifieduserdate": "{date} av {user}",
   "components.RequestList.RequestItem.modified": "Endret",
-  "components.RequestList.RequestItem.failedretry": "Noe gikk galt under forespørsel-forsøket.",
+  "components.RequestList.RequestItem.failedretry": "Noe gikk galt mens du prøvde forespørselen på nytt.",
   "components.RequestButton.viewrequest4k": "Vis forespørsel i 4K",
   "components.RequestButton.viewrequest": "Vis Forespørsel",
   "components.RequestButton.requestmore4k": "Forespør mer i 4K",
@@ -300,40 +297,38 @@
   "components.PersonDetails.birthdate": "Født {birthdate}",
   "components.PersonDetails.alsoknownas": "Også kjent som: {names}",
   "components.PermissionEdit.viewrequests": "Vis Forespørsler",
-  "components.PermissionEdit.settingsDescription": "Gi tilgang til å endre globale innstillinger. En bruker må ha denne tilgangen for å kunne gi den til andre brukere.",
-  "components.PermissionEdit.settings": "Administrer Innstillinger",
-  "components.PermissionEdit.requestDescription": "Gi tilgang til å forespørre medie som ikke er i 4K.",
+  "components.PermissionEdit.requestDescription": "Gi tilgang til å forespørre matriale som ikke er i 4K.",
   "components.PermissionEdit.request4kTvDescription": "Gi tilgang til å forespørre serier i 4K.",
   "components.PermissionEdit.request4kTv": "Forespør Serier i 4K",
   "components.PermissionEdit.request4kMoviesDescription": "Gi tilgang til å forespørre filmer i 4K.",
   "components.PermissionEdit.request4kMovies": "Forespør Filmer i 4K",
-  "components.PermissionEdit.request4kDescription": "Gi tillatelse til å forespørre medie i 4K.",
+  "components.PermissionEdit.request4kDescription": "Gi tillatelse til å forespørre matriale i 4K.",
   "components.PermissionEdit.request4k": "Forespør i 4K",
   "components.PermissionEdit.request": "Forespør",
-  "components.PermissionEdit.managerequestsDescription": "Gi tilgang til å administrere medie-forespørsler. Alle forespørsler utført av en bruker med denne tilgangen vil automatisk bli godkjent.",
+  "components.PermissionEdit.managerequestsDescription": "Gi tilgang til å administrere forespørsler. Alle forespørsler utført av en bruker med denne tilgangen vil automagisk bli godkjent.",
   "components.PermissionEdit.managerequests": "Administrer Forespørsler",
-  "components.PermissionEdit.autoapproveSeriesDescription": "Godkjenn serieforespørsler som ikke er i 4K automatisk.",
-  "components.PermissionEdit.autoapproveSeries": "Godkjenn serieforespørsler automatisk",
-  "components.PermissionEdit.autoapproveMoviesDescription": "Godkjenn filmforespørsler som ikke er i 4K automatisk.",
-  "components.PermissionEdit.autoapproveMovies": "Godkjenn filmforespørsler automatisk",
-  "components.PermissionEdit.autoapproveDescription": "Godkjenn alle forespørsler som ikke er i 4K automatisk.",
-  "components.PermissionEdit.autoapprove4kSeriesDescription": "Godkjenn serieforespørsler i 4K automatisk.",
-  "components.PermissionEdit.autoapprove4kSeries": "Automatisk godkjenning av serier i 4K",
-  "components.PermissionEdit.autoapprove4kMoviesDescription": "Godkjenn filmforespørsler i 4K automatisk.",
-  "components.PermissionEdit.autoapprove4kMovies": "Automatisk godkjenning av filmer i 4K",
-  "components.PermissionEdit.autoapprove4kDescription": "Godkjenn alle forespørsler av 4K automatisk.",
-  "components.PermissionEdit.autoapprove4k": "Godkjenn 4K Automatisk",
-  "components.PermissionEdit.autoapprove": "Godkjenn Automatisk",
+  "components.PermissionEdit.autoapproveSeriesDescription": "Godkjenn serieforespørsler som ikke er i 4K automagisk.",
+  "components.PermissionEdit.autoapproveSeries": "Godkjenn serieforespørsler automagisk",
+  "components.PermissionEdit.autoapproveMoviesDescription": "Godkjenn filmforespørsler som ikke er i 4K automagisk.",
+  "components.PermissionEdit.autoapproveMovies": "Godkjenn filmforespørsler automagisk",
+  "components.PermissionEdit.autoapproveDescription": "Godkjenn alle forespørsler som ikke er i 4K automagisk.",
+  "components.PermissionEdit.autoapprove4kSeriesDescription": "Godkjenn serieforespørsler i 4K automagisk.",
+  "components.PermissionEdit.autoapprove4kSeries": "Automagisk godkjenning av serier i 4K",
+  "components.PermissionEdit.autoapprove4kMoviesDescription": "Godkjenn filmforespørsler i 4K automagisk.",
+  "components.PermissionEdit.autoapprove4kMovies": "Automagisk godkjenning av filmer i 4K",
+  "components.PermissionEdit.autoapprove4kDescription": "Godkjenn alle forespørsler av 4K automagisk.",
+  "components.PermissionEdit.autoapprove4k": "Godkjenn 4K Automagisk",
+  "components.PermissionEdit.autoapprove": "Godkjenn Automagisk",
   "components.PermissionEdit.advancedrequestDescription": "Gi tilgang til å endre avanserte forespørsler.",
   "components.PermissionEdit.advancedrequest": "Avanserte Forespørsler",
   "components.PermissionEdit.adminDescription": "Full administrator tilgang. Overstyrer alle andre tillatelser.",
   "components.PermissionEdit.admin": "Administrator",
   "components.NotificationTypeSelector.mediafailed": "Forespørsel Feilet",
-  "components.NotificationTypeSelector.mediadeclinedDescription": "Bli varslet når en medieforespørsel blir avvist.",
+  "components.NotificationTypeSelector.mediadeclinedDescription": "Bli varslet når en forespørsel om nytt matriale blir avvist.",
   "components.NotificationTypeSelector.mediadeclined": "Forespørsel Avvist",
   "components.NotificationTypeSelector.mediaavailable": "Forespørsel Tilgjengelig",
   "components.NotificationTypeSelector.mediaapproved": "Forespørsel Godkjent",
-  "components.NotificationTypeSelector.mediaAutoApproved": "Forespørsel Automatisk Godkjent",
+  "components.NotificationTypeSelector.mediaAutoApproved": "Forespørsel Automagisk Godkjent",
   "components.MovieDetails.watchtrailer": "Se Trailer",
   "components.MovieDetails.playonplex": "Spill av med Plex",
   "components.MovieDetails.play4konplex": "Spill av i 4K i Plex",
@@ -342,7 +337,7 @@
   "components.MediaSlider.ShowMoreCard.seemore": "Vis mer",
   "components.Login.validationpasswordrequired": "Du må skrive et passord",
   "components.Login.validationemailrequired": "Du må bruke en gyldig E-postadresse",
-  "components.Login.signinwithplex": "Bruk Plex-konto",
+  "components.Login.signinwithplex": "Bruk din Plex-konto",
   "components.Login.signinwithoverseerr": "Bruk {applicationTitle}-konto",
   "components.Login.signinheader": "Logg inn for å fortsette",
   "components.Login.signingin": "Logger inn…",
@@ -356,12 +351,12 @@
   "components.RequestModal.requestedited": "Redigerte forespørsel for <strong>{title}</strong>!",
   "components.RequestModal.alreadyrequested": "Allerede forespurt",
   "components.RequestList.RequestItem.requested": "Forespurt",
-  "components.NotificationTypeSelector.mediarequestedDescription": "Bli varslet når medie blir forespurt og krever godkjenning.",
+  "components.NotificationTypeSelector.mediarequestedDescription": "Bli varslet når nytt matriale blir forespurt og krever godkjenning.",
   "components.NotificationTypeSelector.mediarequested": "Forespørsel venter Godkjenning",
-  "components.NotificationTypeSelector.mediafailedDescription": "Bli varslet når forespurt medie ikke kan bli lagt til i Radarr eller Sonarr.",
-  "components.NotificationTypeSelector.mediaavailableDescription": "Bli varslet når forespurt medie blir tilgjengelig.",
-  "components.NotificationTypeSelector.mediaapprovedDescription": "Bli varslet når forespurt medie blir manuelt godkjent.",
-  "components.NotificationTypeSelector.mediaAutoApprovedDescription": "Bli varslet når medie blir forespurt og forespørselen automatisk blir godkjent.",
+  "components.NotificationTypeSelector.mediafailedDescription": "Bli varslet når forespurt matriale ikke kan bli lagt til i Radarr eller Sonarr.",
+  "components.NotificationTypeSelector.mediaavailableDescription": "Bli varslet når forespurt matriale blir tilgjengelig.",
+  "components.NotificationTypeSelector.mediaapprovedDescription": "Bli varslet når forespurt matriale blir manuelt godkjent.",
+  "components.NotificationTypeSelector.mediaAutoApprovedDescription": "Bli varslet når nytt matriale blir forespurt og forespørselen blir automagisk godkjent.",
   "i18n.delimitedlist": "{a}, {b}",
   "i18n.tvshow": "Serie",
   "components.UserProfile.seriesrequest": "Serieforespørsler",
@@ -372,13 +367,13 @@
   "components.MovieDetails.originaltitle": "Originaltittel",
   "i18n.all": "Alle",
   "components.UserList.deleteconfirm": "Er du sikker på at du ønsker å slette denne brukeren? All forespørseldata for denne brukeren vil bli slettet.",
-  "components.UserList.autogeneratepassword": "Generer passord automatisk",
+  "components.UserList.autogeneratepassword": "Generer passord automagisk",
   "components.Settings.originallanguageTip": "Filtrer innhold basert på originalspråk",
   "components.Settings.originallanguage": "Utforskelsesspråk",
   "components.Settings.SettingsLogs.showall": "Vis all logg",
   "components.Settings.SettingsJobsCache.cacheDescription": "Overseerr mellomlagrer forespørsler til eksterne APIer for å optimalisere ytelsen samt unngå unødvendige API-kall.",
   "components.Settings.Notifications.allowselfsigned": "Godta selvsignerte sertifikater",
-  "components.RequestModal.SearchByNameModal.notvdbiddescription": "Vi kunne ikke koble forespørselen din automatisk. Vennligst velg korrekt kobling fra listen under.",
+  "components.RequestModal.SearchByNameModal.notvdbiddescription": "Vi klarte ikke å koble denne serien automagisk. Vennligst velg riktig serie under.",
   "components.RequestModal.QuotaDisplay.allowedRequestsUser": "Denne brukeren har tillatelse til å forespørre <strong>{limit}</strong> {type} hver <strong>{days}.</strong> dag.",
   "components.RequestModal.QuotaDisplay.allowedRequests": "Du har tillatelse til å forespørre <strong>{limit}</strong> {type} hver <strong>{days}.</strong> dag.",
   "components.Settings.partialRequestsEnabled": "Godta ufullstendige serieforespørsler",
@@ -460,8 +455,8 @@
   "components.RequestModal.QuotaDisplay.quotaLinkUser": "Du kan se en oppsummering av denne brukerens forespørselbegrensninger på <ProfileLink>profilsiden deres</ProfileLink>.",
   "components.RequestModal.QuotaDisplay.quotaLink": "Du kan se en oppsummering av dine forespørselbegrensninger på <ProfileLink>profilsiden</ProfileLink>.",
   "components.RequestModal.QuotaDisplay.notenoughseasonrequests": "Ikke nok gjenværende sesongforespørsler",
-  "components.Settings.csrfProtectionTip": "Sett ekstern API-tilgang til skrivebeskyttet modus (krever HTTPS og en omstart av Overseer for at endringen skal tre i kraft)",
-  "components.Settings.csrfProtectionHoverTip": "Ikke aktiver dette med mindre du vet hva du gjør!",
+  "components.Settings.csrfProtectionTip": "Sett ekstern API-tilgang til skrivebeskyttet modus (krever HTTPS)",
+  "components.Settings.csrfProtectionHoverTip": "Ikke aktiver denne instillingen med mindre du vet hva du gjør!",
   "components.Settings.csrfProtection": "Aktiver CSRF-beskyttelse",
   "components.Settings.cacheImages": "Aktiver mellomlagring av bilder",
   "components.Settings.region": "Utforskelsesregion",
@@ -576,15 +571,13 @@
   "components.UserProfile.totalrequests": "Totalt antall forespørsler",
   "components.UserProfile.requestsperdays": "{limit} gjenstår",
   "components.UserProfile.recentrequests": "Nylig Forespurt",
-  "components.UserProfile.norequests": "Ingen forespørsler.",
   "components.Settings.noDefaultServer": "Minst én {serverType} server må være definert som standard for at {mediaType}-forespørsler skal kunne bli håndtert.",
   "components.RequestModal.pendingapproval": "Forespørselen din avventer godkjenning.",
-  "components.RequestList.RequestItem.mediaerror": "TIttelen som var knyttet til denne forespørselen er ikke lenger tilgjengelig.",
+  "components.RequestList.RequestItem.mediaerror": "{mediaType} Finnes ikke",
   "components.RequestCard.deleterequest": "Slett forespørsel",
   "components.RequestList.RequestItem.deleterequest": "Slett forespørsel",
-  "components.RequestList.RequestItem.cancelRequest": "Avbryt forespørsel",
-  "components.RequestCard.mediaerror": "Tittelen som var knyttet til denne forespørselen er ikke lenger tilgjengelig.",
-  "components.Discover.noRequests": "Ingen forespørsler.",
+  "components.RequestList.RequestItem.cancelRequest": "Avbryt Forespørsel",
+  "components.RequestCard.mediaerror": "{mediaType} Finnes ikke",
   "components.Settings.SettingsAbout.betawarning": "Dette er beta-programvare. Funksjoner kan slutte og fungerer og/eller være ustabile. Reporter gjerne problemer på GitHub!",
   "components.Settings.noDefaultNon4kServer": "Dersom du har én {serverType} server for både ikke-4K og 4K-media (eller hvis du kun laster ned 4K-innhold), skal {serverType} server <strong>IKKE</strong> være huket av som en 4K server.",
   "components.Settings.noDefault4kServer": "En 4K {serverType} server må være satt som standard for at brukere skal kunne forspørre 4K {mediaType}.",
@@ -622,10 +615,10 @@
   "components.PermissionEdit.requestTv": "Forespør Serier",
   "components.PermissionEdit.requestMoviesDescription": "Gi tilgang til å forespørre filmer som ikke er i 4K.",
   "components.PermissionEdit.requestMovies": "Forespør Filmer",
-  "components.NotificationTypeSelector.usermediarequestedDescription": "Bli varslet når andre brukere forespør medie hvor forespørselen krever godkjenning.",
+  "components.NotificationTypeSelector.usermediarequestedDescription": "Bli varslet når andre brukere forespør nytt matriale hvor forespørselen krever godkjenning.",
   "components.NotificationTypeSelector.usermediafailedDescription": "Bli varslet når dine forespørsler ikke kan bli lagt til Radarr eller Sonarr.",
   "components.NotificationTypeSelector.usermediadeclinedDescription": "Bli varslet når dine forespørsler blir avvist.",
-  "components.NotificationTypeSelector.usermediaAutoApprovedDescription": "Bli varslet når andre brukere forespør medie og forespørselen er automatisk godkjent.",
+  "components.NotificationTypeSelector.usermediaAutoApprovedDescription": "Bli varslet når andre brukere forespør nytt matriale og forespørselen er automagisk godkjent.",
   "components.NotificationTypeSelector.usermediaapprovedDescription": "Bli varslet når dine forespørsler blir godkjent.",
   "components.NotificationTypeSelector.usermediaavailableDescription": "Bli varslet når dine forespørsler blir tilgjengelig.",
   "components.NotificationTypeSelector.notificationTypes": "Varselstyper",
@@ -655,9 +648,9 @@
   "components.IssueDetails.closeissueandcomment": "Lukk med Kommentar",
   "components.IssueModal.issueOther": "Annet",
   "components.ManageSlideOver.manageModalRequests": "Forespørsler",
-  "components.ManageSlideOver.manageModalTitle": "Adminstrer {mediaType}",
+  "components.ManageSlideOver.manageModalTitle": "Administrer {mediaType}",
   "components.ManageSlideOver.mark4kavailable": "Marker som Tilgjengelig i 4K",
-  "components.ManageSlideOver.openarr": "Åpne i {arr}",
+  "components.ManageSlideOver.openarr": "Vis i {arr}",
   "components.MovieDetails.streamingproviders": "Tilgjengelig på",
   "components.NotificationTypeSelector.adminissuereopenedDescription": "Bli varslet når avvik blir gjenåpnet av andre brukere.",
   "components.NotificationTypeSelector.adminissueresolvedDescription": "Bli varslet når avvik blir utbedret av andre brukere.",
@@ -684,7 +677,7 @@
   "components.IssueModal.issueSubtitles": "Undertekster",
   "components.Layout.Sidebar.issues": "Avvik",
   "components.ManageSlideOver.downloadstatus": "Nedlastningsstatus",
-  "components.ManageSlideOver.manageModalClearMedia": "Fjern all Medieinfo",
+  "components.ManageSlideOver.manageModalClearMedia": "Fjern all Info",
   "components.ManageSlideOver.manageModalIssues": "Åpne et Avvik",
   "components.ManageSlideOver.manageModalNoRequests": "Ingen forespørsler.",
   "components.ManageSlideOver.markavailable": "Marker som Tilgjengelig",
@@ -727,7 +720,6 @@
   "components.NotificationTypeSelector.userissuecreatedDescription": "Bli varslet når andre brukere rapporterer avvik.",
   "components.PermissionEdit.createissuesDescription": "Gi tillatelse til å rapportere avvik.",
   "components.RequestModal.requestmovies4k": "Forespør {count} {count, plural, one {Film} other {Filmer}} i 4K",
-  "components.StatusChacker.reloadOverseerr": "Last på nytt",
   "components.UserList.email": "E-postadresse",
   "components.UserList.validationpasswordminchars": "Passordet er for kort; det må bestå av minimum 8 tegn",
   "i18n.status": "Status",
@@ -761,8 +753,7 @@
   "components.Settings.Notifications.NotificationsGotify.validationTokenRequired": "Du må oppgi en applikasjon/API-nøkkel",
   "i18n.next": "Neste",
   "components.Settings.SettingsJobsCache.editJobSchedule": "Endre Oppgave",
-  "components.Settings.SettingsJobsCache.editJobSchedulePrompt": "Frekvens",
-  "components.StatusChacker.newversionavailable": "Programvare-oppdatering",
+  "components.Settings.SettingsJobsCache.editJobSchedulePrompt": "Ny Frekvens",
   "components.TvDetails.firstAirDate": "Første gang sendt",
   "i18n.deleting": "Sletter…",
   "components.UserProfile.UserSettings.UserNotificationSettings.emailsettingssaved": "Innstillingene for E-post ble lagret!",
@@ -782,7 +773,7 @@
   "components.Settings.validationPortRequired": "Du må oppgi et gyldig port-nummer",
   "components.PermissionEdit.manageissuesDescription": "Gi tillatelse til å administre avvik.",
   "i18n.retrying": "Prøver på nytt…",
-  "components.Settings.RadarrModal.enableSearch": "Aktiver Automatisk Søk",
+  "components.Settings.RadarrModal.enableSearch": "Aktiver Automagisk Søk",
   "components.Settings.Notifications.validationPgpPrivateKey": "Du må oppgi en gyldig PGP-privatnøkkel",
   "components.Settings.SettingsJobsCache.cachekeys": "Totalt antall nøkkler",
   "components.MovieDetails.productioncountries": "Produksjonsland",
@@ -805,7 +796,6 @@
   "components.IssueModal.CreateIssueModal.episode": "Episode {episodeNumber}",
   "components.IssueModal.CreateIssueModal.problemepisode": "Gjelder Episode",
   "components.IssueModal.CreateIssueModal.extras": "Tillegg",
-  "components.IssueModal.CreateIssueModal.issomethingwrong": "Hva er problemet med {title}?",
   "components.IssueList.sortAdded": "Nylig Lagt til",
   "components.IssueModal.CreateIssueModal.problemseason": "Gjelder Sesong",
   "components.IssueModal.CreateIssueModal.providedetail": "Vennligst gi en forklaring av problemet som oppsto, gjerne så detaljert som mulig.",
@@ -864,8 +854,8 @@
   "components.Settings.SettingsJobsCache.jobScheduleEditSaved": "Oppgaven ble endret!",
   "components.Settings.SettingsJobsCache.editJobScheduleSelectorHours": "Hver {jobScheduleHours}. time",
   "components.Settings.SettingsJobsCache.editJobScheduleSelectorMinutes": "Hvert {jobScheduleMinutes}. minutt",
-  "components.Settings.SettingsUsers.localLoginTip": "Tillater brukere å kunne logge inn med kun deres E-postadresse og passord istedenfor med Plex OAuth",
-  "components.Settings.SettingsUsers.newPlexLoginTip": "Tillater Plex brukere å logge inn uten å være importert på forhånd",
+  "components.Settings.SettingsUsers.localLoginTip": "Tilllat brukere å logge på med kun E-postadresse og passord istedenfor med Plex OAuth",
+  "components.Settings.SettingsUsers.newPlexLoginTip": "Tillat Plex brukere å logge inn uten å være importert på forhånd",
   "components.Settings.SonarrModal.validationApplicationUrl": "Du må oppgi en gyldig nettadresse",
   "components.Settings.SonarrModal.validationBaseUrlTrailingSlash": "Base URL kan ikke slutte med en skråstrek",
   "components.Settings.locale": "Visningsspråk",
@@ -879,14 +869,13 @@
   "components.TvDetails.productioncountries": "Produksjonsland",
   "components.TvDetails.seasons": "{seasonCount, plural, one {# Sesong} other {# Sesonger}}",
   "components.TvDetails.originaltitle": "Originaltittel",
-  "components.StatusChacker.newversionDescription": "Overseerr har blitt oppdatert! Vennligst trykk på knappen under for å laste siden på nytt.",
   "components.TvDetails.anime": "Animasjon",
   "components.TvDetails.play4konplex": "Spill av i 4K med Plex",
   "components.UserList.localuser": "Lokal bruker",
   "components.UserList.password": "Passord",
   "components.UserList.nouserstoimport": "Det er ingen brukere å importere fra Plex.",
   "components.UserList.userdeleteerror": "Noe gikk galt under sletting av brukeren.",
-  "components.UserList.passwordinfodescription": "Sett opp en nettadresse for Overseerr og aktiver E-postvarsler for å kunne sende ut automatiske genererte passord.",
+  "components.UserList.passwordinfodescription": "Sett opp en nettadresse for Overseerr og aktiver E-postvarsler for å kunne sende ut automagisk genererte passord.",
   "components.UserList.usercreatedfailedexisting": "Denne E-postadressen er allerede i bruk av en annen bruker.",
   "components.UserProfile.UserSettings.UserNotificationSettings.discordsettingsfailed": "Kunne ikke lagre instillingene for Discord.",
   "components.UserProfile.UserSettings.UserNotificationSettings.email": "E-post",
@@ -942,10 +931,10 @@
   "components.UserProfile.UserSettings.UserNotificationSettings.telegramsettingsfailed": "Kunne ikke lagre instillingene for Telegram.",
   "components.UserProfile.UserSettings.UserNotificationSettings.telegramChatId": "Chat ID",
   "components.Settings.SettingsUsers.newPlexLogin": "Aktiver \"Plex Sign-In\" for nye brukere",
-  "components.Settings.SonarrModal.enableSearch": "Aktiver Automatisk Søk",
+  "components.Settings.SonarrModal.enableSearch": "Aktiver Automagisk Søk",
   "components.Settings.notificationAgentSettingsDescription": "Konfigurer og aktiver varslingstjenester.",
   "components.UserList.displayName": "Visningsnavn",
-  "components.UserList.autogeneratepasswordTip": "Send et automatisk generet passord til bruken på E-post",
+  "components.UserList.autogeneratepasswordTip": "Send et automagisk generet passord til bruken på E-post",
   "components.UserList.usercreatedsuccess": "Bruker opprettet!",
   "components.UserList.userdeleted": "Bruker slettet!",
   "components.UserList.validationEmail": "Du må oppgi en gyldig E-postadresse",
@@ -989,13 +978,13 @@
   "components.Settings.Notifications.toastEmailTestSuccess": "Test-varsel ble sendt med E-post!",
   "components.Settings.Notifications.toastTelegramTestFailed": "Telegram mislykkes med å sende test-varsel.",
   "components.Settings.SettingsJobsCache.jobScheduleEditFailed": "Noe gikk galt under lagring av oppgaven.",
-  "components.Settings.cacheImagesTip": "Optimaliser alle bilder og lagre de lokalt på serveren (Dette kommer til å ta veldig mye plass på harddisken)",
+  "components.Settings.cacheImagesTip": "Mellomlagrer og serverer optimaliserte bilder (Dette tar veldig mye diskplass)",
   "components.UserProfile.UserSettings.UserPasswordChange.noPasswordSetOwnAccount": "Din konto har ikke noe passord på nåværende tidspunkt. Lag et passord under for å kunne logge inn med din E-postadresse som \"lokal-bruker\".",
   "components.UserProfile.UserSettings.UserPasswordChange.toastSettingsFailureVerifyCurrent": "Noe gikk galt under lagring av passordet. Var ditt nåværende passord skrevet korrekt?",
   "components.Settings.Notifications.NotificationsWebhook.resetPayloadSuccess": "JSON payload tilbakestilt!",
   "components.Settings.Notifications.NotificationsPushover.userTokenTip": "Din 30-tegns <UsersGroupsLink>bruker- eller gruppe-nøkkel</UsersGroupsLink>",
   "components.Settings.SettingsJobsCache.cachevsize": "Verdistørrelse",
-  "components.Settings.trustProxyTip": "Tillatt Overseerr å registrere klienters IP addresser korrekt bak en proxy (Overseerr må startes på nytt før endringene trer i kraft)",
+  "components.Settings.trustProxyTip": "Tillatt Overseerr å registrere klienters IP addresser korrekt bak en proxy",
   "components.Settings.serviceSettingsDescription": "Konfigurer dine {serverType}tjener(e) nedenfor. Du kan koble til flere forskellige {serverType}tjenere men kun to av dem kan markeres som standard (en som ikke er 4K og en 4K). Administratorer kan endre hvilken tjener som brukes før godkjennelse av nye forespørsler.",
   "components.ManageSlideOver.manageModalClearMediaWarning": "* Dette vil slette all data for denne tittelen uten mulighet for å bli gjennopprettet, det inkluderer alle forespørsler, avvik osv. Hvis denne tittelen finnes i ditt Plex bibliotek vil medieinformasjon bli opprettet på nytt under neste skanning.",
   "components.Settings.Notifications.NotificationsWebhook.authheader": "Autorisasjonshode",
@@ -1040,5 +1029,93 @@
   "components.UserProfile.UserSettings.UserGeneralSettings.discordId": "Discord Bruker ID",
   "components.UserProfile.UserSettings.UserGeneralSettings.validationDiscordId": "Du må oppgi en gyldig Bruker ID for Discord",
   "components.UserProfile.UserSettings.UserGeneralSettings.discordIdTip": "<FindDiscordIdLink>ID-nummeret</FindDiscordIdLink> til din brukerkonto",
-  "components.Settings.SettingsAbout.appDataPath": "Datakatalog"
+  "components.Settings.SettingsAbout.appDataPath": "Datakatalog",
+  "components.RequestBlock.languageprofile": "Språkprofil",
+  "components.MovieDetails.digitalrelease": "Digital utgivelse",
+  "components.MovieDetails.physicalrelease": "Fysisk Utgivelse",
+  "components.MovieDetails.theatricalrelease": "Kinopremiere",
+  "components.StatusChecker.appUpdated": "{applicationTitle} Oppdatert",
+  "components.PermissionEdit.viewrecent": "Vis nylig lag til",
+  "components.PermissionEdit.viewrecentDescription": "Gi tillatelse til å vise nylig lagt til.",
+  "components.Settings.deleteServer": "Slett {serverType} tjener",
+  "components.RequestCard.tmdbid": "TMDB ID",
+  "components.RequestCard.tvdbid": "TheTVDB ID",
+  "components.StatusChecker.appUpdatedDescription": "Vennligst klikk her for å laste applikasjonen på nytt.",
+  "components.Discover.DiscoverWatchlist.discoverwatchlist": "Din Plex Watchlist",
+  "components.Discover.plexwatchlist": "Din Plex Watchlist",
+  "components.NotificationTypeSelector.mediaautorequestedDescription": "Bli varslet når nytt matriale fra diin Plex Watchlist blir automagisk forespurt.",
+  "components.PermissionEdit.autorequestSeries": "Forespør Serier Automagisk",
+  "components.PermissionEdit.autorequestMoviesDescription": "Gi tilgang til å automagisk sende film forespørsler som ikke er i 4K via Plex Watchlist.",
+  "components.PermissionEdit.autorequest": "Auto-Forespørsel",
+  "components.PermissionEdit.autorequestDescription": "Gi tilgang til å automagisk sende forespørsler som ikke er i 4K via Plex Watchlist.",
+  "components.PermissionEdit.autorequestMovies": "Forespør Serier Automagisk",
+  "components.Discover.DiscoverWatchlist.watchlist": "Plex Watchlist",
+  "components.MovieDetails.managemovie": "Administrer Film",
+  "components.MovieDetails.reportissue": "Rapporter Avvik",
+  "components.NotificationTypeSelector.mediaautorequested": "Forespørsel Automagisk Forespurt",
+  "components.PermissionEdit.autorequestSeriesDescription": "Gi tilgang til å automagisk sende serie forespørsler som ikke er i 4K via Plex Watchlist.",
+  "components.Settings.SettingsLogs.viewdetails": "Vis Detaljer",
+  "components.AirDateBadge.airedrelative": "Sendt {relativeTime}",
+  "components.AirDateBadge.airsrelative": "Sendes {relativeTime}",
+  "components.MovieDetails.rtaudiencescore": "Publikumspoeng for Rotten Tomatoes",
+  "components.PermissionEdit.viewwatchlists": "Vis Plex Watchlist",
+  "components.PermissionEdit.viewwatchlistsDescription": "Gi tilgang til å vise andre brukere sin Plex Watchlist.",
+  "components.RequestBlock.requestdate": "Tidspunkt for Forespørsel",
+  "components.RequestBlock.requestedby": "Forespurt av",
+  "components.RequestCard.approverequest": "Godkjenn Forespørsel",
+  "components.RequestCard.cancelrequest": "Avbryt Forespørsel",
+  "components.RequestCard.declinerequest": "Avvis Forespørsel",
+  "components.RequestCard.editrequest": "Rediger forespørsel",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.movierequests": "Filmforespørsler",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.seriesrequests": "Serieforespørsler",
+  "components.Layout.UserDropdown.requests": "Forespørsler",
+  "components.MovieDetails.tmdbuserscore": "Brukerpoeng for TMDb",
+  "components.MovieDetails.rtcriticsscore": "Tomatometer for Rotten Tomatoes",
+  "components.RequestBlock.edit": "Rediger forespørsel",
+  "components.RequestBlock.lastmodifiedby": "Sist endret av",
+  "components.RequestBlock.approve": "Godkjenn Forespørsel",
+  "components.RequestBlock.delete": "Slett forespørsel",
+  "components.RequestBlock.decline": "Avvis Forespørsel",
+  "components.TitleCard.mediaerror": "{mediaType} Finnes ikke",
+  "components.RequestList.RequestItem.tmdbid": "TMDb ID",
+  "i18n.restartRequired": "Omstart Nødvendig",
+  "components.TitleCard.cleardata": "Fjern all Info",
+  "components.TitleCard.tmdbid": "TMDb ID",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmovies": "Forespør Filmer Automagisk",
+  "components.Settings.SettingsJobsCache.plex-watchlist-sync": "Synkronisering av Plex-Watchlist",
+  "components.Settings.restartrequiredTooltip": "Overseerr må startes på nytt for at de nye innstillingene skal tre i kraft",
+  "components.TvDetails.reportissue": "Rapporter Avvik",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseriestip": "Automagisk forespør serier som ligger på <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink>",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseries": "Forespør Serier Automagisk",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmoviestip": "Automagisk forespør filmer som ligger på <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink>",
+  "components.UserProfile.plexwatchlist": "Plex Watchlist",
+  "components.RequestList.RequestItem.tvdbid": "TheTVDb ID",
+  "components.StatusChecker.restartRequiredDescription": "Start tjeneren på nytt for å ta i bruk de nye innstillingene.",
+  "components.StatusChecker.restartRequired": "Omstart av tjener nødvendig",
+  "components.TitleCard.tvdbid": "TheTVDb ID",
+  "components.Settings.experimentalTooltip": "Aktivering av denne innstillingen kan føre til uventet oppførsel av programmet",
+  "components.Settings.advancedTooltip": "Feil konfigurering av denne innstillingen kan føre til defekt funksjonalitet",
+  "components.TvDetails.Season.somethingwentwrong": "Noe gikk galt under henting av data for denne sesongen.",
+  "components.StatusChecker.reloadApp": "Last inn {applicationTitle} på nytt",
+  "components.StatusBadge.playonplex": "Spill av med Plex",
+  "components.StatusBadge.openinarr": "Vis i {arr}",
+  "components.StatusBadge.managemedia": "Administrer {mediaType}",
+  "components.TvDetails.episodeCount": "{episodeCount, plural, one {# Episode} other {# Episoder}}",
+  "components.TvDetails.rtcriticsscore": "Tomatometer for Rotten Tomatoes",
+  "components.TvDetails.manageseries": "Administrer Serie",
+  "components.TvDetails.rtaudiencescore": "Publikumspoeng for Rotten Tomatoes",
+  "components.TvDetails.seasonstitle": "Sesonger",
+  "components.TvDetails.seasonnumber": "Sesong {seasonNumber}",
+  "components.RequestModal.requestseriestitle": "Forespør Serier",
+  "components.TvDetails.status4k": "4K {status}",
+  "components.TvDetails.tmdbuserscore": "Brukerpoeng for TMDb",
+  "components.RequestModal.requestseries4ktitle": "Forespør Serier i 4K",
+  "components.RequestModal.requestmovietitle": "Forespør Film",
+  "components.RequestModal.requestcollection4ktitle": "Forespør hele samlingen i 4K",
+  "components.RequestModal.requestmovie4ktitle": "Forespør Film i 4K",
+  "components.RequestModal.requestcollectiontitle": "Forespør hele samlingen",
+  "components.Discover.emptywatchlist": "Matriale som du legger til via <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink> vil dukke opp her.",
+  "components.UserProfile.emptywatchlist": "Matriale som du legger til via <PlexWatchlistSupportLink>Plex Watchlist</PlexWatchlistSupportLink> vil dukke opp her.",
+  "components.RequestModal.SearchByNameModal.nomatches": "Vi klarte ikke å koble denne serien med et søkbart treff.",
+  "components.Settings.SettingsJobsCache.editJobScheduleCurrent": "Nåværende frekvens"
 }
diff --git a/src/i18n/locale/nl.json b/src/i18n/locale/nl.json
index 982bf7a5..de695af0 100644
--- a/src/i18n/locale/nl.json
+++ b/src/i18n/locale/nl.json
@@ -33,13 +33,12 @@
   "components.RequestModal.cancel": "Verzoek annuleren",
   "components.RequestModal.extras": "Extra's",
   "components.RequestModal.numberofepisodes": "Aantal afleveringen",
-  "components.RequestModal.pendingrequest": "Verzoek voor {title} in behandeling",
+  "components.RequestModal.pendingrequest": "Verzoek in behandeling",
   "components.RequestModal.requestCancel": "Verzoek voor <strong>{title}</strong> is geannuleerd.",
   "components.RequestModal.requestSuccess": "<strong>{title}</strong> is succesvol aangevraagd!",
   "components.RequestModal.requestadmin": "Dit verzoek zal automatisch goedgekeurd worden.",
   "components.RequestModal.requestfrom": "Het verzoek van {user} is in behandeling.",
   "components.RequestModal.requestseasons": "{seasonCount} {seasonCount, plural, one {seizoen} other {seizoenen}} aanvragen",
-  "components.RequestModal.requesttitle": "{title} aanvragen",
   "components.RequestModal.season": "Seizoen",
   "components.RequestModal.seasonnumber": "Seizoen {number}",
   "components.RequestModal.selectseason": "Seizoen(en) selecteren",
@@ -223,9 +222,6 @@
   "components.TvDetails.network": "{networkCount, plural, one {Netwerk} other {Netwerken}}",
   "components.TvDetails.firstAirDate": "Datum eerste uitzending",
   "components.TvDetails.anime": "Anime",
-  "components.StatusChacker.reloadOverseerr": "Herladen",
-  "components.StatusChacker.newversionavailable": "Toepassingsupdate",
-  "components.StatusChacker.newversionDescription": "Overseerr is geüpdatet! Klik op de onderstaande knop om de pagina opnieuw te laden.",
   "components.Settings.toastSettingsSuccess": "Instellingen succesvol opgeslagen!",
   "components.Settings.toastSettingsFailure": "Er ging iets mis bij het opslaan van de instellingen.",
   "components.Settings.toastApiKeySuccess": "Nieuwe API-sleutel succesvol gegenereerd!",
@@ -291,8 +287,7 @@
   "components.Settings.Notifications.NotificationsWebhook.customJson": "JSON-payload",
   "components.Settings.Notifications.NotificationsWebhook.authheader": "Autorisatie-header",
   "components.Settings.Notifications.NotificationsWebhook.agentenabled": "Agent inschakelen",
-  "components.RequestModal.request4ktitle": "{title} in 4K aanvragen",
-  "components.RequestModal.pending4krequest": "4K-verzoek voor {title} in behandeling",
+  "components.RequestModal.pending4krequest": "4K-verzoek in behandeling",
   "components.RequestButton.viewrequest4k": "4K-verzoek bekijken",
   "components.RequestButton.viewrequest": "Verzoek bekijken",
   "components.RequestButton.requestmore": "Meer aanvragen",
@@ -338,8 +333,7 @@
   "i18n.experimental": "Experimenteel",
   "components.Settings.hideAvailable": "Beschikbare media verbergen",
   "components.RequestModal.requesterror": "Er ging iets mis bij het aanvragen.",
-  "components.RequestModal.SearchByNameModal.notvdbiddescription": "We konden je verzoek niet automatisch matchen. Selecteer de juiste match uit de onderstaande lijst.",
-  "components.RequestModal.SearchByNameModal.nosummary": "Er is geen samenvatting voor deze titel gevonden.",
+  "components.RequestModal.SearchByNameModal.notvdbiddescription": "We kunnen deze serie niet automatisch matchen. Selecteer hieronder de juiste match.",
   "components.Login.signinwithplex": "Plex-account gebruiken",
   "components.Login.signinheader": "Log in om verder te gaan",
   "components.Login.signingin": "Bezig met inloggen…",
@@ -364,12 +358,10 @@
   "components.Settings.serverpreset": "Server",
   "components.Settings.serverRemote": "extern",
   "components.Settings.serverLocal": "lokaal",
-  "components.Settings.csrfProtectionTip": "Externe API-toegang instellen op alleen-lezen (vereist HTTPS en Overseerr moet opnieuw worden geladen om wijzigingen door te voeren)",
+  "components.Settings.csrfProtectionTip": "Externe API-toegang instellen op alleen-lezen (vereist HTTPS)",
   "components.Settings.csrfProtection": "CSRF-bescherming inschakelen",
   "components.PermissionEdit.usersDescription": "Toestemming geven om gebruikers te beheren. Gebruikers met deze toestemming kunnen gebruikers met beheerdersrechten niet wijzigen of die rechten verlenen.",
   "components.PermissionEdit.users": "Gebruikers beheren",
-  "components.PermissionEdit.settingsDescription": "Toestemming geven om algemene instellingen te wijzigen. Een gebruiker heeft deze machtiging nodig om ze aan anderen te verlenen.",
-  "components.PermissionEdit.settings": "Instellingen beheren",
   "components.PermissionEdit.requestDescription": "Toestemming geven om niet-4K-media aan te vragen.",
   "components.PermissionEdit.request4kTvDescription": "Toestemming geven om series in 4K aan te vragen.",
   "components.PermissionEdit.request4kTv": "4K-series aanvragen",
@@ -400,7 +392,7 @@
   "components.MovieDetails.play4konplex": "Afspelen in 4K op Plex",
   "components.MovieDetails.mark4kavailable": "Als beschikbaar in 4K markeren",
   "components.MovieDetails.markavailable": "Als beschikbaar markeren",
-  "components.Settings.trustProxyTip": "Overseerr toestaan om IP-adressen van clients correct te registreren achter een proxy (Overseerr moet opnieuw worden geladen om de wijzigingen door te voeren)",
+  "components.Settings.trustProxyTip": "Overseerr toestaan om IP-adressen van clients correct te registreren achter een proxy",
   "components.Settings.trustProxy": "Proxy-ondersteuning inschakelen",
   "components.Settings.SettingsJobsCache.cacheflushed": "{cachename} cache leeggemaakt.",
   "components.Settings.SettingsJobsCache.cache": "Cache",
@@ -588,7 +580,6 @@
   "components.NotificationTypeSelector.mediaAutoApproved": "Verzoek automatisch goedgekeurd",
   "components.UserProfile.UserSettings.unauthorizedDescription": "Je hebt geen toestemming om de instellingen van deze gebruiker te wijzigen.",
   "components.UserProfile.UserSettings.UserPermissions.unauthorizedDescription": "Je kan je eigen machtigingen niet wijzigen.",
-  "components.UserProfile.norequests": "Geen verzoeken.",
   "components.TvDetails.episodeRuntimeMinutes": "{runtime} minuten",
   "components.TvDetails.episodeRuntime": "Afleveringsduur",
   "components.Settings.Notifications.pgpPrivateKeyTip": "Versleutelde e-mailberichten ondertekenen met <OpenPgpLink>OpenPGP</OpenPgpLink>",
@@ -633,7 +624,7 @@
   "components.Settings.SettingsJobsCache.jobsandcache": "Taken en cache",
   "components.Settings.SettingsAbout.about": "Over",
   "components.ResetPassword.passwordreset": "Wachtwoord opnieuw instellen",
-  "components.Settings.cacheImagesTip": "Alle afbeeldingen optimaliseren en lokaal opslaan (gebruikt een aanzienlijke hoeveelheid schijfruimte)",
+  "components.Settings.cacheImagesTip": "Geoptimaliseerde afbeeldingen cachen en hosten (vereist veel schijfruimte)",
   "components.Settings.cacheImages": "Afbeeldingscaching inschakelen",
   "components.Settings.SettingsLogs.logDetails": "Loggegevens",
   "components.Settings.SettingsLogs.extraData": "Aanvullende gegevens",
@@ -714,9 +705,9 @@
   "components.RequestModal.AdvancedRequester.selecttags": "Labels selecteren",
   "components.RequestModal.AdvancedRequester.notagoptions": "Geen labels.",
   "components.Settings.RadarrModal.loadingTags": "Labels laden…",
-  "components.RequestList.RequestItem.mediaerror": "De gekoppelde titel voor dit verzoek is niet meer beschikbaar.",
+  "components.RequestList.RequestItem.mediaerror": "{mediaType} niet gevonden",
   "components.RequestList.RequestItem.deleterequest": "Verzoek verwijderen",
-  "components.RequestCard.mediaerror": "De gekoppelde titel voor dit verzoek is niet meer beschikbaar.",
+  "components.RequestCard.mediaerror": "{mediaType} niet gevonden",
   "components.RequestCard.deleterequest": "Verzoek verwijderen",
   "components.UserProfile.UserSettings.UserNotificationSettings.validationPgpPublicKey": "Je moet een geldige openbare PGP-sleutel opgeven",
   "components.UserProfile.UserSettings.UserNotificationSettings.telegramsettingssaved": "Instellingen Telegrammeldingen succesvol opgeslagen!",
@@ -734,7 +725,6 @@
   "components.RequestModal.pendingapproval": "Je verzoek is in afwachting van goedkeuring.",
   "components.RequestList.RequestItem.cancelRequest": "Verzoek annuleren",
   "components.NotificationTypeSelector.notificationTypes": "Meldingtypes",
-  "components.Discover.noRequests": "Geen verzoeken.",
   "components.UserProfile.UserSettings.UserPasswordChange.noPasswordSetOwnAccount": "Er is voor jouw account momenteel geen wachtwoord ingesteld. Configureer hieronder een wachtwoord om in te kunnen loggen als een \"lokale gebruiker\" met uw e-mailadres.",
   "components.UserProfile.UserSettings.UserPasswordChange.noPasswordSet": "Deze gebruikersaccount heeft momenteel geen wachtwoord ingesteld. Configureer hieronder een wachtwoord zodat deze account in staat is om zich aan te melden als een \"lokale gebruiker\".",
   "components.Settings.serviceSettingsDescription": "Configureer je {serverType} server(s) hieronder. Je kunt meerdere {serverType} servers verbinden, maar slechts twee ervan kunnen als standaard worden gemarkeerd (één niet-4K en één 4K). Beheerders kunnen vóór de goedkeuring de server die gebruikt wordt om nieuwe aanvragen te verwerken aanpassen.",
@@ -857,7 +847,7 @@
   "components.MovieDetails.streamingproviders": "Momenteel te streamen op",
   "components.Settings.SettingsJobsCache.jobScheduleEditSaved": "Taak succesvol bewerkt!",
   "components.Settings.SettingsJobsCache.editJobScheduleSelectorMinutes": "Elk(e) {jobScheduleMinutes, plural, one {minuut} other {{jobScheduleMinutes} minuten}}",
-  "components.Settings.SettingsJobsCache.editJobSchedulePrompt": "Frequentie",
+  "components.Settings.SettingsJobsCache.editJobSchedulePrompt": "Nieuwe frequentie",
   "components.Settings.SettingsJobsCache.jobScheduleEditFailed": "Er ging iets mis bij het opslaan van de taak.",
   "components.Settings.SettingsJobsCache.editJobSchedule": "Taak wijzigen",
   "components.Settings.SettingsJobsCache.editJobScheduleSelectorHours": "Elk(e) {jobScheduleHours, plural, one {uur} other {{jobScheduleHours} uren}}",
@@ -895,7 +885,7 @@
   "components.IssueModal.CreateIssueModal.allepisodes": "Alle afleveringen",
   "components.IssueModal.issueAudio": "Audio",
   "components.IssueDetails.nocomments": "Geen opmerkingen.",
-  "components.IssueModal.CreateIssueModal.reportissue": "Een probleem melden",
+  "components.IssueModal.CreateIssueModal.reportissue": "Probleem melden",
   "components.IssueDetails.allepisodes": "Alle afleveringen",
   "components.IssueDetails.toasteditdescriptionsuccess": "Probleembeschrijving succesvol bewerkt!",
   "components.IssueDetails.toastissuedeleted": "Probleem succesvol verwijderd!",
@@ -935,7 +925,6 @@
   "components.IssueList.IssueItem.unknownissuetype": "Onbekend",
   "components.IssueList.IssueItem.viewissue": "Probleem bekijken",
   "components.IssueList.IssueItem.problemepisode": "Getroffen aflevering",
-  "components.IssueModal.CreateIssueModal.issomethingwrong": "Is er een probleem met {title}?",
   "components.IssueModal.CreateIssueModal.problemepisode": "Getroffen aflevering",
   "components.IssueModal.CreateIssueModal.toastSuccessCreate": "Probleemmelding voor <strong>{title}</strong> succesvol ingediend!",
   "components.PermissionEdit.viewissues": "Problemen weergeven",
@@ -1040,5 +1029,93 @@
   "components.UserProfile.UserSettings.UserGeneralSettings.discordId": "Gebruikers-ID Discord",
   "components.UserProfile.UserSettings.UserGeneralSettings.discordIdTip": "Het <FindDiscordIdLink>meercijferige ID-nummer</FindDiscordIdLink> van je Discord-account",
   "components.UserProfile.UserSettings.UserGeneralSettings.validationDiscordId": "Je moet een geldige gebruikers-ID van Discord opgeven",
-  "components.Settings.SettingsAbout.appDataPath": "Gegevensmap"
+  "components.Settings.SettingsAbout.appDataPath": "Gegevensmap",
+  "components.RequestBlock.languageprofile": "Taalprofiel",
+  "components.Settings.SettingsJobsCache.editJobScheduleCurrent": "Huidige frequentie",
+  "components.StatusBadge.managemedia": "{mediaType} beheren",
+  "components.StatusBadge.openinarr": "Openen in {arr}",
+  "components.StatusBadge.playonplex": "Afspelen op Plex",
+  "components.UserProfile.emptywatchlist": "Media die zijn toegevoegd aan je <PlexWatchlistSupportLink>Plex Kijklijst</PlexWatchlistSupportLink> verschijnen hier.",
+  "components.MovieDetails.digitalrelease": "Digitale release",
+  "i18n.restartRequired": "Opnieuw opstarten vereist",
+  "components.PermissionEdit.viewrecentDescription": "Toestemming geven om de lijst met recent toegevoegde media te bekijken.",
+  "components.PermissionEdit.viewrecent": "Recent toegevoegd bekijken",
+  "components.Settings.deleteServer": "{serverType}-server verwijderen",
+  "components.StatusChecker.appUpdated": "{applicationTitle} bijgewerkt",
+  "components.RequestList.RequestItem.tmdbid": "TMDB ID",
+  "components.RequestList.RequestItem.tvdbid": "TheTVDB ID",
+  "components.StatusChecker.restartRequired": "Server opnieuw opstarten vereist",
+  "components.StatusChecker.restartRequiredDescription": "Start de server opnieuw op om de bijgewerkte instellingen toe te passen.",
+  "components.TitleCard.cleardata": "Gegevens wissen",
+  "components.TitleCard.mediaerror": "{mediatype} niet gevonden",
+  "components.TitleCard.tvdbid": "TheTVDB ID",
+  "components.RequestCard.tmdbid": "TMDB ID",
+  "components.RequestCard.declinerequest": "Verzoek weigeren",
+  "components.RequestCard.editrequest": "Verzoek bewerken",
+  "components.RequestCard.cancelrequest": "Verzoek annuleren",
+  "components.RequestModal.requestcollection4ktitle": "Collectie aanvragen in 4K",
+  "components.RequestModal.requestcollectiontitle": "Collectie aanvragen",
+  "components.RequestModal.requestseries4ktitle": "Serie aanvragen in 4K",
+  "components.RequestModal.requestmovie4ktitle": "Film aanvragen in 4K",
+  "components.RequestModal.requestseriestitle": "Serie aanvragen",
+  "components.RequestModal.requestmovietitle": "Film aanvragen",
+  "components.TvDetails.tmdbuserscore": "Gebruikersscore TMDB",
+  "components.TvDetails.rtaudiencescore": "Publieksscore Rotten Tomatoes",
+  "components.TvDetails.seasonnumber": "Seizoen {seasonNumber}",
+  "components.TvDetails.Season.somethingwentwrong": "Er ging iets mis bij het ophalen van de seizoensgegevens.",
+  "components.TvDetails.seasonstitle": "Seizoenen",
+  "components.Discover.DiscoverWatchlist.discoverwatchlist": "Je Plex Kijklijst",
+  "components.Discover.plexwatchlist": "Je Plex Kijklijst",
+  "components.MovieDetails.physicalrelease": "Fysieke release",
+  "components.PermissionEdit.autorequest": "Automatisch aanvragen",
+  "components.Settings.SettingsJobsCache.plex-watchlist-sync": "Plex Kijklijst synchroniseren",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseries": "Series automatisch aanvragen",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseriestip": "Automatisch series op je <PlexWatchlistSupportLink>Plex Kijklijst</PlexWatchlistSupportLink> aanvragen",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmoviestip": "Automatisch films op je <PlexWatchlistSupportLink>Plex Kijklijst</PlexWatchlistSupportLink> aanvragen",
+  "components.PermissionEdit.autorequestDescription": "Toestemming geven om niet-4K media in je Plex Kijklijst automatisch aan te vragen.",
+  "components.RequestCard.tvdbid": "TheTVDB ID",
+  "components.Discover.DiscoverWatchlist.watchlist": "Plex Kijklijst",
+  "components.MovieDetails.theatricalrelease": "Bioscooprelease",
+  "components.NotificationTypeSelector.mediaautorequested": "Aanvraag automatisch ingediend",
+  "components.NotificationTypeSelector.mediaautorequestedDescription": "Ontvang een melding wanneer er automatisch nieuwe mediaverzoeken worden ingediend voor items op je Plex Kijklijst.",
+  "components.PermissionEdit.autorequestSeriesDescription": "Toestemming geven om niet-4K series in je Plex Kijklijst automatisch aan te vragen.",
+  "components.PermissionEdit.viewwatchlists": "Plex Kijklijsten bekijken",
+  "components.PermissionEdit.viewwatchlistsDescription": "Toestemming verlenen om de Plex Kijklijsten van andere gebruikers te bekijken.",
+  "components.Settings.SettingsLogs.viewdetails": "Details bekijken",
+  "components.Settings.advancedTooltip": "Deze instelling onjuist configureren, kan resulteren in gebroken functionaliteit",
+  "components.StatusChecker.reloadApp": "{applicationTitle} opnieuw laden",
+  "components.TitleCard.tmdbid": "TMDB ID",
+  "components.StatusChecker.appUpdatedDescription": "Klik op de onderstaande knop om de toepassing opnieuw te laden.",
+  "components.UserProfile.plexwatchlist": "Plex Kijklijst",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmovies": "Films automatisch aanvragen",
+  "components.TvDetails.manageseries": "Serie beheren",
+  "components.MovieDetails.managemovie": "Film beheren",
+  "components.MovieDetails.reportissue": "Probleem melden",
+  "components.PermissionEdit.autorequestMoviesDescription": "Toestemming geven om niet-4K films in je Plex Kijklijst automatisch aan te vragen.",
+  "components.PermissionEdit.autorequestSeries": "Series automatisch aanvragen",
+  "components.PermissionEdit.autorequestMovies": "Films automatisch aanvragen",
+  "components.Settings.experimentalTooltip": "Deze instelling inschakelen, kan leiden tot onverwacht gedrag van de toepassing",
+  "components.Settings.restartrequiredTooltip": "Overseerr moet opnieuw worden gestart om wijzigingen in deze instelling door te voeren",
+  "components.AirDateBadge.airedrelative": "{relativeTime} uitgezonden",
+  "components.AirDateBadge.airsrelative": "Uitzending {relativeTime}",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.seriesrequests": "Serieverzoeken",
+  "components.TvDetails.episodeCount": "{episodeCount, plural, one {# aflevering} other {# afleveringen}}",
+  "components.TvDetails.status4k": "4K {status}",
+  "components.MovieDetails.rtaudiencescore": "Publieksscore Rotten Tomatoes",
+  "components.MovieDetails.rtcriticsscore": "Tomatometer Rotten Tomatoes",
+  "components.MovieDetails.tmdbuserscore": "Gebruikersscore TMDB",
+  "components.RequestBlock.approve": "Verzoek goedkeuren",
+  "components.TvDetails.reportissue": "Probleem melden",
+  "components.TvDetails.rtcriticsscore": "Tomatometer Rotten Tomatoes",
+  "components.RequestModal.SearchByNameModal.nomatches": "We konden geen match vinden voor deze serie.",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.movierequests": "Filmverzoeken",
+  "components.Layout.UserDropdown.requests": "Verzoeken",
+  "components.RequestBlock.decline": "Verzoek weigeren",
+  "components.Discover.emptywatchlist": "Media die zijn toegevoegd aan je <PlexWatchlistSupportLink>Plex Kijklijst</PlexWatchlistSupportLink> verschijnen hier.",
+  "components.RequestBlock.delete": "Verzoek verwijderen",
+  "components.RequestBlock.edit": "Verzoek bewerken",
+  "components.RequestBlock.lastmodifiedby": "Laatst gewijzigd door",
+  "components.RequestBlock.requestdate": "Aanvraagdatum",
+  "components.RequestBlock.requestedby": "Aangevraagd door",
+  "components.RequestCard.approverequest": "Verzoek goedkeuren"
 }
diff --git a/src/i18n/locale/pl.json b/src/i18n/locale/pl.json
index 0a6bd3db..1488ce33 100644
--- a/src/i18n/locale/pl.json
+++ b/src/i18n/locale/pl.json
@@ -108,14 +108,12 @@
   "components.IssueModal.CreateIssueModal.whatswrong": "Co jest nie tak?",
   "components.Discover.MovieGenreList.moviegenres": "Gatunki filmowe",
   "components.Discover.TvGenreList.seriesgenres": "Gatunki seriali",
-  "components.Discover.noRequests": "Brak próśb.",
   "components.Discover.recentrequests": "Ostatnie prośby",
   "components.Discover.upcomingmovies": "Nadchodzące filmy",
   "components.IssueModal.CreateIssueModal.reportissue": "Zgłoś problem",
   "components.IssueModal.CreateIssueModal.season": "Sezon {seasonNumber}",
   "components.IssueModal.CreateIssueModal.validationMessageRequired": "Musisz podać opis",
   "components.IssueModal.issueAudio": "Audio",
-  "components.IssueModal.CreateIssueModal.issomethingwrong": "Czy wystąpił problem z {title}?",
   "components.IssueDetails.reopenissueandcomment": "Otwórz ponownie z komentarzem",
   "components.IssueModal.issueOther": "Inny",
   "components.CollectionDetails.numberofmovies": "{count} Filmy",
@@ -176,7 +174,6 @@
   "components.PermissionEdit.autoapproveMovies": "Automatyczne zatwierdzanie filmów",
   "components.PermissionEdit.autoapproveMoviesDescription": "Przyznaj automatyczne zatwierdzanie próśb o filmy inne niż 4K.",
   "components.PermissionEdit.requestTvDescription": "Udziel pozwolenia na przesyłanie próśb o seriale inne niż 4K.",
-  "components.PermissionEdit.settings": "Zarządzaj ustawieniami",
   "components.PersonDetails.appearsin": "Wystąpienia",
   "components.PersonDetails.alsoknownas": "Znany również jako: {names}",
   "components.PlexLoginButton.signingin": "Logowanie…",
@@ -225,7 +222,6 @@
   "components.RequestModal.AdvancedRequester.tags": "Tagi",
   "components.RequestModal.QuotaDisplay.movie": "film",
   "components.PermissionEdit.viewrequests": "Wyświetl prośby",
-  "components.PermissionEdit.settingsDescription": "Przyznaj uprawnienia do modyfikowania ustawień globalnych. Użytkownik musi mieć to uprawnienie, aby przyznać je innym.",
   "components.PermissionEdit.users": "Zarządzanie użytkownikami",
   "components.PermissionEdit.viewissues": "Wyświetl problemy",
   "components.PersonDetails.birthdate": "Urodzony {birthdate}",
@@ -344,7 +340,6 @@
   "components.RequestModal.requestadmin": "Ta prośba zostanie zatwierdzona automatycznie.",
   "components.ResetPassword.passwordreset": "Resetowanie hasła",
   "components.Settings.Notifications.NotificationsPushbullet.toastPushbulletTestSuccess": "Powiadomienie testowe Pushbullet wysłane!",
-  "components.RequestModal.requesttitle": "Prośba o {title}",
   "components.ResetPassword.confirmpassword": "Potwierdź hasło",
   "components.ResetPassword.email": "Adres e-mail",
   "components.ResetPassword.password": "Hasło",
@@ -454,7 +449,6 @@
   "components.RequestModal.QuotaDisplay.notenoughseasonrequests": "Brak wystarczającej liczby próśb o sezon",
   "components.RequestModal.QuotaDisplay.requiredquotaUser": "Aby przesłać prośbę o ten serial, ten użytkownik musi mieć co najmniej <strong>{seasons}</strong> {seasons, plural, one {prośbę} other {prośby}}.",
   "components.RequestModal.QuotaDisplay.seasonlimit": "{limit, plural, one {sezon} other {sezony}}",
-  "components.RequestModal.SearchByNameModal.nosummary": "Nie znaleziono żadnych informacji o tym tytule.",
   "components.RequestModal.SearchByNameModal.notvdbiddescription": "Nie mogliśmy automatycznie spełnić Twojej prośby. Wybierz odpowiednie dopasowanie z poniższej listy.",
   "components.RequestModal.alreadyrequested": "Już poproszono",
   "components.RequestModal.autoapproval": "Automatyczne zatwierdzenie",
@@ -462,10 +456,9 @@
   "components.RequestModal.errorediting": "Coś poszło nie tak podczas edytowania prośby.",
   "components.RequestModal.extras": "Dodatki",
   "components.RequestModal.numberofepisodes": "Liczba odcinków",
-  "components.RequestModal.pending4krequest": "Oczekująca prośba o 4K dla {title}",
+  "components.RequestModal.pending4krequest": "Oczekująca prośba o 4K",
   "components.RequestModal.pendingapproval": "Twoja prośba oczekuje na zatwierdzenie.",
-  "components.RequestModal.pendingrequest": "Oczekująca prośba o {title}",
-  "components.RequestModal.request4ktitle": "Poproś o {title} w 4K",
+  "components.RequestModal.pendingrequest": "Oczekująca prośba",
   "components.RequestModal.requestCancel": "Prośba o <strong>{title}</strong> została anulowana.",
   "components.RequestModal.requestedited": "Prośba o <strong>{title}</strong> została pomyślnie edytowana!",
   "components.RequestModal.requesterror": "Coś poszło nie tak podczas przesyłania prośby.",
@@ -691,7 +684,6 @@
   "components.Setup.tip": "Wskazówka",
   "components.Setup.welcome": "Witamy w Overseerr",
   "components.StatusBadge.status4k": "4K {status}",
-  "components.StatusChacker.newversionDescription": "Overseerr został zaktualizowany! Kliknij przycisk poniżej, aby ponownie załadować stronę.",
   "components.TvDetails.anime": "Anime",
   "components.TvDetails.nextAirDate": "Następna data emisji",
   "components.UserList.bulkedit": "Masowa edycja",
@@ -767,8 +759,6 @@
   "components.Setup.configureplex": "Skonfiguruj Plex",
   "components.Setup.configureservices": "Skonfiguruj usługi",
   "components.Setup.continue": "Kontynuuj",
-  "components.StatusChacker.newversionavailable": "Aktualizacja aplikacji",
-  "components.StatusChacker.reloadOverseerr": "Odśwież",
   "components.TvDetails.TvCast.fullseriescast": "Pełna obsada serialu",
   "components.TvDetails.TvCrew.fullseriescrew": "Pełna ekipa serialu",
   "components.TvDetails.episodeRuntime": "Czas trwania odcinka",
@@ -860,7 +850,6 @@
   "components.UserProfile.UserSettings.menuPermissions": "Uprawnienia",
   "components.UserProfile.UserSettings.unauthorizedDescription": "Nie masz uprawnień do modyfikowania ustawień tego użytkownika.",
   "components.UserProfile.limit": "{remaining} z {limit}",
-  "components.UserProfile.norequests": "Brak próśb.",
   "components.UserProfile.pastdays": "{type} (ostatnie {days} dni)",
   "components.UserProfile.requestsperdays": "Pozostało {limit}",
   "components.UserProfile.seriesrequest": "Prośby o seriale",
@@ -913,7 +902,7 @@
   "components.Settings.SonarrModal.animerootfolder": "Folder główny anime",
   "components.Settings.SonarrModal.selectQualityProfile": "Wybierz profil jakości",
   "components.Settings.SonarrModal.selecttags": "Wybierz tagi",
-  "components.Settings.csrfProtectionTip": "Ustaw zewnętrzny dostęp api na tylko do odczytu (wymaga HTTPS, a Overseerr musi zostać ponownie załadowany, aby zmiany zostały wprowadzone)",
+  "components.Settings.csrfProtectionTip": "Ustaw zewnętrzny dostęp api na tylko do odczytu (wymaga HTTPS)",
   "components.Settings.toastPlexRefreshFailure": "Nie udało się pobrać listy serwerów Plex.",
   "components.Settings.SonarrModal.apiKey": "Klucz API",
   "components.Settings.cancelscan": "Anuluj skanowanie",
@@ -934,7 +923,7 @@
   "components.Settings.partialRequestsEnabled": "Zezwalaj na prośby o część serialu",
   "components.Settings.sonarrsettings": "Ustawienia Sonarr",
   "components.Settings.ssl": "Protokół SSL",
-  "components.Settings.trustProxyTip": "Pozwól Overseerr poprawnie rejestrować adresy IP klientów za serwerem proxy (Overseerr musi zostać ponownie załadowany, aby zmiany zostały wprowadzone)",
+  "components.Settings.trustProxyTip": "Pozwól Overseerr poprawnie rejestrować adresy IP klientów za serwerem proxy",
   "components.Settings.toastPlexConnectingSuccess": "Połączenie Plex nawiązane pomyślnie!",
   "components.Settings.toastSettingsSuccess": "Ustawienia zostały zapisane pomyślnie!",
   "components.Settings.serviceSettingsDescription": "Skonfiguruj poniżej swój serwer(y) {serverType}. Możesz podłączyć wiele serwerów {serverType}, ale tylko dwa z nich mogą być oznaczone jako domyślne (jeden nie-4K i jeden 4K). Administratorzy mogą zmienić serwer używany do przetwarzania nowych żądań przed zatwierdzeniem.",
@@ -1040,5 +1029,36 @@
   "components.UserProfile.UserSettings.UserGeneralSettings.discordId": "ID użytkownika Discorda",
   "components.UserProfile.UserSettings.UserGeneralSettings.discordIdTip": "<FindDiscordIdLink>Wielocyfrowy numer ID</FindDiscordIdLink> powiązany z Twoim kontem użytkownika Discord",
   "components.UserProfile.UserSettings.UserGeneralSettings.validationDiscordId": "Musisz podać poprawne ID użytkownika Discord",
-  "components.Settings.SettingsAbout.appDataPath": "Katalog danych"
+  "components.Settings.SettingsAbout.appDataPath": "Katalog danych",
+  "components.StatusChecker.restartRequiredDescription": "Uruchom ponownie serwer, aby zastosować zaktualizowane ustawienia.",
+  "components.StatusChecker.appUpdated": "Zaktualizowano {applicationTitle}",
+  "components.Settings.deleteServer": "Usuń serwer {serverType}",
+  "components.StatusChecker.appUpdatedDescription": "Kliknij przycisk poniżej, aby ponownie załadować aplikację.",
+  "components.StatusChecker.reloadApp": "Odśwież {applicationTitle}",
+  "i18n.restartRequired": "Wymagane jest ponowne uruchomienie",
+  "components.RequestBlock.languageprofile": "Profil językowy",
+  "components.StatusChecker.restartRequired": "Wymagane ponowne uruchomienie serwera",
+  "components.MovieDetails.digitalrelease": "Wydanie cyfrowe",
+  "components.MovieDetails.physicalrelease": "Wydanie fizyczne",
+  "components.MovieDetails.theatricalrelease": "Wydanie kinowe",
+  "components.Discover.DiscoverWatchlist.discoverwatchlist": "Twoja lista obserwowanych Plex",
+  "components.Discover.plexwatchlist": "Twoja lista obserwowanych Plex",
+  "components.PermissionEdit.autorequest": "Automatyczna prośba",
+  "components.PermissionEdit.autorequestDescription": "Udziel zgody na automatyczne przesyłanie próśb dotyczących multimediów innych niż 4K za pośrednictwem listy obserwowanych Plex.",
+  "components.NotificationTypeSelector.mediaautorequested": "Prośba przesłana automatycznie",
+  "components.NotificationTypeSelector.mediaautorequestedDescription": "Otrzymuj powiadomienia o automatycznym składaniu nowych próśb o multimedia dla pozycji znajdujących się na liście obserwowanych Plex.",
+  "components.PermissionEdit.autorequestMovies": "Filmy z próśb automatycznych",
+  "components.Discover.DiscoverWatchlist.watchlist": "Lista obserwowanych Plex",
+  "components.MovieDetails.managemovie": "Zarządzaj filmem",
+  "components.MovieDetails.reportissue": "Zgłoś problem",
+  "components.PermissionEdit.autorequestMoviesDescription": "Udziel zgody na automatyczne przesyłanie próśb dotyczących multimediów innych niż 4K za pośrednictwem listy obserwowanych Plex.",
+  "components.PermissionEdit.autorequestSeries": "Automatyczna prośba o serial",
+  "components.AirDateBadge.airedrelative": "Wyemitowany {relativeTime}",
+  "components.AirDateBadge.airsrelative": "Data emisji {relativeTime}",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.movierequests": "Prośby o filmy",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.seriesrequests": "Prośby o seriale",
+  "components.Layout.UserDropdown.requests": "Prośby",
+  "components.MovieDetails.rtaudiencescore": "Ocena Rotten Tomatoes",
+  "components.MovieDetails.rtcriticsscore": "Tomatometer Rotten Tomatoes",
+  "components.MovieDetails.tmdbuserscore": "Ocena użytkowników TMDB"
 }
diff --git a/src/i18n/locale/pt_BR.json b/src/i18n/locale/pt_BR.json
index eb6b698d..58aaf208 100644
--- a/src/i18n/locale/pt_BR.json
+++ b/src/i18n/locale/pt_BR.json
@@ -141,12 +141,11 @@
   "components.Search.searchresults": "Resultados da Pesquisa",
   "components.RequestModal.selectseason": "Selecione Temporada(s)",
   "components.RequestModal.seasonnumber": "Temporada {number}",
-  "components.RequestModal.requesttitle": "Solicitar {title}",
   "components.RequestModal.requestfrom": "Existe uma solicitação pendente de {username}.",
   "components.RequestModal.requestadmin": "Essa solicitação será aprovada automaticamente.",
   "components.RequestModal.requestSuccess": "<strong>{title}</strong> solicitado com sucesso!",
   "components.RequestModal.requestCancel": "Solicitação para <strong>{title}</strong> cancelada.",
-  "components.RequestModal.pendingrequest": "Solicitação Pendente para {title}",
+  "components.RequestModal.pendingrequest": "Solicitação Pendente",
   "components.RequestModal.numberofepisodes": "# de Episódeos",
   "components.RequestModal.extras": "Extras",
   "components.RequestModal.cancel": "Cancelar Solicitação",
@@ -216,7 +215,7 @@
   "components.UserList.role": "Privilégio",
   "components.UserList.plexuser": "Usuário Plex",
   "components.UserList.deleteuser": "Deletar Usuário",
-  "components.UserList.deleteconfirm": "Tem certeza que deseja deletar esse usuário? Todas informações de solicitações feitas por esse usuário serão permanentemente removidas.",
+  "components.UserList.deleteconfirm": "Tem certeza que deseja apagar esse usuário? Todas informações de solicitações feitas por esse usuário serão permanentemente removidas.",
   "components.UserList.created": "Criado",
   "components.UserList.admin": "Administrador",
   "components.TvDetails.similar": "Séries Semelhantes",
@@ -235,7 +234,7 @@
   "components.MovieDetails.watchtrailer": "Assistir Trailer",
   "components.CollectionDetails.requestcollection": "Solicitar Coleção",
   "components.CollectionDetails.overview": "Sinopse",
-  "components.CollectionDetails.numberofmovies": "Filmes: {count}",
+  "components.CollectionDetails.numberofmovies": "{count} Filmes",
   "i18n.requested": "Solicitado",
   "i18n.retry": "Tentar Novamente",
   "i18n.failed": "Falhou",
@@ -252,9 +251,6 @@
   "components.Settings.Notifications.NotificationsSlack.webhookUrl": "URL de Webhook",
   "components.Settings.Notifications.NotificationsSlack.slacksettingssaved": "Configurações de notificação via Slack salvas com sucesso!",
   "components.Settings.Notifications.NotificationsSlack.slacksettingsfailed": "Falha ao salvar configurações de notificação via Slack.",
-  "components.StatusChacker.reloadOverseerr": "Recarregar",
-  "components.StatusChacker.newversionDescription": "Overseer foi atualizado! Por favor clique no botão abaixo para recarregar a página.",
-  "components.StatusChacker.newversionavailable": "Atualização da Aplicação",
   "components.Settings.SettingsAbout.documentation": "Documentação",
   "components.NotificationTypeSelector.mediarequestedDescription": "Envia notificações quando outros usuários solicitarem novas mídias que requerem aprovação.",
   "components.NotificationTypeSelector.mediaavailable": "Solicitação Disponível",
@@ -276,8 +272,7 @@
   "components.RequestList.sortAdded": "Mais Recente",
   "components.RequestList.showallrequests": "Exibir Todas Solicitações",
   "components.StatusBadge.status4k": "4K {status}",
-  "components.RequestModal.request4ktitle": "Solicitar {title} em 4K",
-  "components.RequestModal.pending4krequest": "Solicitação em 4K Pendente para {title}",
+  "components.RequestModal.pending4krequest": "Solicitação em 4K Pendente",
   "components.Settings.Notifications.NotificationsWebhook.webhooksettingssaved": "Configurações de notificação via Webhook salvas com sucesso!",
   "components.Settings.Notifications.NotificationsWebhook.webhooksettingsfailed": "Falha ao salvar configurações de notificação via Webhook.",
   "components.Settings.Notifications.NotificationsWebhook.webhookUrl": "URL de Webhook",
@@ -339,7 +334,6 @@
   "components.Settings.hideAvailable": "Ocultar Títulos Disponíveis",
   "components.RequestModal.requesterror": "Algo deu errado ao solicitar mídia.",
   "components.RequestModal.SearchByNameModal.notvdbiddescription": "Não conseguimos correlacionar sua solicitação automaticamente. Por favor selecione a correspondência correta na lista abaixo.",
-  "components.RequestModal.SearchByNameModal.nosummary": "Sinopse não encontrada para esse título.",
   "components.Login.signin": "Entrar",
   "components.UserList.userssaved": "Permissões de usuário salvas com sucesso!",
   "components.UserList.bulkedit": "Edição Em Massa",
@@ -357,15 +351,13 @@
   "components.Settings.serverRemote": "remoto",
   "components.Settings.serverLocal": "local",
   "components.Settings.notificationAgentSettingsDescription": "Configure e habilite agentes de notificação.",
-  "components.Settings.csrfProtectionTip": "Define acesso externo à API como apenas leitura (Requer HTTPS e é necessário reiniciar Overseerr para mudança ter efeito)",
+  "components.Settings.csrfProtectionTip": "Define acesso externo à API como apenas leitura (Requer HTTPS)",
   "components.Settings.csrfProtection": "Habilitar Proteção Contra CSRF",
   "components.PlexLoginButton.signinwithplex": "Entrar",
   "components.Login.signingin": "Autenticando…",
   "components.PlexLoginButton.signingin": "Autenticando…",
   "components.PermissionEdit.usersDescription": "Concede permissão para gerenciar usuários. Usuários com essa permissão não podem modificar usuários com acesso Administrativo, ou condecer tal permissão.",
   "components.PermissionEdit.users": "Gerenciar Usuários",
-  "components.PermissionEdit.settingsDescription": "Concede permissão para modificar configurações globais. O usuário precisar ter essa permissão para concedê-la a outros.",
-  "components.PermissionEdit.settings": "Gerenciar Configurações",
   "components.PermissionEdit.requestDescription": "Concede permissão para solicitar mídia não 4K.",
   "components.PermissionEdit.request4kTvDescription": "Concede permissão para solicitar séries em 4K.",
   "components.PermissionEdit.request4kTv": "Solicitar Séries em 4K",
@@ -401,7 +393,7 @@
   "components.MovieDetails.markavailable": "Marcar como Disponível",
   "components.MovieDetails.mark4kavailable": "Marcar como Disponível em 4K",
   "components.Settings.trustProxy": "Habilitar Suporte a Proxy",
-  "components.Settings.trustProxyTip": "Permite que Overseerr exiba o IP correto do cliente atrás de um proxy (Overseerr precisa ser reiniciado para que as mudanças tenham efeito)",
+  "components.Settings.trustProxyTip": "Permite que Overseerr exiba o IP correto do cliente atrás de um proxy",
   "components.Settings.SettingsJobsCache.cacheflushed": "Cache {cachename} limpo.",
   "components.Settings.SettingsJobsCache.cache": "Cache",
   "components.Settings.SettingsJobsCache.cachevsize": "Tamanho do Valor",
@@ -575,7 +567,6 @@
   "components.Settings.SettingsJobsCache.radarr-scan": "Escanemento do Radarr",
   "components.Settings.SettingsJobsCache.plex-recently-added-scan": "Recentemente Adicionado ao Plex",
   "components.Settings.SettingsJobsCache.plex-full-scan": "Escaneamento de Todas Bibliotecas do Plex",
-  "components.UserProfile.norequests": "Nenhuma solicitação.",
   "components.UserProfile.UserSettings.unauthorizedDescription": "Você não tem permissão para modificar as configurações desse usuários.",
   "components.UserProfile.UserSettings.UserPermissions.unauthorizedDescription": "Você não pode modificar suas próprias permissões.",
   "components.UserProfile.ProfileHeader.userid": "ID de Usuário: {userid}",
@@ -606,7 +597,7 @@
   "components.ResetPassword.passwordreset": "Redefinir Senha",
   "components.Settings.SettingsLogs.logDetails": "Detalhes do Log",
   "components.UserProfile.UserSettings.UserPasswordChange.toastSettingsFailureVerifyCurrent": "Algo deu errado ao salvar sua senha. Sua senha foi digitada corretamente?",
-  "components.Settings.cacheImagesTip": "Otimiza e armazena todas imagens localmente (consume um espaço significante do disco)",
+  "components.Settings.cacheImagesTip": "Armazena em cache e distribui imagens otimizadas (requer um espaço significante no disco)",
   "pages.somethingwentwrong": "Algo deu errado",
   "pages.serviceunavailable": "Serviço Indisponível",
   "pages.pagenotfound": "Página Não Encontrada",
@@ -737,17 +728,16 @@
   "components.Settings.Notifications.validationPgpPassword": "Você deve prover uma senha PGP",
   "components.Settings.Notifications.botUsernameTip": "Permitir que usuários iniciem uma conversa com o seu bot e configure suas próprias notificações",
   "components.RequestModal.pendingapproval": "Sua solicitação está aguardando aprovação.",
-  "components.RequestList.RequestItem.mediaerror": "O título associado à essa solicitação não está mais disponível.",
+  "components.RequestList.RequestItem.mediaerror": "{mediaType} Não Encontrado",
   "components.RequestList.RequestItem.deleterequest": "Apagar Solicitação",
   "components.RequestList.RequestItem.cancelRequest": "Cancelar Solicitação",
-  "components.RequestCard.mediaerror": "O título associado à essa solicitação não está mais disponível.",
+  "components.RequestCard.mediaerror": "{mediaType} Não Encontrado",
   "components.RequestCard.deleterequest": "Apagar Solicitação",
   "components.NotificationTypeSelector.notificationTypes": "Tipos de Notificação",
   "components.Layout.VersionStatus.streamstable": "Overseerr Estável",
   "components.Layout.VersionStatus.streamdevelop": "Overseerr Desenv.",
   "components.Layout.VersionStatus.outofdate": "Desatualizado",
   "components.Layout.VersionStatus.commitsbehind": "{commitsBehind} {commitsBehind, plural, one {versão} other {versões}} atrasado(a)",
-  "components.Discover.noRequests": "Nenhuma solicitação.",
   "components.UserList.autogeneratepasswordTip": "Envia para o usuário uma senha gerada automaticamente",
   "i18n.retrying": "Tentando Novamente…",
   "components.UserList.usercreatedfailedexisting": "O e-mail informado já está em uso por outro usuário.",
@@ -908,7 +898,6 @@
   "components.IssueDetails.toaststatusupdatefailed": "Algo deu errado ao atualizar o estado do problema.",
   "components.IssueDetails.unknownissuetype": "Desconhecido",
   "components.IssueList.issues": "Problemas",
-  "components.IssueModal.CreateIssueModal.issomethingwrong": "Algum problema com {title}?",
   "components.IssueModal.CreateIssueModal.problemepisode": "Episódio Afetado",
   "components.IssueModal.CreateIssueModal.problemseason": "Temporada Afetada",
   "components.IssueList.IssueItem.problemepisode": "Episódio Afetado",
@@ -1040,5 +1029,79 @@
   "components.ManageSlideOver.alltime": "Desde Início",
   "components.ManageSlideOver.playedby": "Reproduzido por",
   "components.Settings.Notifications.NotificationsPushbullet.channelTag": "Tag do Canal",
-  "components.Settings.SettingsAbout.appDataPath": "Configurações"
+  "components.Settings.SettingsAbout.appDataPath": "Configurações",
+  "components.RequestBlock.languageprofile": "Perfil de Idioma",
+  "components.StatusChecker.appUpdated": "{applicationTitle} Atualizado",
+  "components.StatusChecker.restartRequiredDescription": "Por favor, reinicie o servidor para aplicar as novas configurações.",
+  "i18n.restartRequired": "Reinicialização Necessária",
+  "components.StatusChecker.reloadApp": "Recarregar {applicationTitle}",
+  "components.StatusChecker.restartRequired": "Reinicialização do Servidor Necessária",
+  "components.StatusChecker.appUpdatedDescription": "Por favor, clique no botão abaixo para recarregar a aplicação.",
+  "components.Settings.deleteServer": "Remover Servidor {serverType}",
+  "components.MovieDetails.digitalrelease": "Lançamento Digital",
+  "components.MovieDetails.physicalrelease": "Lançamento em Disco",
+  "components.MovieDetails.theatricalrelease": "Lançamento no Cinema",
+  "components.PermissionEdit.viewrecent": "Ver Recentemente Adicionados",
+  "components.PermissionEdit.viewrecentDescription": "Concede permissão para ver lista de mídias adicionadas recentemente.",
+  "components.RequestCard.tmdbid": "ID do TMDB",
+  "components.RequestCard.tvdbid": "ID do TheTVDB",
+  "components.RequestList.RequestItem.tmdbid": "ID do TMDB",
+  "components.RequestList.RequestItem.tvdbid": "ID do TheTVDB",
+  "components.TitleCard.mediaerror": "{mediaType} Não Encontrado",
+  "components.TitleCard.tmdbid": "ID do TMDB",
+  "components.TitleCard.tvdbid": "ID do TheTVDB",
+  "components.TitleCard.cleardata": "Limpar Dados",
+  "components.PermissionEdit.autorequest": "Solicitar Automaticamente",
+  "components.PermissionEdit.autorequestMovies": "Solicitar Filmes Automaticamente",
+  "components.PermissionEdit.autorequestSeries": "Solicitar Séries Automaticamente",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmovies": "Solicitar Filmes Automaticamente",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseries": "Solicitar Séries Automaticamente",
+  "components.Discover.DiscoverWatchlist.discoverwatchlist": "Sua Lista para Assistir do Plex",
+  "components.Discover.plexwatchlist": "Sua Lista para Assistir do Plex",
+  "components.Discover.DiscoverWatchlist.watchlist": "Lista para Assistir do Plex",
+  "components.AirDateBadge.airedrelative": "Exibido em {relativeTime}",
+  "components.AirDateBadge.airsrelative": "Exibindo {relativeTime}",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.movierequests": "Pedidos de Filmes",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.seriesrequests": "Pedidos de Séries",
+  "components.Layout.UserDropdown.requests": "Pedidos",
+  "components.MovieDetails.managemovie": "Gerenciar Filme",
+  "components.NotificationTypeSelector.mediaautorequestedDescription": "Ser notificado quando um novo pedido de mídia de algum item da sua Lista para assistir no Plex for automaticamente enviado.",
+  "components.NotificationTypeSelector.mediaautorequested": "Pedido automaticamente enviado",
+  "components.PermissionEdit.autorequestDescription": "Dar permissão para enviar automaticamente pedidos para mídias não-4K via Lista para assistir do Plex.",
+  "components.PermissionEdit.autorequestMoviesDescription": "Dar permissão para enviar automaticamente pedidos para filmes não-4K via Lista para assistir do Plex.",
+  "components.PermissionEdit.autorequestSeriesDescription": "Dar permissão para enviar automaticamente pedidos para séries não-4K via Lista para assistir do Plex.",
+  "components.PermissionEdit.viewwatchlists": "Ver Lista para assistir do Plex",
+  "components.PermissionEdit.viewwatchlistsDescription": "Dar permissão para ver a Lista para assistir do Plex de outros usuários.",
+  "components.Settings.SettingsJobsCache.plex-watchlist-sync": "Sincronizar Lista para assistir do Plex",
+  "components.Settings.SettingsLogs.viewdetails": "Ver Detalhes",
+  "components.Settings.advancedTooltip": "Configurar incorretamente esta opção pode resultar em uma funcionalidade quebrada",
+  "components.Settings.restartrequiredTooltip": "Overseerr deve ser reiniciado para as mudanças tomarem efeito",
+  "components.Settings.experimentalTooltip": "Habilitar essa opção pode resultar em um comportamento não esperado da aplicação",
+  "components.TvDetails.reportissue": "Reportar um Problema",
+  "components.MovieDetails.reportissue": "Reportar um problema",
+  "components.StatusBadge.managemedia": "Gerenciar {mediaType}",
+  "components.StatusBadge.openinarr": "Abrir em {arr}",
+  "components.TvDetails.Season.somethingwentwrong": "Algo deu errado enquanto os dados da temporada eram adquiridos.",
+  "components.TvDetails.manageseries": "Gerenciar Séries",
+  "components.TvDetails.rtcriticsscore": "Pontuação de audiência no Rotten Tomatoes",
+  "components.TvDetails.seasonnumber": "Temporada {seasonNumber}",
+  "components.TvDetails.seasonstitle": "Temporadas",
+  "components.TvDetails.rtaudiencescore": "Pontuação de audiência no Rotten Tomatoes",
+  "components.TvDetails.status4k": "4K {status}",
+  "components.TvDetails.tmdbuserscore": "Pontuação de Usuário do TMDB",
+  "components.MovieDetails.tmdbuserscore": "Pontuação de usuário do TMDB",
+  "components.MovieDetails.rtaudiencescore": "Pontuação de audiência no Rotten Tomatoes",
+  "components.MovieDetails.rtcriticsscore": "Tomatômetro do Rotten Tomatoes",
+  "components.RequestBlock.edit": "Editar Pedido",
+  "components.RequestCard.approverequest": "Aprovar pedido",
+  "components.RequestBlock.approve": "Aprovar pedido",
+  "components.RequestBlock.requestdate": "Data do pedido",
+  "components.RequestCard.declinerequest": "Rejeitar Pedido",
+  "components.RequestCard.editrequest": "Editar Pedido",
+  "components.StatusBadge.playonplex": "Reproduzir no Plex",
+  "components.RequestBlock.decline": "Rejeitar pedido",
+  "components.RequestBlock.lastmodifiedby": "Última modificação por",
+  "components.RequestBlock.delete": "Deletar pedido",
+  "components.RequestBlock.requestedby": "Pedido por",
+  "components.RequestCard.cancelrequest": "Cancelar pedido"
 }
diff --git a/src/i18n/locale/pt_PT.json b/src/i18n/locale/pt_PT.json
index 9ae007bd..ba83cdd8 100644
--- a/src/i18n/locale/pt_PT.json
+++ b/src/i18n/locale/pt_PT.json
@@ -71,7 +71,6 @@
   "components.RequestModal.selectseason": "Selecionar Semporada(s)",
   "components.RequestModal.seasonnumber": "Temporada {number}",
   "components.RequestModal.season": "Temporada",
-  "components.RequestModal.requesttitle": "Pedir {title}",
   "components.RequestModal.requestseasons": "Pedir {seasonCount} {seasonCount, plural, one {Temporada} other {Temporadas}}",
   "components.RequestModal.requestfrom": "O peido de {username} está com aprovação pendente.",
   "components.RequestModal.requestedited": "Pedido para <strong>{title}</strong> modificado com sucesso!",
@@ -79,9 +78,8 @@
   "components.RequestModal.requestadmin": "Este pedido será aprovado automaticamente.",
   "components.RequestModal.requestSuccess": "<strong>{title}</strong> pedido com sucesso!",
   "components.RequestModal.requestCancel": "Pedido para <strong>{title}</strong> cancelado.",
-  "components.RequestModal.request4ktitle": "Pedir {title} em 4K",
-  "components.RequestModal.pendingrequest": "Pedido pendente para {title}",
-  "components.RequestModal.pending4krequest": "Pedido 4K pendente para {title}",
+  "components.RequestModal.pendingrequest": "Pedido pendente",
+  "components.RequestModal.pending4krequest": "Pedido 4K pendente",
   "components.RequestModal.numberofepisodes": "# de Episódios",
   "components.RequestModal.extras": "Extras",
   "components.RequestModal.errorediting": "Ocorreu um erro durante a edição do pedido.",
@@ -333,14 +331,10 @@
   "components.TvDetails.anime": "Anime",
   "components.TvDetails.TvCrew.fullseriescrew": "Equipa Técnica Completa da Série",
   "components.TvDetails.TvCast.fullseriescast": "Elenco Completo da Série",
-  "components.StatusChacker.reloadOverseerr": "Recarregar",
-  "components.StatusChacker.newversionavailable": "Atualização de Aplicação",
-  "components.StatusChacker.newversionDescription": "Overseerr foi atualizado! Clique no botão abaixo para recarregar a página.",
   "components.StatusBadge.status4k": "4K {status}",
   "components.Login.signinwithplex": "Iniciar sessão com a sua conta Plex",
   "components.RequestModal.requesterror": "Ocorreu um erro ao submeter o pedido.",
   "components.RequestModal.SearchByNameModal.notvdbiddescription": "Não foi possível associar seu pedido automaticamente. Por favor selecione a correspondência correta a partir da lista abaixo.",
-  "components.RequestModal.SearchByNameModal.nosummary": "Sinopse não encontrada para este título.",
   "components.Login.signinheader": "Iniciar sessão para continuar",
   "components.Login.signingin": "A Iniciar Sessão…",
   "components.Login.signin": "Iniciar Sessão",
@@ -362,12 +356,10 @@
   "components.Settings.serverpreset": "Servidor",
   "components.Settings.serverRemote": "remoto",
   "components.Settings.serverLocal": "local",
-  "components.Settings.csrfProtectionTip": "Definir o acesso externo API para somente leitura (requer HTTPS, e Overseerr deve ser recarregado para que as alterações tenham efeito)",
+  "components.Settings.csrfProtectionTip": "Definir o acesso externo API para somente leitura (requer HTTPS)",
   "components.Settings.csrfProtection": "Ativar Proteção CSRF",
   "components.PermissionEdit.usersDescription": "Conceder permissão para gerir utilizadores Overseerr. Os utilizadores com essa permissão não podem modificar os utilizadores ou conceder o privilégio de administrador.",
   "components.PermissionEdit.users": "Gerir Utilizadores",
-  "components.PermissionEdit.settingsDescription": "Conceder permissão para modificar as definições de Overseerr. Um utilizador deve ter esta permissão para a conceder a outros.",
-  "components.PermissionEdit.settings": "Gerir Definições",
   "components.PermissionEdit.requestDescription": "Conceder permissão para pedir multimédia não 4K.",
   "components.PermissionEdit.request4kTvDescription": "Conceder permissão para pedir séries em 4K.",
   "components.PermissionEdit.request4kTv": "Pedir Séries 4K",
@@ -398,7 +390,7 @@
   "components.TvDetails.play4konplex": "Ver em 4K no Plex",
   "components.MovieDetails.play4konplex": "Ver em 4K no Plex",
   "components.MovieDetails.playonplex": "Ver no Plex",
-  "components.Settings.trustProxyTip": "Permitir que o Overseerr registe corretamente os endereços IP do cliente por trás de um proxy (o Overseerr deve ser recarregado para que as alterações tenham efeito)",
+  "components.Settings.trustProxyTip": "Permitir que o Overseerr registe corretamente os endereços IP do cliente por trás de um proxy",
   "components.Settings.trustProxy": "Ativar Suporte de Proxy",
   "components.MovieDetails.markavailable": "Marcar como Disponível",
   "components.MovieDetails.mark4kavailable": "Marcar como Disponível em 4K",
@@ -588,7 +580,6 @@
   "components.UserProfile.UserSettings.UserPermissions.unauthorizedDescription": "Não pode modificar suas próprias permissões.",
   "components.NotificationTypeSelector.mediaAutoApprovedDescription": "Enviar notificações quando os utilizadores apresentarem novos pedidos de multimédia que são automaticamente aprovados.",
   "components.NotificationTypeSelector.mediaAutoApproved": "Multimédia Aprovada Automaticamente",
-  "components.UserProfile.norequests": "Sem pedidos.",
   "components.TvDetails.episodeRuntimeMinutes": "{runtime} minutos",
   "components.TvDetails.episodeRuntime": "Duração do Episódio",
   "components.Settings.Notifications.pgpPrivateKeyTip": "Assinar mensagens de e-mail encriptadas utilizando <OpenPgpLink>OpenPGP</OpenPgpLink>",
@@ -738,7 +729,6 @@
   "components.UserProfile.UserSettings.UserNotificationSettings.discordsettingssaved": "Definições de notificação Discord gravadas com sucesso!",
   "components.UserProfile.UserSettings.UserNotificationSettings.discordsettingsfailed": "Falha ao gravar as definições de notificação Discord.",
   "components.RequestList.RequestItem.cancelRequest": "Cancelar Pedido",
-  "components.Discover.noRequests": "Sem pedidos.",
   "components.Settings.serviceSettingsDescription": "Configure o seu(s) servidor(es) {serverType} abaixo. Pode ligar vários servidores {serverType}, mas apenas dois deles podem ser marcados como predefinidos (um não 4K e um 4K). Os administradores podem mudar o servidor usado para processar novos pedidos antes da aprovação.",
   "components.Settings.noDefaultServer": "Pelo menos um servidor {serverType} deve ser marcado como predefinido para que os pedidos de {mediaType} sejam processados.",
   "components.Settings.noDefaultNon4kServer": "Se tiver apenas um único servidor {serverType} para conteúdo não 4K e 4K (ou se apenas transfere conteúdo 4K), o seu servidor {serverType} <strong>NÃO</strong> deve ser designado como um servidor 4K.",
diff --git a/src/i18n/locale/ro.json b/src/i18n/locale/ro.json
new file mode 100644
index 00000000..40156c18
--- /dev/null
+++ b/src/i18n/locale/ro.json
@@ -0,0 +1,39 @@
+{
+  "components.Discover.DiscoverStudio.studioMovies": "{studio} Filme",
+  "components.AppDataWarning.dockerVolumeMissingDescription": "Montarea volumului <code>{appDataPath}</code> nu a fost configurată corespunzător. Toate datele vor fi șterse atunci când containerul este oprit sau repornit.",
+  "components.CollectionDetails.numberofmovies": "{count} Filme",
+  "components.CollectionDetails.overview": "Prezentare generală",
+  "components.CollectionDetails.requestcollection": "Cere colecția",
+  "components.CollectionDetails.requestcollection4k": "Cere colecția în 4K",
+  "components.Discover.DiscoverMovieGenre.genreMovies": "{genul} Filme",
+  "components.Discover.DiscoverMovieLanguage.languageMovies": "{Limba} Filme",
+  "components.Discover.DiscoverNetwork.networkSeries": "{network} Seriale",
+  "components.Discover.MovieGenreSlider.moviegenres": "Genuri de film",
+  "components.Discover.NetworkSlider.networks": "Rețele",
+  "components.Discover.TvGenreList.seriesgenres": "Genuri seriale",
+  "components.IssueDetails.IssueDescription.edit": "Editați descrierea",
+  "components.IssueDetails.IssueComment.validationComment": "Trebuie să introduceți un mesaj",
+  "components.IssueDetails.IssueDescription.description": "Descriere",
+  "components.IssueDetails.IssueComment.postedbyedited": "Postat {relativeTime} de {username} (Editat)",
+  "components.Discover.DiscoverTvGenre.genreSeries": "{genre} Seriale",
+  "components.Discover.DiscoverTvLanguage.languageSeries": "{language} Seriale",
+  "components.Discover.MovieGenreList.moviegenres": "Genuri de film",
+  "components.Discover.StudioSlider.studios": "Studiouri",
+  "components.Discover.TvGenreSlider.tvgenres": "Genuri seriale",
+  "components.Discover.discover": "Descoperă",
+  "components.Discover.discovermovies": "Filme populare",
+  "components.Discover.discovertv": "Seriale populare",
+  "components.Discover.popularmovies": "Filme populare",
+  "components.Discover.populartv": "Seriale populare",
+  "components.Discover.recentlyAdded": "Adăugate recent",
+  "components.Discover.recentrequests": "Solicitări recente",
+  "components.Discover.upcoming": "Filme viitoare",
+  "components.Discover.upcomingmovies": "Filme viitoare",
+  "components.Discover.upcomingtv": "Seriale viitoare",
+  "components.DownloadBlock.estimatedtime": "Estimat {time}",
+  "components.IssueDetails.IssueComment.areyousuredelete": "Ești sigur că vrei să ștergi acest comentariu?",
+  "components.IssueDetails.IssueComment.delete": "Șterge comentariul",
+  "components.IssueDetails.IssueComment.edit": "Editează comentariul",
+  "components.IssueDetails.IssueComment.postedby": "Postat {relativeTime} de {username}",
+  "components.IssueDetails.IssueDescription.deleteissue": "Ștergeți problema"
+}
diff --git a/src/i18n/locale/ru.json b/src/i18n/locale/ru.json
index ca387bff..2676327c 100644
--- a/src/i18n/locale/ru.json
+++ b/src/i18n/locale/ru.json
@@ -33,13 +33,12 @@
   "components.RequestModal.cancel": "Отменить запрос",
   "components.RequestModal.extras": "Дополнительно",
   "components.RequestModal.numberofepisodes": "# эпизодов",
-  "components.RequestModal.pendingrequest": "В ожидании запрос на {title}",
+  "components.RequestModal.pendingrequest": "",
   "components.RequestModal.requestCancel": "Запрос на <strong>{title}</strong> отменён.",
   "components.RequestModal.requestSuccess": "<strong>{title}</strong> успешно запрошен!",
   "components.RequestModal.requestadmin": "Этот запрос будет одобрен автоматически.",
   "components.RequestModal.requestfrom": "Запрос пользователя {username} ожидает одобрения.",
   "components.RequestModal.requestseasons": "Запросить {seasonCount} {seasonCount, plural, one {сезон} other {сезона(ов)}}",
-  "components.RequestModal.requesttitle": "Запросить {title}",
   "components.RequestModal.season": "Сезон",
   "components.RequestModal.seasonnumber": "Сезон {number}",
   "components.RequestModal.selectseason": "Выберите сезон(ы)",
@@ -190,7 +189,6 @@
   "components.UserList.create": "Создать",
   "components.TvDetails.network": "{networkCount, plural, one {Телеканал} other {Телеканалы}}",
   "components.TvDetails.anime": "Аниме",
-  "components.StatusChacker.newversionavailable": "Обновить приложение",
   "components.Settings.toastSettingsSuccess": "Настройки успешно сохранены!",
   "components.Settings.serverpresetManualMessage": "Ручная настройка",
   "components.Settings.serverpreset": "Сервер",
@@ -255,7 +253,6 @@
   "components.RegionSelector.regionDefault": "Все регионы",
   "components.PermissionEdit.viewrequests": "Просмотр запросов",
   "components.PermissionEdit.users": "Управление пользователями",
-  "components.PermissionEdit.settings": "Управление настройками",
   "components.PermissionEdit.managerequests": "Управление запросами",
   "components.UserProfile.UserSettings.UserGeneralSettings.admin": "Администратор",
   "components.PermissionEdit.admin": "Администратор",
@@ -287,7 +284,6 @@
   "components.UserList.owner": "Владелец",
   "components.UserProfile.UserSettings.UserGeneralSettings.owner": "Владелец",
   "components.MovieDetails.markavailable": "Пометить как доступный",
-  "components.StatusChacker.reloadOverseerr": "Перезагрузить",
   "components.StatusBadge.status4k": "4K {status}",
   "pages.errormessagewithcode": "{statusCode} - {error}",
   "components.Settings.Notifications.NotificationsPushbullet.accessToken": "Токен доступа",
@@ -409,7 +405,6 @@
   "components.Layout.LanguagePicker.displaylanguage": "Язык интерфейса",
   "components.DownloadBlock.estimatedtime": "Приблизительно {time}",
   "components.Discover.upcomingtv": "Предстоящие сериалы",
-  "components.Discover.noRequests": "Запросов нет.",
   "components.Discover.discover": "Найти что-то новое",
   "components.Discover.TvGenreSlider.tvgenres": "Сериалы по жанрам",
   "components.Discover.TvGenreList.seriesgenres": "Сериалы по жанрам",
@@ -455,7 +450,6 @@
   "components.PersonDetails.birthdate": "Рожден(а) {birthdate}",
   "components.PermissionEdit.viewrequestsDescription": "Предоставить разрешение на просмотр медиа-запросов, отправленных другими пользователями.",
   "components.PermissionEdit.usersDescription": "Предоставить разрешение на управление пользователями. Пользователи с этим разрешением не могут предоставлять права администратора и редактировать пользователей, являющихся администраторами.",
-  "components.PermissionEdit.settingsDescription": "Предоставить разрешение на изменение глобальных настроек. Пользователь должен иметь это разрешение, чтобы предоставить его другим.",
   "components.PermissionEdit.requestTvDescription": "Предоставить разрешение на отправку запросов всех сериалов, отличных от 4К.",
   "components.PermissionEdit.requestTv": "Запросы сериалов",
   "components.PermissionEdit.requestMoviesDescription": "Предоставить разрешение на отправку запросов всех фильмов, отличных от 4К.",
@@ -572,8 +566,7 @@
   "components.TvDetails.seasons": "{seasonCount, plural, one {# сезон} other {# сезонов}}",
   "components.RequestModal.QuotaDisplay.requiredquotaUser": "Этому пользователю необходимо иметь по крайней мере <strong>{seasons}</strong> {seasons, plural, one {запрос на сезоны} other {запроса(ов) на сезоны}} для того, чтобы отправить запрос на этот сериал.",
   "components.RequestModal.QuotaDisplay.requiredquota": "Вам необходимо иметь по крайней мере <strong>{seasons}</strong> {seasons, plural, one {запрос на сезоны} other {запроса(ов) на сезоны}} для того, чтобы отправить запрос на этот сериал.",
-  "components.RequestModal.request4ktitle": "Запросить {title} в 4К",
-  "components.RequestModal.pending4krequest": "В ожидании 4К запрос на {title}",
+  "components.RequestModal.pending4krequest": "",
   "components.RequestModal.autoapproval": "Автоматическое одобрение",
   "i18n.usersettings": "Настройки пользователя",
   "i18n.showingresults": "Показываются результаты с <strong>{from}</strong> по <strong>{to}</strong> из <strong>{total}</strong>",
@@ -583,12 +576,10 @@
   "i18n.requesting": "Запрос…",
   "i18n.request4k": "Запросить в 4К",
   "i18n.areyousure": "Вы уверены?",
-  "components.StatusChacker.newversionDescription": "Overseerr был обновлён! Пожалуйста, нажмите кнопку ниже, чтобы перезагрузить страницу.",
   "components.RequestModal.alreadyrequested": "Уже запрошен",
   "components.RequestModal.SearchByNameModal.notvdbiddescription": "Мы не смогли автоматически выполнить ваш запрос. Пожалуйста, выберите правильное совпадение из списка ниже.",
   "components.TvDetails.originaltitle": "Название оригинала",
   "components.Settings.validationApplicationTitle": "Вы должны указать название приложения",
-  "components.RequestModal.SearchByNameModal.nosummary": "Аннотации для этого названия не найдено.",
   "i18n.tvshow": "Сериал",
   "components.Settings.partialRequestsEnabled": "Разрешить частичные запросы сериалов",
   "components.Settings.mediaTypeSeries": "сериал",
@@ -606,7 +597,7 @@
   "components.TvDetails.showtype": "Тип сериала",
   "components.TvDetails.TvCrew.fullseriescrew": "Полная съёмочная группа сериала",
   "components.TvDetails.TvCast.fullseriescast": "Полный актёрский состав сериала",
-  "components.Settings.trustProxyTip": "Позволяет Overseerr корректно регистрировать IP-адреса клиентов за прокси-сервером (Overseerr необходимо перезагрузить, чтобы изменения вступили в силу)",
+  "components.Settings.trustProxyTip": "Позволяет Overseerr корректно регистрировать IP-адреса клиентов за прокси-сервером",
   "components.Settings.originallanguageTip": "Контент фильтруется по языку оригинала",
   "components.Settings.noDefaultNon4kServer": "Если вы используете один сервер {serverType} для контента, в том числе и для 4К, или если вы загружаете только контент 4K, ваш сервер {serverType} <strong>НЕ</strong> должен быть помечен как 4К сервер.",
   "components.UserList.localLoginDisabled": "Параметр <strong>Включить локальный вход</strong> в настоящее время отключен.",
@@ -626,7 +617,7 @@
   "components.Settings.SonarrModal.enableSearch": "Включить автоматический поиск",
   "components.Settings.SonarrModal.edit4ksonarr": "Редактировать 4К сервер Sonarr",
   "components.Settings.toastApiKeyFailure": "Что-то пошло не так при создании нового ключа API.",
-  "components.Settings.csrfProtectionTip": "Устанавливает доступ к API извне только для чтения (требуется HTTPS, для вступления изменений в силу необходимо перезагрузить Overseerr)",
+  "components.Settings.csrfProtectionTip": "Устанавливает доступ к API извне только для чтения (требуется HTTPS)",
   "components.Settings.SonarrModal.animequalityprofile": "Профиль качества для аниме",
   "components.Settings.SonarrModal.animelanguageprofile": "Языковой профиль для аниме",
   "components.Settings.SonarrModal.animeTags": "Теги для аниме",
@@ -755,7 +746,6 @@
   "components.UserProfile.pastdays": "{type} (за {days} день(ей))",
   "components.UserProfile.seriesrequest": "Запросов сериалов",
   "components.UserProfile.movierequests": "Запросов фильмов",
-  "components.UserProfile.norequests": "Запросов нет.",
   "components.UserProfile.limit": "{remaining} из {limit}",
   "components.UserProfile.UserSettings.unauthorizedDescription": "У вас нет разрешения на изменение настроек этого пользователя.",
   "components.UserProfile.UserSettings.UserPasswordChange.nopermissionDescription": "У вас нет разрешения на изменение пароля этого пользователя.",
@@ -892,7 +882,6 @@
   "components.IssueModal.CreateIssueModal.episode": "Эпизод {episodeNumber}",
   "components.ManageSlideOver.mark4kavailable": "Пометить как доступный в 4К",
   "components.IssueModal.CreateIssueModal.extras": "Дополнительно",
-  "components.IssueModal.CreateIssueModal.issomethingwrong": "Есть проблема с «{title}»?",
   "components.IssueModal.CreateIssueModal.problemseason": "Затронутый сезон",
   "components.ManageSlideOver.downloadstatus": "Загрузки",
   "components.ManageSlideOver.manageModalIssues": "Открытые проблемы",
diff --git a/src/i18n/locale/sq.json b/src/i18n/locale/sq.json
index 17152209..0b0a4c43 100644
--- a/src/i18n/locale/sq.json
+++ b/src/i18n/locale/sq.json
@@ -29,7 +29,6 @@
   "components.IssueModal.CreateIssueModal.allepisodes": "Të gjithë Episodet",
   "components.IssueModal.CreateIssueModal.allseasons": "Të gjithë Sezonet",
   "components.IssueModal.CreateIssueModal.extras": "Ekstrat",
-  "components.IssueModal.CreateIssueModal.issomethingwrong": "A ka ndonjë problem me {title}?",
   "components.Login.loginerror": "Diçka shkoi keq duke u përpjekur të hyja.",
   "components.Login.signinheader": "Identifikohu për të vazhduar",
   "components.MovieDetails.budget": "Buxheti",
@@ -56,7 +55,6 @@
   "components.Discover.discover": "Zbulo",
   "components.Discover.discovermovies": "Filma Popullorë",
   "components.Discover.discovertv": "Seriale Popullore",
-  "components.Discover.noRequests": "Asnjë kërkesë.",
   "components.Discover.popularmovies": "Filma Popullorë",
   "components.Discover.populartv": "Seriale Popullore",
   "components.Discover.recentlyAdded": "Shtuar së Fundmi",
@@ -248,8 +246,6 @@
   "components.PermissionEdit.requestDescription": "Jep leje për të paraqitur kërkesat për media jo-4K.",
   "components.PermissionEdit.requestTv": "Kërko Serialin",
   "components.PermissionEdit.requestTvDescription": "Jep leje për të paraqitur kërkesa për seri jo-4K.",
-  "components.PermissionEdit.settings": "Menaxho Cilësimet",
-  "components.PermissionEdit.settingsDescription": "Jep leje për të modifikuar cilësimet globale. Një përdorues duhet ta ketë këtë leje për t'ua dhënë të tjerëve.",
   "components.PermissionEdit.users": "Menaxho Përdoruesit",
   "components.PermissionEdit.usersDescription": "Jep leje për të menaxhuar përdoruesit. Përdoruesit me këtë leje nuk mund të modifikojnë ose të japin privilegjin e administratorit.",
   "components.PermissionEdit.viewissues": "Shiko Problemet",
@@ -289,7 +285,6 @@
   "components.RequestModal.QuotaDisplay.notenoughseasonrequests": "Nuk kanë mbetur kërkesa të mjaftueshme për sezonin",
   "components.RequestModal.QuotaDisplay.quotaLink": "Ju mund të shikoni një përmbledhje të kufizimeve tuaja të kërkesës në <ProfileLink>faqen tuaj të profilit</ProfileLink>.",
   "components.RequestModal.QuotaDisplay.season": "sezon",
-  "components.RequestModal.SearchByNameModal.nosummary": "Nuk u gjet asnjë përmbledhje për këtë titull.",
   "components.RequestModal.SearchByNameModal.notvdbiddescription": "Nuk mund të përputheshim automatikisht me kërkesën tënde. Ju lutem zgjidhni ndeshjen e saktë nga lista më poshtë.",
   "components.RequestModal.alreadyrequested": "E Kërkuar Tashmë",
   "components.RequestModal.approve": "Mirato Kërkesën",
@@ -297,9 +292,8 @@
   "components.RequestModal.edit": "Ndrysho kërkesën",
   "components.RequestModal.errorediting": "Diçka shkoi keq duke modifikuar kërkesën.",
   "components.RequestModal.numberofepisodes": "# i Episodeve",
-  "components.RequestModal.pending4krequest": "Kërkesë 4K në pritje për {title}",
-  "components.RequestModal.pendingrequest": "Kërkesë në pritje për {title}",
-  "components.RequestModal.request4ktitle": "Kërko {title} në 4K",
+  "components.RequestModal.pending4krequest": "",
+  "components.RequestModal.pendingrequest": "Kërkesë në pritje",
   "components.RequestModal.requestApproved": "Kërkesa për <strong>{title}</strong> u miratua!",
   "components.RequestModal.requestCancel": "Kërkesa për <strong>{title}</strong> u anullua.",
   "components.RequestModal.requestSuccess": "<strong>{title}</strong> u kërkua me sukses!",
@@ -309,7 +303,6 @@
   "components.RequestModal.requestfrom": "Kërkesa e {username} është në pritje të miratimit.",
   "components.RequestModal.requestmovies": "Kërko {count} {count, plural, one {Film} other {Filma}}",
   "components.RequestModal.requestmovies4k": "Kërko {count} {count, plural, one {Film} other {Filma}} në 4K",
-  "components.RequestModal.requesttitle": "Kërko {title}",
   "components.RequestModal.season": "Sezoni",
   "components.RequestModal.seasonnumber": "Sezoni {numri}",
   "components.RequestModal.selectmovies": "Zgjidh Filmat",
@@ -662,7 +655,7 @@
   "components.Settings.toastTautulliSettingsFailure": "Diçka shkoi keq duke ruajtur cilësimet e Tautullit.",
   "components.Settings.toastTautulliSettingsSuccess": "Cilësimet e Tautulli u ruajtën me sukses!",
   "components.Settings.trustProxy": "Aktivo suportin Proxy",
-  "components.Settings.trustProxyTip": "Lejo Overseerr të regjistrojë në mënyrë korrekte adresat IP të klientit prapa një proxy (Overseerr duhet të ristartohet që ndryshimet të hyjnë në fuqi)",
+  "components.Settings.trustProxyTip": "Lejo Overseerr të regjistrojë në mënyrë korrekte adresat IP të klientit prapa një proxy",
   "components.Settings.urlBase": "Baza URL",
   "components.Settings.validationApiKey": "Duhet të japësh një çelës API",
   "components.Settings.validationApplicationTitle": "Duhet të japësh një titull aplikacioni",
@@ -689,9 +682,6 @@
   "components.Setup.welcome": "Mirë se vini në Overseerr",
   "components.StatusBadge.status": "{status}",
   "components.StatusBadge.status4k": "{status} 4K",
-  "components.StatusChacker.newversionDescription": "Overseerr është përditësuar! Ju lutemi, klikoni butonin më poshtë për të ringarkuar faqen.",
-  "components.StatusChacker.newversionavailable": "Përditësimi i aplikacionit",
-  "components.StatusChacker.reloadOverseerr": "Ringarko",
   "components.TvDetails.TvCast.fullseriescast": "Kast i plotë i serisë",
   "components.TvDetails.TvCrew.fullseriescrew": "Ekuipazhi i plotë i serisë",
   "components.TvDetails.anime": "Anime",
@@ -824,7 +814,6 @@
   "components.UserProfile.UserSettings.menuPermissions": "Lejet",
   "components.UserProfile.UserSettings.unauthorizedDescription": "Ju nuk keni leje për të modifikuar cilësimet e këtij përdoruesi.",
   "components.UserProfile.limit": "{remaining} prej {limit}",
-  "components.UserProfile.norequests": "Asnjë kërkesë.",
   "components.UserProfile.pastdays": "{type} (kaluar {days} ditë)",
   "components.UserProfile.recentlywatched": "Shikuar së fundmi",
   "components.UserProfile.totalrequests": "Kërkesat totale",
@@ -968,7 +957,7 @@
   "components.Settings.copied": "Çelësi API u kopjua.",
   "components.Settings.csrfProtection": "Aktivo mbrojtjen e CSRF",
   "components.Settings.csrfProtectionHoverTip": "MOS e aktivizoni këtë cilësim nëse nuk e kuptoni se çfarë po bëni!",
-  "components.Settings.csrfProtectionTip": "Cakto aksesin e API-së së jashtme vetëm për lexim (kërkon HTTPS dhe Overseerr duhet të ringarkohet që ndryshimet të hyjnë në fuqi)",
+  "components.Settings.csrfProtectionTip": "Cakto aksesin e API-së së jashtme vetëm për lexim (kërkon HTTPS)",
   "components.Settings.currentlibrary": "Libraria aktuale: {name}",
   "components.Settings.default": "E paracaktuar",
   "components.Settings.default4k": "E Paracaktuar 4K",
@@ -1039,5 +1028,44 @@
   "i18n.next": "Tjetra",
   "i18n.experimental": "Eksperimentale",
   "i18n.noresults": "S'ka rezultate.",
-  "i18n.notrequested": "Nuk është Kerkuar"
+  "i18n.notrequested": "Nuk është Kerkuar",
+  "components.Settings.SettingsAbout.appDataPath": "Direktoria e të dhënave",
+  "components.MovieDetails.digitalrelease": "Publikimi Dixhital",
+  "components.MovieDetails.physicalrelease": "Lëshimi Fizik",
+  "components.MovieDetails.theatricalrelease": "Publikimi Teatror",
+  "components.PermissionEdit.viewrecent": "Shiko Shtuar së fundi",
+  "components.PermissionEdit.viewrecentDescription": "Jep leje për të parë listën e mediave të shtuara kohët e fundit.",
+  "components.Discover.DiscoverWatchlist.discoverwatchlist": "Lista juaj e shikimit në Plex",
+  "components.PermissionEdit.autorequestMoviesDescription": "Jepni lejen për të paraqitur automatikisht kërkesat për mediat jo-4K nëpërmjet Plex Watchlist.",
+  "components.PermissionEdit.autorequestSeries": "Kërkesa Automatike Serialesh",
+  "components.PermissionEdit.autorequestSeriesDescription": "Jep leje për të paraqitur automatikisht kërkesat për seri jo-4K nëpërmjet Plex Watchlist.",
+  "components.Discover.DiscoverWatchlist.watchlist": "Lista e Shikimit Plex",
+  "components.Discover.plexwatchlist": "Lista juaj e shikimit në Plex",
+  "components.MovieDetails.reportissue": "Raportoni një problem",
+  "components.NotificationTypeSelector.mediaautorequested": "Kërkesa u dorëzua automatikisht",
+  "components.PermissionEdit.autorequest": "Auto-Kërkesë",
+  "components.PermissionEdit.autorequestDescription": "Jepni lejen për të paraqitur automatikisht kërkesat për mediat jo-4K nëpërmjet Plex Watchlist.",
+  "components.PermissionEdit.autorequestMovies": "Kërkesë automatike për filma",
+  "components.PermissionEdit.viewwatchlists": "Shiko listat e shikimit të Plex",
+  "components.PermissionEdit.viewwatchlistsDescription": "Jep leje për të parë listat e Plex Watchlist të përdoruesve të tjerë.",
+  "components.MovieDetails.managemovie": "Menaxho filmin",
+  "components.AirDateBadge.airedrelative": "Transmetuar {relativeTime}",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.movierequests": "Kërkesat e Filmave",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.seriesrequests": "Kërkesat e Serialeve",
+  "components.Layout.UserDropdown.requests": "Kërkesat",
+  "components.MovieDetails.rtaudiencescore": "Rezultati i audiencës së Rotten Tomatoes",
+  "components.MovieDetails.rtcriticsscore": "Tomatometeri i Rotten Tomatoes",
+  "components.NotificationTypeSelector.mediaautorequestedDescription": "Njoftohuni kur kërkesat e reja të medias dorëzohen automatikisht për artikujt në Listën tuaj të Plex Watchlist.",
+  "components.RequestBlock.languageprofile": "Profili i gjuhës",
+  "components.AirDateBadge.airsrelative": "Duke u Transmetuar {relativeTime}",
+  "components.Discover.emptywatchlist": "Këtu do të shfaqet media e shtuar në listën tuaj <PlexWatchlistSupportLink>Plex</PlexWatchlistSupportLink>.",
+  "components.RequestBlock.decline": "Refuzo kërkesën",
+  "components.RequestBlock.delete": "Fshije Kërkesën",
+  "components.RequestBlock.edit": "Ndrysho kërkesën",
+  "components.MovieDetails.tmdbuserscore": "Nota e përdoruesve TMDB",
+  "components.RequestBlock.approve": "Mirato Kërkesën",
+  "components.RequestBlock.lastmodifiedby": "Ndryshuar së fundi nga",
+  "components.RequestBlock.requestdate": "Data e Kërkesës",
+  "components.RequestBlock.requestedby": "Kërkuar nga",
+  "components.RequestCard.approverequest": "Mirato Kërkesën"
 }
diff --git a/src/i18n/locale/sr.json b/src/i18n/locale/sr.json
index 07705d07..d04487c9 100644
--- a/src/i18n/locale/sr.json
+++ b/src/i18n/locale/sr.json
@@ -37,7 +37,7 @@
   "components.TvDetails.network": "{networkCount, plural, one {Mreža} other {Mreže}}",
   "components.TvDetails.cast": "Uloge",
   "components.TvDetails.anime": "Anime",
-  "components.TvDetails.TvCast.fullseriescast": "Glumci cele serije",
+  "components.TvDetails.TvCast.fullseriescast": "Svi glumci serije",
   "components.Setup.welcome": "Dobrodošli u Overseerr",
   "components.Setup.tip": "Savet",
   "components.Setup.signinMessage": "Započni tako što ćete se prijaviti sa svojim Plex nalogom",
@@ -74,7 +74,7 @@
   "components.Settings.manualscan": "Ručno skeniranje sadržaja",
   "components.Settings.librariesRemaining": "Broj sadržaja koji se obradjuje: {count}",
   "components.Settings.hostname": "Hostname ili IP adresa",
-  "components.Settings.generalsettingsDescription": "Ovo su podešavanja vezana za uobičajenu Overseerr konfiguraciju.",
+  "components.Settings.generalsettingsDescription": "Konfiguriši globalna i uobičajena podešavanja za Overseerr.",
   "components.Settings.generalsettings": "Standarna podešavanja",
   "components.Settings.deleteserverconfirm": "Da li ste sigurni da želite da izbrišete ovaj server?",
   "components.Settings.default4k": "Podrazumevano 4K",
@@ -170,12 +170,11 @@
   "components.RequestModal.selectseason": "Odaberi sezonu(e)",
   "components.RequestModal.seasonnumber": "Sezona {number}",
   "components.RequestModal.season": "Sezona",
-  "components.RequestModal.requesttitle": "Zatraži {title}",
   "components.RequestModal.requestfrom": "Trenutno postoji zahtev na čekanju od {username}.",
   "components.RequestModal.requestadmin": "Ovaj zahtev će odmah biti prihvaćen.",
   "components.RequestModal.requestSuccess": "Poslat zahtev za <strong>{title}</strong> !",
   "components.RequestModal.requestCancel": "Zahtev za <strong>{title}</strong> otkazan.",
-  "components.RequestModal.pendingrequest": "Zahtev na čekanju za {title}",
+  "components.RequestModal.pendingrequest": "Zahtev na čekanju",
   "components.RequestModal.numberofepisodes": "# broj epizoda",
   "components.RequestModal.extras": "Dodaci",
   "components.RequestModal.cancel": "Otkaži zahtev",
@@ -210,7 +209,7 @@
   "components.Discover.populartv": "Popularne serije",
   "components.Discover.popularmovies": "Popularni filmovi",
   "components.Discover.discovertv": "Popularne serije",
-  "components.Discover.discovermovies": "Popunarni Filmovi",
+  "components.Discover.discovermovies": "Popularni filmovi",
   "pages.errormessagewithcode": "{statusCode} - {error}",
   "components.StatusBadge.status": "{status}",
   "components.UserProfile.movierequests": "Zahtev za film",
@@ -219,7 +218,6 @@
   "components.Discover.discover": "Pronađi novo",
   "components.MovieDetails.showless": "Prikaži manje",
   "components.Settings.SettingsLogs.logs": "Logovi",
-  "components.StatusChacker.reloadOverseerr": "Osveži",
   "components.MovieDetails.watchtrailer": "Pogledaj najavu",
   "components.UserProfile.UserSettings.UserNotificationSettings.notifications": "Notifikacije",
   "components.UserList.create": "Kreiraj",
@@ -339,7 +337,6 @@
   "components.RegionSelector.regionDefault": "Svi regioni",
   "components.Settings.SonarrModal.externalUrl": "Eksterni URL",
   "components.Discover.DiscoverMovieLanguage.languageMovies": "{language} filmova",
-  "components.StatusChacker.newversionavailable": "Ažuriranje aplikacije",
   "components.Settings.originallanguage": "Otkrijte jezik",
   "components.CollectionDetails.numberofmovies": "{count} filmova",
   "components.RequestList.sortAdded": "Najnoviji",
@@ -381,7 +378,6 @@
   "components.UserProfile.UserSettings.UserGeneralSettings.generalsettings": "Standardna podešavanja",
   "components.UserProfile.UserSettings.UserGeneralSettings.plexuser": "Plex korisnik",
   "components.PermissionEdit.autoapprove4k": "Automatsko odobrenje 4K",
-  "components.Discover.noRequests": "Nema zahteva.",
   "components.IssueModal.issueSubtitles": "Titl",
   "components.PermissionEdit.managerequests": "Upravljajte zahtevima",
   "components.RequestBlock.rootfolder": "Root folder",
@@ -389,7 +385,7 @@
   "components.RequestModal.AdvancedRequester.destinationserver": "Odredišni server",
   "components.RequestList.RequestItem.requesteddate": "Zahtevano",
   "components.Settings.Notifications.NotificationsPushbullet.accessToken": "Pristupni token",
-  "components.Settings.SettingsJobsCache.jobname": "Ima posla",
+  "components.Settings.SettingsJobsCache.jobname": "Ime posla",
   "components.Settings.SonarrModal.languageprofile": "Jezik profila",
   "components.Settings.is4k": "4K",
   "components.Settings.mediaTypeSeries": "serije",
@@ -407,7 +403,6 @@
   "components.IssueDetails.IssueDescription.description": "Opis",
   "components.IssueDetails.allseasons": "Sve sezone",
   "components.IssueDetails.unknownissuetype": "Nepoznat",
-  "components.PermissionEdit.settings": "Upravljajte podešavanjima",
   "components.Settings.SonarrModal.syncEnabled": "Omogući skeniranje",
   "components.ResetPassword.confirmpassword": "Potvrdi lozinku",
   "components.Settings.SettingsJobsCache.cachename": "Ime keša",
@@ -514,8 +509,107 @@
   "components.UserProfile.ProfileHeader.joindate": "Pridružio se {joindate}",
   "components.Settings.Notifications.botUsername": "Bot korisničko ime",
   "components.Settings.Notifications.pgpPassword": "PGP lozinka",
-  "components.UserProfile.norequests": "Nema zahteva.",
   "components.Settings.SettingsLogs.logDetails": "Detalji dnevnika",
   "components.Settings.scan": "Sinhronizacija biblioteka",
-  "components.UserProfile.UserSettings.UserNotificationSettings.sendSilently": "Pošalji tiho"
+  "components.UserProfile.UserSettings.UserNotificationSettings.sendSilently": "Pošalji tiho",
+  "i18n.notrequested": "Nije zahtevano",
+  "components.Settings.Notifications.validationEmail": "Morate uneti validnu email adresu",
+  "components.UserList.usercreatedfailedexisting": "Email adresa je već iskorišćena od strane drugog korisnika.",
+  "components.Settings.Notifications.NotificationsLunaSea.toastLunaSeaTestSending": "Šaljem LunaSea probno obaveštenje…",
+  "components.CollectionDetails.requestcollection4k": "Zahtevaj kolekciju u 4K",
+  "components.Login.signinheader": "Uloguj se za nastavak",
+  "components.Login.signinwithoverseerr": "Iskoristi nalog od {applicationTitle}",
+  "components.Settings.SettingsAbout.helppaycoffee": "Pomozi i plati kafu",
+  "components.Settings.SettingsJobsCache.editJobSchedule": "Modifikuj posao",
+  "components.Settings.SettingsJobsCache.jobScheduleEditSaved": "Posao uspešno izmenjen!",
+  "i18n.save": "Sačuvaj izmene",
+  "components.PermissionEdit.autoapprove4kMovies": "Automatski odobri 4K filmove",
+  "components.PermissionEdit.autoapprove4kMoviesDescription": "Dozvoli automatsko odobravanje zahteva za 4K filmove.",
+  "components.PermissionEdit.autoapprove4kSeries": "Automatski odobri 4K serije",
+  "components.ResetPassword.resetpassword": "Resetuj svoju lozinku",
+  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestSending": "Šaljem Gotify probno obaveštenje…",
+  "components.Settings.RadarrModal.create4kradarr": "Dodaj novi 4K Radarr server",
+  "components.ManageSlideOver.alltime": "Sve vreme",
+  "components.Settings.validationUrl": "Morate uneti validnu URL adresu",
+  "components.UserProfile.UserSettings.UserGeneralSettings.applanguage": "Prikaži jezik",
+  "components.UserProfile.UserSettings.UserGeneralSettings.displayName": "Prikaži ime",
+  "components.UserProfile.UserSettings.UserPasswordChange.validationConfirmPassword": "Morate potvrditi novu lozinku",
+  "components.Settings.SettingsJobsCache.jobScheduleEditFailed": "Došlo je do greške prilikom čuvanja posla.",
+  "components.Login.signinwithplex": "Koristi tvoj Plex nalog",
+  "components.Login.validationemailrequired": "Moraš uneti validnu email adresu",
+  "components.Login.validationpasswordrequired": "Moraš uneti lozinku",
+  "components.Settings.toastPlexConnectingFailure": "Neuspelo povezivanje na Plex.",
+  "components.RequestBlock.languageprofile": "Jezički profil",
+  "components.ResetPassword.resetpasswordsuccessmessage": "Lozinka uspešno resetovana!",
+  "components.ResetPassword.validationemailrequired": "Moraš uneti validnu email adresu",
+  "components.ResetPassword.validationpasswordminchars": "Lozinka je previše kratka; mora imati najmanje 8 znakova",
+  "components.ResetPassword.validationpasswordrequired": "Moraš uneti lozinku",
+  "components.Settings.Notifications.NotificationsPushbullet.toastPushbulletTestSending": "Šaljem Pushbullet probno obaveštenje…",
+  "components.Settings.Notifications.NotificationsPushbullet.toastPushbulletTestSuccess": "Pushbullet probno obaveštenje poslato!",
+  "components.Settings.Notifications.NotificationsPushover.toastPushoverTestSending": "Šaljem Pushover probno obaveštenje…",
+  "components.Settings.Notifications.NotificationsSlack.toastSlackTestSending": "Šaljem Slack probno obaveštenje…",
+  "components.Settings.Notifications.NotificationsWebPush.agentenabled": "Omogući agenta",
+  "components.Settings.Notifications.NotificationsWebhook.validationWebhookUrl": "Morate uneti validnu URL adresu",
+  "components.Settings.Notifications.encryptionOpportunisticTls": "Uvek koristi STARTTLS",
+  "components.Settings.RadarrModal.edit4kradarr": "Izmeni 4K Radarr server",
+  "components.Settings.SettingsAbout.outofdate": "Zastarelo",
+  "components.Settings.SettingsJobsCache.jobsandcache": "Poslovi i keš",
+  "components.Settings.SettingsUsers.toastSettingsSuccess": "Podešavanja korisnika uspešno sačuvana!",
+  "components.Settings.SonarrModal.animelanguageprofile": "Jezički profil za anime",
+  "components.Settings.SonarrModal.animeTags": "Anime oznake",
+  "components.Settings.SonarrModal.enableSearch": "Omogući automatsku pretragu",
+  "components.Settings.SonarrModal.loadingTags": "Oznake se učitavaju…",
+  "components.Settings.SonarrModal.loadinglanguageprofiles": "Učitavanje jezičkih profila…",
+  "components.Settings.SonarrModal.selecttags": "Izaberi oznake",
+  "components.Settings.SonarrModal.selectLanguageProfile": "Izaberi jezički profil",
+  "components.Settings.SonarrModal.toastSonarrTestFailure": "Neuspešno povezivanje na Sonarr.",
+  "components.Settings.SonarrModal.toastSonarrTestSuccess": "Povezivanje na Sonarr uspešno!",
+  "components.Settings.SonarrModal.validationApplicationUrl": "Moraš uneti validnu URL adresu",
+  "components.Settings.SonarrModal.validationLanguageProfileRequired": "Moraš izabrati jezički profil",
+  "components.Settings.externalUrl": "Spoljni URL",
+  "components.Settings.regionTip": "Filtriraj sadržaj po regionalnoj dostupnosti",
+  "components.Settings.tautulliSettings": "Tautulli podešavanja",
+  "components.Settings.tautulliApiKey": "API ključ",
+  "components.Settings.toastTautulliSettingsFailure": "Nešto nije u redu prilikom čuvanja Tautulli podešavanja.",
+  "components.Settings.tautulliSettingsDescription": "Opciono konfiguriši podešavanja za tvoj Tautulli server. Overseerr će učitavati istoriju gledanja Plex sadržaja iz Tautulli-ja.",
+  "components.Settings.toastPlexConnectingSuccess": "Povezivanje sa Plex-om uspešno!",
+  "components.Settings.toastPlexRefresh": "Učitavam listu servera sa Plex-a…",
+  "components.Settings.toastPlexRefreshFailure": "Neuspešno učitavanje liste servara sa Plexa.",
+  "components.Settings.toastPlexRefreshSuccess": "Lista Plex servera uspešno preuzeta!",
+  "components.TvDetails.nextAirDate": "Sledeći datum prikazivanja",
+  "components.UserList.nouserstoimport": "Nema Plex korisnika za unos.",
+  "components.UserList.createlocaluser": "Kreiraj lokalnog korisnika",
+  "components.UserList.autogeneratepassword": "Automatski generiši šifru",
+  "components.UserProfile.UserSettings.UserGeneralSettings.toastSettingsSuccess": "Podašavanja uspešno sačuvana!",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pgpPublicKeyTip": "Enkriptuj email poruke koristeći <OpenPgpLink>OpenPGP</OpenPgpLink>",
+  "components.UserProfile.UserSettings.UserNotificationSettings.sendSilentlyDescription": "Pošalji notifikacije bez zvuka",
+  "components.UserProfile.UserSettings.UserPasswordChange.validationCurrentPassword": "Morate uneti trenutnu lozinku",
+  "components.UserProfile.UserSettings.UserPasswordChange.validationNewPassword": "Morate uneti novu lozinku",
+  "components.UserProfile.UserSettings.UserPasswordChange.validationNewPasswordLength": "Lozinka je previše kratka; mora imati najmanje 8 znakova",
+  "components.UserProfile.totalrequests": "Ukupan broj zahteva",
+  "i18n.noresults": "Nema rezultata.",
+  "i18n.request4k": "Zahtevaj u 4K",
+  "i18n.resultsperpage": "Prikaži {pageSize} rezultata po strani",
+  "i18n.showingresults": "Prikazujem <strong>{from}</strong> do <strong>{to}</strong> od <strong>{total}</strong> rezultata",
+  "components.Settings.RadarrModal.validationApplicationUrl": "Morate uneti validnu URL adresu",
+  "components.Settings.SettingsAbout.Releases.viewongithub": "Pogledaj na GitHub",
+  "components.Settings.SonarrModal.edit4ksonarr": "Izmeni 4K Sonarr server",
+  "components.UserList.validationEmail": "Morate uneti validnu email adresu",
+  "components.UserProfile.UserSettings.UserPasswordChange.toastSettingsSuccess": "Lozinka uspešno sačuvana!",
+  "components.Settings.toastPlexConnecting": "Pokušavam povezivanje na Plex…",
+  "pages.somethingwentwrong": "Nešto je pogrešno",
+  "pages.internalservererror": "Interna greška servera",
+  "pages.pagenotfound": "Stranica nije pronađena",
+  "components.ManageSlideOver.mark4kavailable": "Obeleži kao dostupno u 4K",
+  "components.Login.loginerror": "Dogodila se greška prilikom prijave.",
+  "components.Settings.SonarrModal.create4ksonarr": "Dodaj novi 4K Sonarr server",
+  "components.PermissionEdit.autoapprove4kSeriesDescription": "Dozvoli automatsko odobravanje zahteva za 4K serije.",
+  "components.ResetPassword.gobacklogin": "Vrati se na stranu za prijavu",
+  "components.Settings.SettingsJobsCache.editJobScheduleSelectorHours": "Svaki {jobScheduleHours, plural, one {hour} other {{jobScheduleHours} hours}}",
+  "components.Settings.SettingsAbout.uptodate": "Najsvežiji",
+  "components.Settings.Notifications.NotificationsWebhook.validationJsonPayloadRequired": "Morate da navedete važeći JSON korisni teret",
+  "components.Settings.Notifications.validationChatIdRequired": "Morate da navedete važeći ID za ćaskanje",
+  "components.StatusBadge.playonplex": "Igrajte na Plex-u",
+  "components.Settings.Notifications.NotificationsPushbullet.validationAccessTokenRequired": "Morate da obezbedite pristupni token",
+  "components.UserList.userssaved": "Korisničke dozvole su uspešno sačuvane!"
 }
diff --git a/src/i18n/locale/sv.json b/src/i18n/locale/sv.json
index dee3a458..b363ea80 100644
--- a/src/i18n/locale/sv.json
+++ b/src/i18n/locale/sv.json
@@ -127,12 +127,11 @@
   "components.RequestModal.selectseason": "Välj säsong(er)",
   "components.RequestModal.seasonnumber": "Säsong {number}",
   "components.RequestModal.season": "Säsong",
-  "components.RequestModal.requesttitle": "Begär {title}",
   "components.RequestModal.requestfrom": "{username}'s begäran väntar på godkännande.",
   "components.RequestModal.requestadmin": "Förfrågan kommer bli godkännas automatiskt.",
   "components.RequestModal.requestSuccess": "<strong>{title}</strong> begärd!",
   "components.RequestModal.requestCancel": "Förfrågan för <strong>{title}</strong> avbruten.",
-  "components.RequestModal.pendingrequest": "Väntande Förfrågan för {title}",
+  "components.RequestModal.pendingrequest": "Väntande Förfrågan",
   "components.RequestModal.numberofepisodes": "Antal Avsnitt",
   "components.RequestModal.extras": "Extramaterial",
   "components.RequestModal.cancel": "Avbryt förfrågan",
@@ -242,9 +241,6 @@
   "components.TvDetails.viewfullcrew": "Visa hela rollistan",
   "components.TvDetails.firstAirDate": "Första sändningsdatum",
   "components.TvDetails.TvCrew.fullseriescrew": "Hela rollistan",
-  "components.StatusChacker.reloadOverseerr": "Ladda om",
-  "components.StatusChacker.newversionavailable": "Applikationsuppdatering",
-  "components.StatusChacker.newversionDescription": "Overseerr har uppdateras! Klicka på knappen nedan för att ladda om sidan.",
   "components.StatusBadge.status4k": "4K {status}",
   "components.Settings.SettingsAbout.documentation": "Dokumentation",
   "components.Settings.Notifications.validationChatIdRequired": "Du måste ange ett giltigt chatt-ID",
@@ -271,8 +267,7 @@
   "components.Settings.Notifications.NotificationsPushover.pushoversettingsfailed": "Notifieringsinställningar för Pushover kunde inte sparas.",
   "components.Settings.Notifications.NotificationsPushover.agentenabled": "Aktiverad",
   "components.Settings.Notifications.NotificationsPushover.accessToken": "Application API-token",
-  "components.RequestModal.request4ktitle": "Begär {titel} i 4K",
-  "components.RequestModal.pending4krequest": "Väntande 4K-förfrågan för {title]",
+  "components.RequestModal.pending4krequest": "Väntande 4K-förfrågan",
   "components.RequestList.sortModified": "Senast ändrad",
   "components.RequestList.sortAdded": "Senaste",
   "components.RequestList.showallrequests": "Visa alla förfrågningar",
@@ -304,8 +299,6 @@
   "components.UserList.bulkedit": "Mass-redigering",
   "components.PermissionEdit.usersDescription": "Bevilja behörighet att hantera användare. Användare med denna behörighet kan inte ändra användare med eller bevilja administratörsbehörighet.",
   "components.PermissionEdit.users": "Hantera Användare",
-  "components.PermissionEdit.settingsDescription": "Ge tillstånd att ändra globala inställningar. En användare måste ha denna behörighet för att ge den till andra.",
-  "components.PermissionEdit.settings": "Hantera Inställningar",
   "components.PermissionEdit.requestDescription": "Ge tillstånd att skicka förfrågningar för icke-4K-media.",
   "components.PermissionEdit.request4kTvDescription": "Bevilja tillstånd att skicka förfrågningar för 4K-serien.",
   "components.PermissionEdit.request4kTv": "Begära 4K Serier",
@@ -321,7 +314,6 @@
   "components.PlexLoginButton.signingin": "Loggar in…",
   "components.RequestModal.requesterror": "Någonting gick fel vid behandling av din begäran.",
   "components.RequestModal.SearchByNameModal.notvdbiddescription": "Vi kunde inte automatiskt matcha din begäran. Var god välj den korrekta matchningen från listan nedanför.",
-  "components.RequestModal.SearchByNameModal.nosummary": "Ingen summering för denna titel hittades.",
   "i18n.experimental": "Experimentell",
   "components.Settings.hideAvailable": "Göm Tillgänglig Media",
   "components.RequestModal.autoapproval": "Automatiskt Godkännande",
@@ -437,7 +429,7 @@
   "components.Settings.SettingsJobsCache.cacheflushed": "{cachename} cache rensad.",
   "components.Settings.SettingsJobsCache.cacheDescription": "Overseerr cachear förfrågningar till externa API-endpoints för att optimera prestanda och att undvika onödiga api-kall.",
   "components.Settings.SettingsJobsCache.cache": "Cache",
-  "components.Settings.trustProxyTip": "Tillåt Overseerr att korrekt registrera klienters IP-adresser bakom en proxy (Overseerr måste laddas om för att ändringarna skall gå i kraft)",
+  "components.Settings.trustProxyTip": "Tillåt Overseerr att korrekt registrera klienters IP-adresser bakom en proxy",
   "components.Settings.trustProxy": "Aktivera Proxy-stöd",
   "components.TvDetails.playonplex": "Spela upp på Plex",
   "components.TvDetails.play4konplex": "Spela upp i 4K på Plex",
@@ -460,7 +452,7 @@
   "components.Settings.serverpreset": "Server",
   "components.Settings.serverRemote": "fjärr",
   "components.Settings.serverLocal": "lokal",
-  "components.Settings.csrfProtectionTip": "Ställ in extern API-åtkomst till skrivskyddad (kräver HTTPS och Overseerr måste laddas om för att ändringar ska träda i kraft)",
+  "components.Settings.csrfProtectionTip": "Ställ in extern API-åtkomst till skrivskyddad (kräver HTTPS)",
   "i18n.loading": "Laddar…",
   "components.UserProfile.recentrequests": "Senaste förfrågningar",
   "components.UserProfile.UserSettings.menuPermissions": "Behörigheter",
@@ -523,7 +515,7 @@
   "components.Settings.scanning": "Synkar…",
   "components.Settings.scan": "Skanna bibliotek",
   "components.Settings.regionTip": "Filtrera innehåll efter region tillgänglighet",
-  "components.Settings.region": "Upptäck Region",
+  "components.Settings.region": "Upptäck region",
   "components.Settings.originallanguageTip": "Filtrera innehåll efter originalspråk",
   "components.Settings.originallanguage": "Upptäck språk",
   "components.Settings.notificationAgentSettingsDescription": "Konfigurera och aktivera aviseringsagenter.",
@@ -593,7 +585,6 @@
   "components.Discover.TvGenreList.seriesgenres": "Seriegenrer",
   "components.Discover.TvGenreSlider.tvgenres": "Seriegenrer",
   "components.RequestModal.AdvancedRequester.folder": "{path} ({space})",
-  "components.UserProfile.norequests": "Inga förfrågningar.",
   "components.TvDetails.episodeRuntimeMinutes": "{runtime} minuter",
   "components.TvDetails.episodeRuntime": "Avsnittets speltid",
   "components.Settings.partialRequestsEnabled": "Tillåt begäran av ofullständig serie",
@@ -684,8 +675,8 @@
   "components.UserProfile.UserSettings.UserGeneralSettings.seriesrequestlimit": "Serieförfrågnings gräns",
   "components.UserProfile.UserSettings.UserGeneralSettings.movierequestlimit": "Filmförfrågnings gräns",
   "components.UserProfile.UserSettings.UserGeneralSettings.enableOverride": "Överskrid den globala gränsen",
-  "components.Settings.SettingsUsers.tvRequestLimitLabel": "Global serieförfrågnings gräns",
-  "components.Settings.SettingsUsers.movieRequestLimitLabel": "Global filmförfrågnings gräns",
+  "components.Settings.SettingsUsers.tvRequestLimitLabel": "Global serieförfrågningsgräns",
+  "components.Settings.SettingsUsers.movieRequestLimitLabel": "Global filmförfrågningsgräns",
   "components.RequestModal.QuotaDisplay.requiredquotaUser": "Den här användaren behöver ha minst <strong>{seasons}</strong> {seasons, plural, one {säsongsförfrågan} other {säsongsförfrågningar}} kvar för att skicka in en begäran om denna serie.",
   "components.RequestModal.QuotaDisplay.seasonlimit": "{limit, plural, one {säsong} other {säsonger}}",
   "components.RequestModal.QuotaDisplay.season": "säsong",
@@ -734,7 +725,6 @@
   "components.RequestModal.pendingapproval": "Din begäran väntar på godkännande.",
   "components.RequestList.RequestItem.cancelRequest": "Avbryt begäran",
   "components.NotificationTypeSelector.notificationTypes": "Notifikationstyper",
-  "components.Discover.noRequests": "Inga förfrågningar.",
   "components.Layout.VersionStatus.streamstable": "Overseerr Stabil",
   "components.Layout.VersionStatus.streamdevelop": "Overseerr Utveckling",
   "components.Layout.VersionStatus.outofdate": "Föråldrad",
@@ -963,7 +953,6 @@
   "components.IssueModal.CreateIssueModal.allepisodes": "Alla avsnitt",
   "components.IssueModal.CreateIssueModal.allseasons": "Alla säsonger",
   "components.IssueModal.CreateIssueModal.episode": "Avsnitt {episodeNumber}",
-  "components.IssueModal.CreateIssueModal.issomethingwrong": "Är det något problem med {title}?",
   "components.IssueModal.CreateIssueModal.problemepisode": "Påverkat avsnitt",
   "components.IssueModal.CreateIssueModal.providedetail": "Ge en detaljerad förklaring av det problem du stötte på.",
   "components.ManageSlideOver.downloadstatus": "Nedladdningar",
@@ -1040,5 +1029,13 @@
   "components.UserProfile.UserSettings.UserGeneralSettings.validationDiscordId": "Du måste ange ett giltigt Discord användar-ID",
   "components.UserProfile.UserSettings.UserGeneralSettings.discordId": "Discord användar-ID",
   "components.UserProfile.UserSettings.UserGeneralSettings.discordIdTip": "Det <FindDiscordIdLink>flersiffriga ID-numret</FindDiscordIdLink> som är kopplat till ditt Discord-användarkonto",
-  "components.Settings.SettingsAbout.appDataPath": "Datakatalog"
+  "components.Settings.SettingsAbout.appDataPath": "Datakatalog",
+  "components.RequestBlock.languageprofile": "Språkprofil",
+  "components.StatusChecker.reloadApp": "Ladda om {applicationTitle}",
+  "i18n.restartRequired": "Omstart krävs",
+  "components.Settings.deleteServer": "Radera {serverType} Server",
+  "components.StatusChecker.appUpdated": "{applicationTitle} Uppdaterad",
+  "components.StatusChecker.appUpdatedDescription": "Klicka på knappen under för att ladda om programmet.",
+  "components.StatusChecker.restartRequired": "Servern behöver startas om",
+  "components.StatusChecker.restartRequiredDescription": "Starta om servern för att verkställa uppdaterade inställningar."
 }
diff --git a/src/i18n/locale/zh_Hans.json b/src/i18n/locale/zh_Hans.json
index c8d3bc85..4232a1f7 100644
--- a/src/i18n/locale/zh_Hans.json
+++ b/src/i18n/locale/zh_Hans.json
@@ -61,9 +61,6 @@
   "components.TvDetails.anime": "动漫",
   "components.TvDetails.TvCrew.fullseriescrew": "制作群",
   "components.TvDetails.TvCast.fullseriescast": "演员阵容",
-  "components.StatusChacker.reloadOverseerr": "刷新页面",
-  "components.StatusChacker.newversionavailable": "软件更新",
-  "components.StatusChacker.newversionDescription": "Overseerr 软件已更新。请点击以下的按钮刷新页面。",
   "components.StatusBadge.status4k": "4K 版{status}",
   "components.Setup.welcome": "欢迎來到 Overseerr",
   "components.Setup.tip": "提示",
@@ -85,7 +82,7 @@
   "components.Settings.validationApplicationUrlTrailingSlash": "必须刪除結尾斜線",
   "components.Settings.validationApplicationUrl": "请输入有效的网址",
   "components.Settings.validationApplicationTitle": "请输入应用程序名",
-  "components.Settings.trustProxyTip": "使用代理服务器时,允许 Overseerr 探明客户端 IP 地址(Overseerr 必须重新启动)",
+  "components.Settings.trustProxyTip": "允许 Overseerr 使用代理正确注册客户端 IP 地址",
   "components.Settings.trustProxy": "启用代理服务器所需功能",
   "components.Settings.toastSettingsSuccess": "设置保存成功!",
   "components.Settings.toastSettingsFailure": "保存设置中出了点问题。",
@@ -157,12 +154,12 @@
   "components.Settings.default4k": "设置 4K 为默认分辨率",
   "components.Settings.default": "默认",
   "components.Settings.currentlibrary": "当前媒体库: {name}",
-  "components.Settings.csrfProtectionTip": "设置外部访问权限为只讀(Overseerr 必须重新启动)",
+  "components.Settings.csrfProtectionTip": "设置外部访问权限为只读(需要 HTTPS)",
   "components.Settings.csrfProtectionHoverTip": "除非你了解此功能,请勿启用它!",
   "components.Settings.csrfProtection": "防止跨站请求伪造(CSRF)攻击",
   "components.Settings.copied": "应用程序密钥已复制到剪贴板。",
   "components.Settings.cancelscan": "取消扫描",
-  "components.Settings.cacheImagesTip": "把所有的图像优化和保存到缓存(需要大量的磁碟空间)",
+  "components.Settings.cacheImagesTip": "缓存并提供优化的图像(需要大量磁盘空间)",
   "components.Settings.cacheImages": "启用图像緩存",
   "components.Settings.applicationurl": "应用程序网址(URL)",
   "components.Settings.applicationTitle": "应用程序名",
@@ -294,7 +291,6 @@
   "components.Discover.recentlyAdded": "最新添加",
   "components.Discover.populartv": "热门电视节目",
   "components.Discover.popularmovies": "热门电影",
-  "components.Discover.noRequests": "没有请求。",
   "components.Discover.discovertv": "热门电视节目",
   "components.Discover.discovermovies": "热门电影",
   "components.Discover.discover": "探索",
@@ -314,7 +310,7 @@
   "components.CollectionDetails.requestcollection": "提交系列请求",
   "components.CollectionDetails.overview": "简介",
   "components.CollectionDetails.numberofmovies": "{count} 部电影",
-  "components.AppDataWarning.dockerVolumeMissingDescription": "必须使用繫結掛载(bind mount)指定某个宿主机器的资料夹跟容器內的 <code>{appDataPath}</code> 资料夹連通,才能保存 Overseerr 的配置和数据。",
+  "components.AppDataWarning.dockerVolumeMissingDescription": "必须使用链接挂载(bind mount)指定某个宿主机器的文件夹跟容器内的 <code>{appDataPath}</code> 文件夹连通,才能保存 Overseerr 的配置和数据。",
   "components.PersonDetails.ascharacter": "饰演 {character}",
   "pages.somethingwentwrong": "出了点问题",
   "pages.serviceunavailable": "服务器无法使用",
@@ -376,7 +372,6 @@
   "components.UserProfile.requestsperdays": "剩余 {limit}",
   "components.UserProfile.recentrequests": "最新请求",
   "components.UserProfile.pastdays": "{type}(前 {days} 天)",
-  "components.UserProfile.norequests": "没有请求。",
   "components.UserProfile.movierequests": "电影请求",
   "components.UserProfile.limit": "{limit} 之 {remaining}",
   "components.UserProfile.UserSettings.unauthorizedDescription": "你无权编辑此用户的设置。",
@@ -703,7 +698,6 @@
   "components.RequestModal.selectseason": "季数选择",
   "components.RequestModal.seasonnumber": "第 {number} 季",
   "components.RequestModal.season": "季数",
-  "components.RequestModal.requesttitle": "为 {title} 提交请求",
   "components.RequestModal.requestseasons": "提交请求",
   "components.RequestModal.requestfrom": "{username} 的请求待处理。",
   "components.RequestModal.requesterror": "提交请求中出了点问题。",
@@ -712,10 +706,9 @@
   "components.RequestModal.requestadmin": "此请求将自动被批准。",
   "components.RequestModal.requestSuccess": "为 <strong>{title}</strong> 提交请求成功!",
   "components.RequestModal.requestCancel": "<strong>{title}</strong> 的请求已被取消。",
-  "components.RequestModal.request4ktitle": "为 {title} 提交 4K 请求",
-  "components.RequestModal.pendingrequest": "{title} 的请求",
+  "components.RequestModal.pendingrequest": "待处理请求",
   "components.RequestModal.pendingapproval": "你的请求正在等待管理员批准。",
-  "components.RequestModal.pending4krequest": "{title} 的 4K 请求",
+  "components.RequestModal.pending4krequest": "待处理的 4K 请求",
   "components.RequestModal.numberofepisodes": "集数",
   "components.RequestModal.extras": "特輯",
   "components.RequestModal.errorediting": "编辑请求中出了点问题。",
@@ -723,8 +716,7 @@
   "components.RequestModal.cancel": "取消请求",
   "components.RequestModal.autoapproval": "自动批准",
   "components.RequestModal.alreadyrequested": "已经有请求",
-  "components.RequestModal.SearchByNameModal.notvdbiddescription": "无法自动配對你的请求。请从以下列表中选择正确的媒体项。",
-  "components.RequestModal.SearchByNameModal.nosummary": "没有简介。",
+  "components.RequestModal.SearchByNameModal.notvdbiddescription": "我们无法自动匹配这个连续剧。请选择下方正确的匹配。",
   "components.RequestModal.QuotaDisplay.seasonlimit": "个季数",
   "components.RequestModal.QuotaDisplay.season": "电视节目季数",
   "components.RequestModal.QuotaDisplay.requiredquotaUser": "此用户的电视节目请求数量必须至少剩余 <strong>{seasons}</strong> 个季数才能为此节目提交请求。",
@@ -758,13 +750,13 @@
   "components.RequestList.RequestItem.requested": "请求者",
   "components.RequestList.RequestItem.modifieduserdate": "{user}({date})",
   "components.RequestList.RequestItem.modified": "最后修改者",
-  "components.RequestList.RequestItem.mediaerror": "找不到此请求的媒体项目。",
+  "components.RequestList.RequestItem.mediaerror": "未找到{mediaType}",
   "components.RequestList.RequestItem.failedretry": "重试提交请求中出了点问题。",
   "components.RequestList.RequestItem.editrequest": "编辑请求",
   "components.RequestList.RequestItem.deleterequest": "刪除请求",
   "components.RequestList.RequestItem.cancelRequest": "取消请求",
   "components.RequestCard.seasons": "季数",
-  "components.RequestCard.mediaerror": "找不到此请求的媒体项目。",
+  "components.RequestCard.mediaerror": "未找到{mediaType}",
   "components.RequestCard.failedretry": "重试提交请求中出了点问题。",
   "components.RequestCard.deleterequest": "刪除请求",
   "components.RequestButton.viewrequest4k": "查看 4K 请求",
@@ -803,8 +795,6 @@
   "components.PermissionEdit.viewrequests": "查看请求",
   "components.PermissionEdit.usersDescription": "授予管理用户的权限。 拥有此权限的用户无法修改具有管理员权限的用户或授予管理员权限。",
   "components.PermissionEdit.users": "用户管理",
-  "components.PermissionEdit.settingsDescription": "授予修改全局设置的权限。 用户必须具有此权限才能将其授予其他人。",
-  "components.PermissionEdit.settings": "设置管理",
   "components.PermissionEdit.requestTvDescription": "授予提交非 4K 电视剧请求的权限。",
   "components.PermissionEdit.requestTv": "提交电视节目请求",
   "components.PermissionEdit.requestMoviesDescription": "授予提交非 4K 电影请求的权限。",
@@ -900,5 +890,183 @@
   "components.IssueList.IssueItem.openeduserdate": "{date} by {user}",
   "components.IssueList.IssueItem.problemepisode": "受影响的剧集",
   "components.IssueList.IssueItem.episodes": "集数",
-  "components.IssueList.IssueItem.opened": "打开"
+  "components.IssueList.IssueItem.opened": "打开",
+  "components.Settings.Notifications.NotificationsGotify.agentenabled": "开启通知",
+  "components.Settings.Notifications.NotificationsGotify.gotifysettingsfailed": "Gotify通知设置保存失败。",
+  "components.Settings.Notifications.NotificationsGotify.gotifysettingssaved": "Gotify通知设置保存成功!",
+  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestFailed": "Gotify 测试通知发送失败。",
+  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestSending": "Gotify测试通知发送中…",
+  "components.Settings.Notifications.enableMentions": "允许提及",
+  "components.Settings.SettingsJobsCache.editJobScheduleSelectorMinutes": "每 {jobScheduleMinutes} 分钟",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoverApplicationToken": "应用 API 令牌",
+  "components.UserList.newplexsigninenabled": "<strong>允许新的 Plex 用户登录</strong> 设置目前已启用。还没有导入的Plex用户也能登录。",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoversettingsfailed": "Pushover 通知设置保存失败。",
+  "components.NotificationTypeSelector.issuecomment": "问题评论",
+  "components.MovieDetails.streamingproviders": "当前可播放",
+  "components.Settings.RadarrModal.inCinemas": "已上映",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletAccessTokenTip": "从您的<PushbulletSettingsLink>账号设置</PushbulletSettingsLink>获取API令牌",
+  "components.Settings.SettingsAbout.appDataPath": "数据目录",
+  "components.Settings.SettingsJobsCache.editJobScheduleSelectorHours": "每 {jobScheduleHours} 小时",
+  "components.Settings.tautulliSettings": "Tautulli 设置",
+  "components.Settings.tautulliSettingsDescription": "关于 Tautulli 服务器的设置。Overseerr 会从 Tautulli 获取 Plex 媒体的观看历史记录。",
+  "components.UserProfile.UserSettings.UserGeneralSettings.discordId": "Discord 用户ID",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletsettingsfailed": "Pushbullet 通知设置保存失败。",
+  "components.UserProfile.UserSettings.UserGeneralSettings.discordIdTip": "您的<FindDiscordIdLink>Discord 用户 ID </FindDiscordIdLink>",
+  "components.IssueList.IssueItem.unknownissuetype": "未知",
+  "components.IssueList.IssueItem.viewissue": "查看问题",
+  "components.IssueList.issues": "问题",
+  "components.IssueList.showallissues": "查看所有问题",
+  "components.IssueList.sortAdded": "最新",
+  "components.IssueList.IssueItem.seasons": "季",
+  "components.IssueList.sortModified": "最后修改",
+  "components.IssueModal.CreateIssueModal.allepisodes": "所有集数",
+  "components.IssueModal.CreateIssueModal.allseasons": "所有季数",
+  "components.IssueModal.CreateIssueModal.submitissue": "提交问题",
+  "components.IssueModal.CreateIssueModal.toastFailedCreate": "提交问题报告时出了点问题。",
+  "components.IssueModal.CreateIssueModal.toastSuccessCreate": "成功为 <strong>{title}</strong> 报告问题!",
+  "components.IssueModal.CreateIssueModal.toastviewissue": "查看问题",
+  "components.IssueModal.CreateIssueModal.validationMessageRequired": "请输入问题说明",
+  "components.IssueModal.CreateIssueModal.whatswrong": "请描述您遇到的问题?",
+  "components.IssueModal.issueAudio": "音频",
+  "components.IssueModal.issueOther": "其他",
+  "components.Layout.Sidebar.issues": "问题",
+  "components.ManageSlideOver.downloadstatus": "下载状态",
+  "components.ManageSlideOver.manageModalClearMedia": "清除数据",
+  "components.NotificationTypeSelector.issuecreatedDescription": "当用户报告问题时发送通知。",
+  "components.NotificationTypeSelector.issuereopenedDescription": "当问题重新开启时发送通知。",
+  "components.PermissionEdit.createissuesDescription": "授予报告媒体问题的权限。",
+  "components.PermissionEdit.manageissuesDescription": "授予管理媒体问题的权限。",
+  "components.RequestModal.requestmovies": "提出请求",
+  "components.RequestModal.requestseasons4k": "提出4K请求",
+  "components.Settings.SettingsJobsCache.jobScheduleEditSaved": "作业编辑成功!",
+  "i18n.resolved": "已解决",
+  "components.NotificationTypeSelector.issuereopened": "问题重新开启",
+  "components.NotificationTypeSelector.userissueresolvedDescription": "当您报告的问题解决时获取通知。",
+  "components.ManageSlideOver.alltime": "历史",
+  "components.ManageSlideOver.manageModalAdvanced": "高级",
+  "components.ManageSlideOver.manageModalClearMediaWarning": "* 这将会删除所有和{mediaType}相关的数据和所有请求。如果{mediaType}在您的Plex服务器存在,数据将会在媒体库扫描时重新建立。",
+  "components.ManageSlideOver.manageModalIssues": "未解决问题",
+  "components.ManageSlideOver.manageModalMedia": "媒体",
+  "components.ManageSlideOver.manageModalMedia4k": "4K 媒体",
+  "components.ManageSlideOver.manageModalRequests": "请求",
+  "components.ManageSlideOver.manageModalTitle": "管理{mediaType}",
+  "components.ManageSlideOver.markavailable": "标记为可观看",
+  "components.ManageSlideOver.mark4kavailable": "标记4K版本可观看",
+  "components.ManageSlideOver.markallseasons4kavailable": "标记所有季的4K版本可观看",
+  "components.ManageSlideOver.markallseasonsavailable": "标记所有季可观看",
+  "components.ManageSlideOver.opentautulli": "在 Tautulli 中查看",
+  "components.ManageSlideOver.pastdays": "过去 {days, number} 天",
+  "components.ManageSlideOver.playedby": "观看者",
+  "components.ManageSlideOver.plays": "<strong>{playCount, number}</strong> 次",
+  "components.MovieDetails.productioncountries": "出品国家",
+  "components.NotificationTypeSelector.adminissuecommentDescription": "当其他用户评论时可以获取通知。",
+  "components.NotificationTypeSelector.adminissuereopenedDescription": "当其他用户重新开启问题时获取通知。",
+  "components.NotificationTypeSelector.adminissueresolvedDescription": "当其他用户解决问题时获取通知。",
+  "components.NotificationTypeSelector.issuecommentDescription": "当问题有新评论时发送通知。",
+  "components.NotificationTypeSelector.issuecreated": "问题报告",
+  "components.NotificationTypeSelector.issueresolved": "问题解决",
+  "components.NotificationTypeSelector.issueresolvedDescription": "当问题解决时发送通知。",
+  "components.NotificationTypeSelector.userissuecommentDescription": "当您报告的问题有新评论时获取通知。",
+  "components.NotificationTypeSelector.userissuecreatedDescription": "当其他用户报告问题时获取通知。",
+  "components.NotificationTypeSelector.userissuereopenedDescription": "当您报告的问题重新开启时获取通知。",
+  "components.PermissionEdit.createissues": "报告问题",
+  "components.PermissionEdit.viewissues": "查看问题",
+  "components.PermissionEdit.viewissuesDescription": "授予查看其他用户报告的媒体问题的权限。",
+  "components.RequestModal.selectmovies": "请选择电影",
+  "components.Settings.Notifications.NotificationsGotify.toastGotifyTestSuccess": "Gotify 测试通知已发送!",
+  "components.Settings.Notifications.NotificationsGotify.token": "应用令牌",
+  "components.Settings.Notifications.NotificationsGotify.url": "服务器地址",
+  "components.Settings.Notifications.NotificationsGotify.validationTokenRequired": "请输入应用令牌",
+  "components.Settings.Notifications.NotificationsGotify.validationTypes": "请选择通知类型",
+  "components.Settings.Notifications.NotificationsGotify.validationUrlRequired": "请输入有效的网址",
+  "components.Settings.Notifications.NotificationsGotify.validationUrlTrailingSlash": "请删除网址结尾斜杠",
+  "components.Settings.urlBase": "网站根路径",
+  "components.Settings.validationApiKey": "请输入API key",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoverUserKeyTip": "您 30 个字符的<UsersGroupsLink>用户或群组ID</UsersGroupsLink>",
+  "components.Settings.Notifications.NotificationsPushbullet.channelTag": "频道标签",
+  "components.Settings.RadarrModal.announced": "已公布",
+  "components.Settings.RadarrModal.released": "已发布",
+  "components.Settings.SettingsJobsCache.editJobSchedulePrompt": "新频率",
+  "components.Settings.externalUrl": "外部网址",
+  "components.Settings.tautulliApiKey": "API Key",
+  "components.Settings.toastTautulliSettingsFailure": "保存 Tautulli 设置时出现问题。",
+  "components.Settings.toastTautulliSettingsSuccess": "Tautulli 设置保存成功!",
+  "components.Settings.validationUrlTrailingSlash": "请删除结尾斜杠",
+  "components.Settings.validationUrlBaseLeadingSlash": "请添加前置斜杠",
+  "components.Settings.validationUrlBaseTrailingSlash": "请删除结尾斜杠",
+  "components.TvDetails.productioncountries": "出品国家",
+  "components.TvDetails.streamingproviders": "当前可播放",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletAccessToken": "API 令牌",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushbulletsettingssaved": "Pushbullet 通知设置保存成功!",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoverApplicationTokenTip": "建立一个 {applicationTitle} 专用的 <ApplicationRegistrationLink>应用</ApplicationRegistrationLink>",
+  "components.UserProfile.recentlywatched": "最近观看",
+  "components.IssueModal.issueSubtitles": "字幕",
+  "components.IssueModal.issueVideo": "视频",
+  "components.ManageSlideOver.manageModalNoRequests": "没有请求。",
+  "i18n.open": "未解决",
+  "components.PermissionEdit.manageissues": "管理问题",
+  "components.RequestModal.approve": "批准请求",
+  "components.RequestModal.requestApproved": "<strong>{title}</strong> 的请求已被批准!",
+  "components.RequestModal.requestmovies4k": "提出4K请求",
+  "components.IssueModal.CreateIssueModal.extras": "特辑",
+  "components.IssueModal.CreateIssueModal.problemepisode": "有问题的集数",
+  "components.IssueModal.CreateIssueModal.problemseason": "有问题的季数",
+  "components.IssueModal.CreateIssueModal.providedetail": "请详细描述您遇到的问题。",
+  "components.IssueModal.CreateIssueModal.reportissue": "报告问题",
+  "components.IssueModal.CreateIssueModal.season": "第 {seasonNumber} 季",
+  "components.ManageSlideOver.openarr": "打开{arr}服务器",
+  "components.ManageSlideOver.openarr4k": "打开4K {arr} 服务器",
+  "components.ManageSlideOver.tvshow": "个剧集",
+  "components.UserProfile.UserSettings.UserNotificationSettings.validationPushoverApplicationToken": "请输入有效的 API 令牌",
+  "components.UserProfile.UserSettings.UserNotificationSettings.validationPushbulletAccessToken": "请输入 API 令牌",
+  "components.ManageSlideOver.movie": "部电影",
+  "components.Settings.SettingsAbout.runningDevelop": "您正在使用 Overseerr 的 <code>develop</code> 开发板。我们只建议开发者和协助测试的人员使用。",
+  "components.Settings.SettingsJobsCache.editJobSchedule": "编辑作业",
+  "components.Settings.SettingsJobsCache.jobScheduleEditFailed": "保存作业设置时出现问题。",
+  "components.Settings.validationUrl": "请输入有效的网址",
+  "components.UserProfile.UserSettings.UserGeneralSettings.validationDiscordId": "请输入有效的 Discord 用户 ID",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoverUserKey": "用户或群组令牌",
+  "components.UserProfile.UserSettings.UserNotificationSettings.pushoversettingssaved": "Pushover 通知设置保存成功!",
+  "components.UserProfile.UserSettings.UserNotificationSettings.validationPushoverUserKey": "请输入有效的用户或群组令牌",
+  "i18n.import": "导入",
+  "i18n.importing": "导入中…",
+  "components.RequestBlock.languageprofile": "语言配置文件",
+  "components.TitleCard.mediaerror": "未找到{mediaType}",
+  "components.MovieDetails.digitalrelease": "数字发行",
+  "components.MovieDetails.physicalrelease": "物理释放",
+  "components.MovieDetails.theatricalrelease": "剧场版",
+  "components.PermissionEdit.viewrecent": "查看最近添加的内容",
+  "components.PermissionEdit.viewrecentDescription": "授予查看最近添加的媒体列表的权限。",
+  "components.StatusChecker.appUpdated": "{applicationTitle} 已更新",
+  "components.StatusChecker.restartRequired": "需要重启服务器",
+  "components.StatusChecker.appUpdatedDescription": "请点击下面的按钮,重新加载应用程序。",
+  "components.StatusChecker.reloadApp": "重新加载 {applicationTitle}",
+  "i18n.restartRequired": "需要重新启动",
+  "components.Settings.deleteServer": "删除 {serverType} 服务器",
+  "components.StatusChecker.restartRequiredDescription": "请重新启动服务器以应用更新的设置。",
+  "components.RequestList.RequestItem.tmdbid": "TMDB ID",
+  "components.Discover.DiscoverWatchlist.watchlist": "Plex 关注列表",
+  "components.MovieDetails.managemovie": "管理电影",
+  "components.MovieDetails.reportissue": "报告问题",
+  "components.NotificationTypeSelector.mediaautorequested": "自动提交的请求",
+  "components.PermissionEdit.viewwatchlistsDescription": "授权查看其他用户的Plex关注列表。",
+  "components.RequestList.RequestItem.tvdbid": "TheTVDB ID",
+  "components.Settings.advancedTooltip": "错误配置此设置可能会导致功能不可用",
+  "components.Settings.experimentalTooltip": "启用此设置可能会导致意外的应用程序行为",
+  "components.TvDetails.reportissue": "报告问题",
+  "components.RequestCard.tmdbid": "TMDB ID",
+  "components.Settings.SettingsLogs.viewdetails": "查看详情",
+  "components.Layout.UserDropdown.requests": "请求",
+  "components.Settings.restartrequiredTooltip": "必须重新启动 Overseerr 才能使更改的设置生效",
+  "components.TvDetails.manageseries": "管理电视节目",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseriestip": "自动请求您的 <PlexWatchlistSupportLink>Plex 关注列表</PlexWatchlistSupportLink>的媒体",
+  "components.AirDateBadge.airedrelative": "播出{relativeTime}",
+  "components.AirDateBadge.airsrelative": "播出{relativeTime}",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.movierequests": "电影请求",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.seriesrequests": "电视节目请求",
+  "components.NotificationTypeSelector.mediaautorequestedDescription": "当 Plex 关注列表中的项目自动提交新媒体请求时,会收到通知。",
+  "components.PermissionEdit.viewwatchlists": "查看 Plex 关注列表",
+  "components.TvDetails.Season.somethingwentwrong": "在检索季元数据时出了问题。",
+  "components.UserProfile.plexwatchlist": "Plex 关注列表",
+  "components.RequestCard.tvdbid": "TheTVDB ID"
 }
diff --git a/src/i18n/locale/zh_Hant.json b/src/i18n/locale/zh_Hant.json
index 164f3010..b58c3408 100644
--- a/src/i18n/locale/zh_Hant.json
+++ b/src/i18n/locale/zh_Hant.json
@@ -20,7 +20,6 @@
   "components.Settings.Notifications.smtpHost": "SMTP 主機",
   "i18n.partiallyavailable": "部分可觀看",
   "i18n.unavailable": "不可觀看",
-  "components.StatusChacker.newversionavailable": "軟體更新",
   "components.StatusBadge.status4k": "4K 版{status}",
   "components.Setup.tip": "提示",
   "components.Setup.welcome": "歡迎來到 Overseerr",
@@ -58,7 +57,7 @@
   "components.UserList.creating": "創建中…",
   "components.UserList.createlocaluser": "建立本地使用者",
   "components.UserList.autogeneratepassword": "自動生成密碼",
-  "i18n.tvshows": "電視節目",
+  "i18n.tvshows": "影集",
   "pages.oops": "哎呀",
   "components.TvDetails.firstAirDate": "原始播出日期",
   "i18n.delete": "刪除",
@@ -118,7 +117,7 @@
   "components.MovieDetails.revenue": "收入",
   "components.MovieDetails.releasedate": "上映日期",
   "components.MovieDetails.recommendations": "推薦",
-  "components.Layout.Sidebar.dashboard": "發現",
+  "components.Layout.Sidebar.dashboard": "探索",
   "components.MovieDetails.overview": "概要",
   "components.MovieDetails.originallanguage": "原始語言",
   "components.MovieDetails.budget": "電影成本",
@@ -134,17 +133,17 @@
   "components.Layout.Sidebar.users": "使用者",
   "components.Layout.Sidebar.settings": "設定",
   "components.Layout.Sidebar.requests": "請求",
-  "components.Layout.SearchInput.searchPlaceholder": "搜尋電影、電視節目、人物…",
+  "components.Layout.SearchInput.searchPlaceholder": "搜尋電影、影集、人物…",
   "components.Discover.upcomingmovies": "即將上映的電影",
   "components.Discover.upcoming": "即將上映的電影",
   "components.Discover.trending": "趨勢",
-  "components.Discover.recentlyAdded": "最新新增",
+  "components.Discover.recentlyAdded": "最近新增",
   "components.Discover.recentrequests": "最新請求",
-  "components.Discover.populartv": "熱門電視節目",
+  "components.Discover.populartv": "熱門影集",
   "components.Discover.popularmovies": "熱門電影",
-  "components.Discover.discovertv": "熱門電視節目",
+  "components.Discover.discovertv": "熱門影集",
   "components.Discover.discovermovies": "熱門電影",
-  "components.CollectionDetails.requestcollection": "提出系列請求",
+  "components.CollectionDetails.requestcollection": "提出電影系列請求",
   "components.CollectionDetails.overview": "概要",
   "components.UserList.userdeleteerror": "刪除使用者時出了點問題。",
   "components.UserList.userdeleted": "使用者刪除成功!",
@@ -163,7 +162,6 @@
   "components.UserList.admin": "管理員",
   "components.Settings.SonarrModal.baseUrl": "網站根目錄",
   "components.Settings.RadarrModal.baseUrl": "網站根目錄",
-  "components.StatusChacker.reloadOverseerr": "刷新頁面",
   "components.Settings.notrunning": "未運行",
   "components.Settings.activeProfile": "目前的品質設定",
   "components.Settings.notificationsettings": "通知設定",
@@ -222,7 +220,7 @@
   "components.Settings.Notifications.NotificationsWebhook.resetPayloadSuccess": "JSON 有效負載重設為預設負載成功!",
   "components.Settings.Notifications.NotificationsPushover.validationUserTokenRequired": "請輸入有效的使用者或群組令牌",
   "components.Settings.menuJobs": "作業和快取",
-  "components.Settings.toastApiKeyFailure": "生成應用程式密鑰出了點問題。",
+  "components.Settings.toastApiKeyFailure": "生成應用程式密鑰時出了點問題。",
   "components.Settings.toastSettingsFailure": "儲存設定時出了點問題。",
   "components.UserList.deleteconfirm": "確定要刪除這個使用者嗎?此使用者的所有儲存資料將被清除。",
   "components.Settings.SettingsAbout.Releases.releasedataMissing": "無法獲取軟體版本資料。",
@@ -248,25 +246,23 @@
   "components.Settings.SettingsAbout.Releases.currentversion": "目前的版本",
   "components.Settings.SettingsAbout.timezone": "時區",
   "components.Settings.SettingsAbout.documentation": "使用說明",
-  "components.RequestModal.pending4krequest": "{title} 的 4K 請求",
-  "components.RequestModal.pendingrequest": "{title} 的請求",
+  "components.RequestModal.pending4krequest": "待處理的 4K 請求",
+  "components.RequestModal.pendingrequest": "待處理的請求",
   "components.RequestModal.extras": "特輯",
   "components.Settings.SettingsAbout.Releases.versionChangelog": "{version} 變更日誌",
   "components.Settings.SettingsAbout.Releases.releases": "軟體版本",
   "components.Settings.plexsettings": "Plex 設定",
   "components.RequestModal.selectseason": "請選擇季數",
-  "components.RequestModal.requesttitle": "為 {title} 提出請求",
   "components.RequestModal.requestseasons": "提出請求",
   "components.RequestModal.requestadmin": "此請求將自動獲批准。",
   "components.RequestModal.requestSuccess": "為 <strong>{title}</strong> 提出請求成功!",
   "components.RequestModal.requestCancel": "<strong>{title}</strong> 的請求已被取消。",
-  "components.RequestModal.request4ktitle": "為 {title} 提出 4K 請求",
   "components.PersonDetails.appearsin": "演出",
   "components.PersonDetails.ascharacter": "飾演 {character}",
   "components.TvDetails.overviewunavailable": "沒有概要。",
   "components.MovieDetails.overviewunavailable": "沒有概要。",
   "components.TvDetails.watchtrailer": "觀看預告片",
-  "components.TvDetails.showtype": "節目類型",
+  "components.TvDetails.showtype": "影集類型",
   "components.TvDetails.similar": "類似",
   "components.RequestModal.requestfrom": "{username} 的請求待處理。",
   "components.Settings.toastApiKeySuccess": "生成新應用程式密鑰成功!",
@@ -308,10 +304,9 @@
   "components.Settings.RadarrModal.editradarr": "編輯 Radarr 伺服器",
   "components.Settings.RadarrModal.defaultserver": "預設伺服器",
   "components.Settings.RadarrModal.add": "新增伺服器",
-  "components.StatusChacker.newversionDescription": "Overseerr 軟體已更新。請點擊以下的按鈕刷新頁面。",
   "components.RequestModal.requestcancelled": "<strong>{title}</strong> 的請求已被取消。",
   "components.RequestModal.AdvancedRequester.qualityprofile": "品質設定",
-  "components.RequestModal.AdvancedRequester.animenote": "※這是個動漫節目。",
+  "components.RequestModal.AdvancedRequester.animenote": "※這是個動漫影集。",
   "components.RequestModal.AdvancedRequester.advancedoptions": "進階選項",
   "components.RequestModal.AdvancedRequester.default": "{name}(預設)",
   "components.RequestModal.AdvancedRequester.destinationserver": "目標伺服器",
@@ -326,7 +321,7 @@
   "components.Settings.SonarrModal.toastSonarrTestFailure": "Sonarr 伺服器連線失敗。",
   "components.Settings.serverpreset": "伺服器",
   "components.RequestModal.autoapproval": "自動批准",
-  "components.PermissionEdit.autoapproveSeries": "電視節目自動批准",
+  "components.PermissionEdit.autoapproveSeries": "影集自動批准",
   "components.PermissionEdit.autoapproveMovies": "電影自動批准",
   "components.PermissionEdit.autoapprove": "自動批准",
   "components.PermissionEdit.admin": "管理員",
@@ -335,7 +330,7 @@
   "components.Settings.serverpresetRefreshing": "載入中…",
   "components.Settings.SonarrModal.syncEnabled": "啟用掃描",
   "components.UserList.userssaved": "使用者權限儲存成功!",
-  "components.Settings.hideAvailable": "隱藏可觀看的電影和電視節目",
+  "components.Settings.hideAvailable": "隱藏可觀看的電影和影集",
   "components.Settings.SonarrModal.externalUrl": "外部網址",
   "components.Settings.RadarrModal.externalUrl": "外部網址",
   "components.Settings.csrfProtection": "防止跨站請求偽造(CSRF)攻擊",
@@ -358,8 +353,7 @@
   "components.PlexLoginButton.signinwithplex": "登入",
   "components.PlexLoginButton.signingin": "登入中…",
   "components.PermissionEdit.users": "管理使用者",
-  "components.PermissionEdit.settings": "管理設定",
-  "components.PermissionEdit.request4kTv": "提出 4K 電視節目請求",
+  "components.PermissionEdit.request4kTv": "提出 4K 影集請求",
   "components.PermissionEdit.request4kMovies": "提出 4K 電影請求",
   "components.PermissionEdit.request4k": "提出 4K 請求",
   "components.PermissionEdit.request": "提出請求",
@@ -402,7 +396,7 @@
   "components.Settings.applicationTitle": "應用程式名稱",
   "components.Search.search": "搜尋",
   "components.Setup.setup": "設定",
-  "components.Discover.discover": "發現",
+  "components.Discover.discover": "探索",
   "components.AppDataWarning.dockerVolumeMissingDescription": "您必須使用繫結掛載(bind mount)來繫結主機上的目錄跟 Docker 容器內的 <code>{appDataPath}</code> 目錄,才能儲存 Overseerr 的設定和數據。",
   "components.RequestModal.AdvancedRequester.requestas": "請求者",
   "components.Settings.RadarrModal.validationApplicationUrlTrailingSlash": "請刪除結尾斜線",
@@ -438,7 +432,7 @@
   "components.NotificationTypeSelector.mediadeclinedDescription": "當請求拒被絕時發送通知。",
   "components.PermissionEdit.request4kDescription": "授予提出 4K 媒體請求的權限。",
   "components.PermissionEdit.request4kMoviesDescription": "授予提出 4K 電影請求的權限。",
-  "components.PermissionEdit.request4kTvDescription": "授予提出 4K 電視節目請求的權限。",
+  "components.PermissionEdit.request4kTvDescription": "授予提出 4K 影集請求的權限。",
   "components.PermissionEdit.requestDescription": "授予提出非 4K 媒體請求的權限。",
   "components.PermissionEdit.viewrequestsDescription": "授予查看其他使用者提出的媒體請求的權限。",
   "components.Settings.SonarrModal.validationLanguageProfileRequired": "請設定語言",
@@ -448,9 +442,8 @@
   "components.Settings.SonarrModal.languageprofile": "語言設定",
   "components.Settings.SonarrModal.animelanguageprofile": "動漫語言設定",
   "components.RequestModal.AdvancedRequester.languageprofile": "語言設定",
-  "components.PermissionEdit.settingsDescription": "授予管理全域設定的權限。",
   "components.PermissionEdit.usersDescription": "授予管理使用者的權限。有此權限的使用者不能編輯管理員或授予管理員權限。",
-  "components.PermissionEdit.autoapproveSeriesDescription": "自動批准非 4K 電視節目請求。",
+  "components.PermissionEdit.autoapproveSeriesDescription": "自動批准非 4K 影集請求。",
   "components.PermissionEdit.autoapproveMoviesDescription": "自動批准非 4K 電影請求。",
   "components.PermissionEdit.autoapproveDescription": "自動批准所有非 4K 媒體請求。",
   "components.PermissionEdit.advancedrequestDescription": "授予使用進階媒體請求選項的權限。",
@@ -463,8 +456,8 @@
   "components.UserList.sortCreated": "加入日期",
   "components.UserList.sortDisplayName": "顯示名稱",
   "components.UserList.sortRequests": "請求數",
-  "components.PermissionEdit.autoapprove4kSeriesDescription": "自動批准 4K 電視節目請求。",
-  "components.PermissionEdit.autoapprove4kSeries": "4K 電視節目自動批准",
+  "components.PermissionEdit.autoapprove4kSeriesDescription": "自動批准 4K 影集請求。",
+  "components.PermissionEdit.autoapprove4kSeries": "4K 影集自動批准",
   "components.PermissionEdit.autoapprove4kMoviesDescription": "自動批准 4K 電影請求。",
   "components.PermissionEdit.autoapprove4kMovies": "4K 電影自動批准",
   "components.PermissionEdit.autoapprove4kDescription": "自動批准所有 4K 媒體請求。",
@@ -506,22 +499,21 @@
   "components.UserProfile.UserSettings.UserPasswordChange.validationCurrentPassword": "請輸入當前的密碼",
   "components.UserProfile.UserSettings.UserPasswordChange.validationNewPassword": "請輸入新密碼",
   "components.UserProfile.UserSettings.UserPasswordChange.toastSettingsSuccess": "密碼設定成功!",
-  "components.RequestModal.SearchByNameModal.nosummary": "沒有概要。",
   "components.UserProfile.UserSettings.UserNotificationSettings.validationDiscordId": "請輸入有效的使用者 ID",
   "components.UserProfile.UserSettings.UserNotificationSettings.discordIdTip": "您的<FindDiscordIdLink>使用者 ID 號碼</FindDiscordIdLink>",
   "components.UserProfile.UserSettings.UserPasswordChange.toastSettingsFailure": "重設密碼時出了點問題。",
-  "components.RequestModal.SearchByNameModal.notvdbiddescription": "無法自動配對您的請求。請從以下列表中選擇正確的媒體項。",
-  "components.CollectionDetails.requestcollection4k": "提出 4K 系列請求",
-  "components.Settings.trustProxyTip": "使用代理伺服器時,允許 Overseerr 註冊客戶端的正確 IP 位址(Overseerr 必須重新啟動)",
-  "components.Settings.csrfProtectionTip": "設定外部訪問權限為只讀(Overseerr 必須重新啟動)",
+  "components.RequestModal.SearchByNameModal.notvdbiddescription": "無法自動配對此影集的數據。 請在以下選擇正確的媒體項。",
+  "components.CollectionDetails.requestcollection4k": "提出 4K 電影系列請求",
+  "components.Settings.trustProxyTip": "使用代理伺服器時,允許 Overseerr 註冊客戶端的正確 IP 位址",
+  "components.Settings.csrfProtectionTip": "設定外部訪問權限為只讀(需要 HTTPS)",
   "components.ResetPassword.requestresetlinksuccessmessage": "通過電子郵件發送了密碼重設鏈接。",
   "components.ResetPassword.resetpasswordsuccessmessage": "密碼重設成功!",
   "components.RegionSelector.regionDefault": "所有地區",
-  "components.UserProfile.UserSettings.UserGeneralSettings.region": "「發現」地區",
-  "components.Settings.region": "「發現」地區",
-  "components.UserProfile.UserSettings.UserGeneralSettings.originallanguage": "「發現」語言",
-  "components.Settings.originallanguage": "「發現」語言",
-  "components.Discover.upcomingtv": "即將上映的電視節目",
+  "components.UserProfile.UserSettings.UserGeneralSettings.region": "「探索」地區",
+  "components.Settings.region": "「探索」地區",
+  "components.UserProfile.UserSettings.UserGeneralSettings.originallanguage": "「探索」語言",
+  "components.Settings.originallanguage": "「探索」語言",
+  "components.Discover.upcomingtv": "即將上映的影集",
   "components.Settings.webhook": "Webhook",
   "components.Settings.email": "電子郵件",
   "components.Settings.generalsettingsDescription": "Overseerr 的全域和預設設定。",
@@ -532,7 +524,7 @@
   "components.Settings.originallanguageTip": "以原始語言篩選結果",
   "components.Settings.SettingsJobsCache.jobsDescription": "Overseerr 將定時運行以下的維護任務。手動執行工作不會影響它正常的行程。",
   "components.Settings.plexsettingsDescription": "關於 Plex 伺服器的設定。Overseerr 將定時執行媒體庫掃描。",
-  "components.Settings.manualscanDescription": "在正常情況下,Overseerr 會每24小時掃描您的 Plex 媒體庫。最新新增的媒體將更頻繁掃描。設定新的 Plex 伺服器時,我們建議您執行一次手動掃描!",
+  "components.Settings.manualscanDescription": "在正常情況下,Overseerr 會每24小時掃描您的 Plex 媒體庫。最近新增的媒體將更頻繁掃描。設定新的 Plex 伺服器時,我們建議您執行一次手動掃描!",
   "components.RegionSelector.regionServerDefault": "預設設定({region})",
   "components.Settings.settingUpPlexDescription": "您可以手動輸入您的 Plex 伺服器資料,或從 <RegisterPlexTVLink>plex.tv</RegisterPlexTVLink> 返回的數據做選擇。請點下拉式選單右邊的按鈕獲取伺服器列表。",
   "components.Settings.plexlibrariesDescription": "Overseerr 將掃描的媒體庫。",
@@ -548,8 +540,8 @@
   "components.Settings.SettingsJobsCache.download-sync": "下載狀態同步",
   "components.Settings.SettingsJobsCache.unknownJob": "未知作業",
   "components.TvDetails.seasons": "{seasonCount} 季",
-  "components.Discover.DiscoverTvGenre.genreSeries": "{genre}電視節目",
-  "components.Discover.DiscoverNetwork.networkSeries": "{network} 電視節目",
+  "components.Discover.DiscoverTvGenre.genreSeries": "{genre}影集",
+  "components.Discover.DiscoverNetwork.networkSeries": "{network} 影集",
   "components.Discover.DiscoverStudio.studioMovies": "{studio} 電影",
   "components.Discover.DiscoverMovieGenre.genreMovies": "{genre}電影",
   "i18n.loading": "載入中…",
@@ -571,9 +563,9 @@
   "components.Settings.scan": "媒體庫同步",
   "components.Settings.SettingsJobsCache.sonarr-scan": "Sonarr 掃描",
   "components.Settings.SettingsJobsCache.radarr-scan": "Radarr 掃描",
-  "components.Settings.SettingsJobsCache.plex-recently-added-scan": "Plex 最新新增掃描",
+  "components.Settings.SettingsJobsCache.plex-recently-added-scan": "Plex 最近新增掃描",
   "components.Settings.SettingsJobsCache.plex-full-scan": "Plex 媒體庫掃描",
-  "components.Discover.DiscoverTvLanguage.languageSeries": "{language}電視節目",
+  "components.Discover.DiscoverTvLanguage.languageSeries": "{language}影集",
   "components.Discover.DiscoverMovieLanguage.languageMovies": "{language}電影",
   "components.UserProfile.ProfileHeader.userid": "使用者 ID:{userid}",
   "components.UserProfile.ProfileHeader.joindate": "加入日期:{joindate}",
@@ -590,17 +582,16 @@
   "components.UserProfile.UserSettings.unauthorizedDescription": "您無權編輯此使用者的設定。",
   "components.Settings.Notifications.pgpPrivateKeyTip": "使用 <OpenPgpLink>OpenPGP</OpenPgpLink> 電子郵件加密與簽章",
   "components.Settings.Notifications.pgpPasswordTip": "使用 <OpenPgpLink>OpenPGP</OpenPgpLink> 電子郵件加密與簽章",
-  "components.UserProfile.norequests": "沒有請求。",
   "components.Settings.Notifications.pgpPassword": "PGP 解密密碼",
   "components.Settings.Notifications.pgpPrivateKey": "PGP 私鑰",
   "components.TvDetails.episodeRuntime": "劇集片長",
   "components.TvDetails.episodeRuntimeMinutes": "{runtime} 分鐘",
   "components.RequestModal.AdvancedRequester.folder": "{path}({space})",
-  "components.Discover.TvGenreSlider.tvgenres": "電視節目類型",
+  "components.Discover.TvGenreSlider.tvgenres": "影集類型",
   "components.Discover.MovieGenreSlider.moviegenres": "電影類型",
   "components.Discover.MovieGenreList.moviegenres": "電影類型",
-  "components.Discover.TvGenreList.seriesgenres": "電視節目類型",
-  "components.Settings.partialRequestsEnabled": "允許不完整的電視節目請求",
+  "components.Discover.TvGenreList.seriesgenres": "影集類型",
+  "components.Settings.partialRequestsEnabled": "允許不完整的影集請求",
   "components.RequestModal.alreadyrequested": "已經有請求",
   "components.Settings.SettingsLogs.time": "時間戳",
   "components.Settings.SettingsLogs.resumeLogs": "恢復",
@@ -632,9 +623,9 @@
   "components.Settings.SettingsLogs.message": "訊息",
   "components.Settings.SettingsJobsCache.jobsandcache": "作業和快取",
   "components.Settings.SettingsAbout.about": "關於 Overseerr",
-  "components.Settings.cacheImages": "啟用圖像緩存",
+  "components.Settings.cacheImages": "啟用圖像檔案快取",
   "components.Settings.SettingsLogs.logsDescription": "您也能直接查看 <code>stdout</code> 數據流或位置於 <code>{appDataPath}/logs/overseerr.log</code> 的日誌檔案。",
-  "components.Settings.cacheImagesTip": "把所有的圖像優化和儲存到快取記憶體(需要大量的磁碟空間)",
+  "components.Settings.cacheImagesTip": "處理和提供優化的圖像檔案(需要大量的磁碟空間)",
   "components.Settings.SettingsLogs.logDetails": "日誌詳細信息",
   "components.Settings.SettingsLogs.extraData": "附加數據",
   "components.Settings.SettingsLogs.copyToClipboard": "複製到剪貼板",
@@ -645,16 +636,16 @@
   "components.PersonDetails.lifespan": "{birthdate}-{deathdate}",
   "components.PersonDetails.alsoknownas": "別名:{names}",
   "i18n.delimitedlist": "{a}、{b}",
-  "components.Settings.SettingsUsers.tvRequestLimitLabel": "電視節目請求全域限制",
+  "components.Settings.SettingsUsers.tvRequestLimitLabel": "影集請求全域限制",
   "components.Settings.SettingsUsers.movieRequestLimitLabel": "電影請求全域限制",
   "components.RequestModal.QuotaDisplay.seasonlimit": "季數",
-  "components.RequestModal.QuotaDisplay.season": "電視節目季數",
+  "components.RequestModal.QuotaDisplay.season": "影集季數",
   "components.RequestModal.QuotaDisplay.requestsremaining": "{remaining, plural, =0 {電影請求剩餘數不足} other {剩餘 <strong>#</strong> 個{type}請求}}",
   "components.RequestModal.QuotaDisplay.notenoughseasonrequests": "請求剩餘數不足",
   "components.RequestModal.QuotaDisplay.movielimit": "電影",
   "components.RequestModal.QuotaDisplay.allowedRequestsUser": "此使用者每 <strong>{days}</strong> 天能提出 <strong>{limit}</strong> 個{type}請求。",
   "components.RequestModal.QuotaDisplay.allowedRequests": "您每 <strong>{days}</strong> 天能提出 <strong>{limit}</strong> 個{type}請求。",
-  "components.UserProfile.UserSettings.UserGeneralSettings.seriesrequestlimit": "電視節目請求限制",
+  "components.UserProfile.UserSettings.UserGeneralSettings.seriesrequestlimit": "影集請求限制",
   "components.UserProfile.UserSettings.UserGeneralSettings.movierequestlimit": "電影請求限制",
   "components.UserProfile.movierequests": "電影請求",
   "components.UserProfile.limit": "{limit} 之 {remaining}",
@@ -665,15 +656,15 @@
   "components.UserProfile.UserSettings.UserGeneralSettings.enableOverride": "覆寫全域限制",
   "components.UserProfile.unlimited": "無限",
   "components.UserProfile.totalrequests": "請求總數",
-  "components.UserProfile.seriesrequest": "電視節目請求",
+  "components.UserProfile.seriesrequest": "影集請求",
   "i18n.view": "檢視",
-  "i18n.tvshow": "電視節目",
+  "i18n.tvshow": "影集",
   "i18n.testing": "測試中…",
   "i18n.test": "測試",
   "i18n.status": "狀態",
   "i18n.showingresults": "<strong>{from}</strong>-<strong>{to}</strong> 列(共 <strong>{total}</strong> 列)",
   "i18n.saving": "儲存中…",
-  "i18n.save": "儲存",
+  "i18n.save": "儲存變更",
   "i18n.resultsperpage": "每頁顯示 {pageSize} 列",
   "i18n.requesting": "提出請求中…",
   "i18n.request4k": "提出 4K 請求",
@@ -686,8 +677,8 @@
   "i18n.back": "返回",
   "i18n.all": "所有",
   "i18n.areyousure": "確定嗎?",
-  "components.RequestModal.QuotaDisplay.requiredquotaUser": "此使用者的電視節目請求數量必須至少剩餘 <strong>{seasons}</strong> 個季數才能提出此節目請求。",
-  "components.RequestModal.QuotaDisplay.requiredquota": "您的電視節目請求數量必須至少剩餘 <strong>{seasons}</strong> 個季數才能提出此節目請求。",
+  "components.RequestModal.QuotaDisplay.requiredquotaUser": "此使用者的影集請求數量必須至少剩餘 <strong>{seasons}</strong> 個季數才能提出此影集請求。",
+  "components.RequestModal.QuotaDisplay.requiredquota": "您的影集請求數量必須至少剩餘 <strong>{seasons}</strong> 個季數才能提出此影集請求。",
   "components.TvDetails.originaltitle": "原始標題",
   "components.MovieDetails.originaltitle": "原始標題",
   "components.RequestModal.QuotaDisplay.quotaLinkUser": "訪問此使用者的<ProfileLink>個人資料頁面</ProfileLink>以查看使用者的請求限制 。",
@@ -714,8 +705,8 @@
   "components.Settings.RadarrModal.tags": "標籤",
   "components.RequestModal.AdvancedRequester.tags": "標籤",
   "components.Settings.RadarrModal.loadingTags": "載入中…",
-  "components.RequestList.RequestItem.mediaerror": "找不到此請求的媒體項目。",
-  "components.RequestCard.mediaerror": "找不到此請求的媒體項目。",
+  "components.RequestList.RequestItem.mediaerror": "找不到{mediaType}",
+  "components.RequestCard.mediaerror": "找不到{mediaType}",
   "components.RequestList.RequestItem.deleterequest": "刪除請求",
   "components.RequestCard.deleterequest": "刪除請求",
   "components.Settings.Notifications.botUsernameTip": "允許使用者也把機器人加到自己的聊天室以及設定自己的通知",
@@ -734,7 +725,6 @@
   "components.UserProfile.UserSettings.UserNotificationSettings.pgpPublicKey": "PGP 公鑰",
   "components.RequestList.RequestItem.cancelRequest": "取消請求",
   "components.NotificationTypeSelector.notificationTypes": "通知類型",
-  "components.Discover.noRequests": "沒有請求。",
   "components.Layout.VersionStatus.commitsbehind": "落後 {commitsBehind} 個提交",
   "components.Layout.VersionStatus.outofdate": "非最新版本",
   "components.Layout.VersionStatus.streamstable": "Overseerr 穩定版",
@@ -744,7 +734,7 @@
   "components.Settings.noDefaultNon4kServer": "如果您只有一個 {serverType} 伺服器,請勿把它設定為 4K 伺服器。",
   "components.Settings.noDefaultServer": "您必須至少指定一個預設 {serverType} 伺服器,才能處理{mediaType}請求。",
   "components.Settings.serviceSettingsDescription": "關於 {serverType} 伺服器的設定。{serverType} 伺服器數沒有最大值限制,但您只能指定兩個預設伺服器(一個非 4K、一個 4K)。",
-  "components.Settings.mediaTypeSeries": "電視節目",
+  "components.Settings.mediaTypeSeries": "影集",
   "components.Settings.mediaTypeMovie": "電影",
   "components.UserProfile.UserSettings.UserPasswordChange.noPasswordSet": "此使用者的帳戶目前沒有設密碼。若在以下設定密碼,此使用者就能使用「本地登入」。",
   "components.UserProfile.UserSettings.UserPasswordChange.noPasswordSetOwnAccount": "您的帳戶目前沒有設密碼。若在以下設定密碼,您就能使用「本地登入」。",
@@ -802,10 +792,10 @@
   "components.Settings.Notifications.NotificationsWebhook.toastWebhookTestSuccess": "Webhook 測試通知已發送!",
   "components.Settings.SettingsUsers.newPlexLoginTip": "讓還沒匯入的 Plex 使用者登入",
   "components.Settings.SettingsUsers.newPlexLogin": "允許新的 Plex 登入",
-  "components.PermissionEdit.requestTv": "提出電視節目請求",
+  "components.PermissionEdit.requestTv": "提出影集請求",
   "components.PermissionEdit.requestMovies": "提出電影請求",
   "components.PermissionEdit.requestMoviesDescription": "授予提出非 4K 電影請求的權限。",
-  "components.PermissionEdit.requestTvDescription": "授予提出非 4K 電視節目請求的權限。",
+  "components.PermissionEdit.requestTvDescription": "授予提出非 4K 影集請求的權限。",
   "components.UserProfile.UserSettings.UserGeneralSettings.languageDefault": "預設設定({language})",
   "components.Settings.locale": "顯示語言",
   "components.DownloadBlock.estimatedtime": "預計:{time}",
@@ -857,7 +847,7 @@
   "components.MovieDetails.streamingproviders": "目前的流媒體服務",
   "components.Settings.SettingsJobsCache.editJobSchedule": "編輯作業",
   "components.Settings.SettingsJobsCache.editJobScheduleSelectorHours": "每 {jobScheduleHours} 小時",
-  "components.Settings.SettingsJobsCache.editJobSchedulePrompt": "頻率",
+  "components.Settings.SettingsJobsCache.editJobSchedulePrompt": "新的頻率",
   "components.Settings.SettingsJobsCache.editJobScheduleSelectorMinutes": "每 {jobScheduleMinutes} 分鐘",
   "components.Settings.SettingsJobsCache.jobScheduleEditFailed": "儲存作業設定時出了點問題。",
   "components.Settings.SettingsJobsCache.jobScheduleEditSaved": "作業編輯成功!",
@@ -889,16 +879,16 @@
   "components.ManageSlideOver.manageModalNoRequests": "沒有請求。",
   "components.ManageSlideOver.openarr": "開啟 {arr} 伺服器",
   "components.ManageSlideOver.openarr4k": "開啟 4K {arr} 伺服器",
-  "components.ManageSlideOver.movie": "部電影",
+  "components.ManageSlideOver.movie": "電影",
   "components.ManageSlideOver.markavailable": "標記為可觀看",
   "components.IssueModal.issueAudio": "音訊",
   "components.ManageSlideOver.downloadstatus": "下載狀態",
   "components.IssueModal.CreateIssueModal.allepisodes": "所有集數",
-  "components.ManageSlideOver.manageModalClearMediaWarning": "※這將會刪除包括使用者請求在內所有有關這{mediaType}的資料。如果這{mediaType}存在於您的 Plex 伺服器,資料將會在媒體庫掃描時重新建立。",
+  "components.ManageSlideOver.manageModalClearMediaWarning": "※這將會刪除包括使用者請求在內所有有關此{mediaType}的資料。如果這{mediaType}存在於您的 Plex 伺服器,資料將會在媒體庫掃描時重新建立。",
   "components.ManageSlideOver.mark4kavailable": "標記 4K 版為可觀看",
   "components.IssueModal.issueSubtitles": "字幕",
   "components.IssueModal.issueOther": "其他",
-  "components.ManageSlideOver.tvshow": "個電視節目",
+  "components.ManageSlideOver.tvshow": "影集",
   "components.ManageSlideOver.manageModalTitle": "管理{mediaType}",
   "components.IssueModal.issueVideo": "影片",
   "components.IssueList.IssueItem.issuetype": "類型",
@@ -919,7 +909,6 @@
   "components.IssueDetails.toaststatusupdated": "問題狀態編輯成功!",
   "components.IssueDetails.toastissuedeletefailed": "刪除問題狀態時出了點問題。",
   "components.IssueList.IssueItem.openeduserdate": "{user}({date})",
-  "components.IssueModal.CreateIssueModal.issomethingwrong": "{title} 有問題嗎?",
   "components.IssueModal.CreateIssueModal.providedetail": "請詳細解釋您遇到的問題。",
   "components.IssueModal.CreateIssueModal.submitissue": "報告問題",
   "components.IssueModal.CreateIssueModal.toastFailedCreate": "提出問題報告時出了點問題。",
@@ -1040,5 +1029,93 @@
   "components.UserProfile.UserSettings.UserGeneralSettings.discordId": "Discord 使用者 ID",
   "components.UserProfile.UserSettings.UserGeneralSettings.discordIdTip": "您的<FindDiscordIdLink>Discord 使用者 ID 號碼</FindDiscordIdLink>",
   "components.UserProfile.UserSettings.UserGeneralSettings.validationDiscordId": "請輸入有效的 Discord 使用者 ID",
-  "components.Settings.SettingsAbout.appDataPath": "數據目錄"
+  "components.Settings.SettingsAbout.appDataPath": "數據目錄",
+  "components.RequestBlock.languageprofile": "語言設定",
+  "components.StatusChecker.appUpdated": "{applicationTitle} 軟體已更新",
+  "components.StatusChecker.reloadApp": "刷新頁面",
+  "components.StatusChecker.restartRequired": "必須重新啟動伺服器",
+  "i18n.restartRequired": "必須重新啟動伺服器",
+  "components.Settings.deleteServer": "刪除 {serverType} 伺服器",
+  "components.StatusChecker.appUpdatedDescription": "請點擊以下的按鈕刷新頁面。",
+  "components.StatusChecker.restartRequiredDescription": "請重新啟動伺服器以應用設定的變更。",
+  "components.MovieDetails.physicalrelease": "實體光碟",
+  "components.MovieDetails.theatricalrelease": "影院",
+  "components.MovieDetails.digitalrelease": "數字版本",
+  "components.PermissionEdit.viewrecent": "查看最近新增",
+  "components.PermissionEdit.viewrecentDescription": "授予查看最近新增的媒體的權限。",
+  "components.RequestList.RequestItem.tmdbid": "TMDB ID",
+  "components.TitleCard.mediaerror": "找不到{mediaType}",
+  "components.TitleCard.tvdbid": "TheTVDB ID",
+  "components.RequestCard.tvdbid": "TheTVDB ID",
+  "components.TitleCard.cleardata": "清除儲存資料",
+  "components.TitleCard.tmdbid": "TMDB ID",
+  "components.RequestCard.tmdbid": "TMDB ID",
+  "components.RequestList.RequestItem.tvdbid": "TheTVDB ID",
+  "components.Discover.plexwatchlist": "您的 Plex 關注列表",
+  "components.PermissionEdit.autorequestMovies": "自動提出電影請求",
+  "components.PermissionEdit.autorequestSeries": "自動提出影集請求",
+  "components.Settings.SettingsJobsCache.plex-watchlist-sync": "Plex 關注列表同步",
+  "components.PermissionEdit.autorequest": "自動提出請求",
+  "components.Discover.DiscoverWatchlist.discoverwatchlist": "您的 Plex 關注列表",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmovies": "自動提出電影請求",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseries": "自動提出影集請求",
+  "components.NotificationTypeSelector.mediaautorequested": "請求自動提出",
+  "components.PermissionEdit.autorequestMoviesDescription": "授予從 Plex 關注列表中自動提出非 4K 電影請求的權限。",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncmoviestip": "從您的 <PlexWatchlistSupportLink>Plex 關注列表</PlexWatchlistSupportLink>中自動提出電影請求",
+  "components.NotificationTypeSelector.mediaautorequestedDescription": "當您的 Plex 關注列表中的媒體自動提出請求時取得通知。",
+  "components.PermissionEdit.autorequestDescription": "授予從 Plex 關注列表中自動提出非 4K 媒體請求的權限。",
+  "components.PermissionEdit.autorequestSeriesDescription": "授予從 Plex 關注列表中自動提出非 4K 影集請求的權限。",
+  "components.UserProfile.UserSettings.UserGeneralSettings.plexwatchlistsyncseriestip": "從您的 <PlexWatchlistSupportLink>Plex 關注列表</PlexWatchlistSupportLink>中自動提出影集請求",
+  "components.Settings.SettingsLogs.viewdetails": "查看詳細信息",
+  "components.TvDetails.reportissue": "報告問題",
+  "components.MovieDetails.managemovie": "管理電影",
+  "components.Discover.DiscoverWatchlist.watchlist": "Plex 關注列表",
+  "components.UserProfile.plexwatchlist": "Plex 關注列表",
+  "components.MovieDetails.reportissue": "報告問題",
+  "components.PermissionEdit.viewwatchlists": "查看 Plex 關注列表",
+  "components.PermissionEdit.viewwatchlistsDescription": "授予查看其他使用者的 Plex 關注列表的權限。",
+  "components.TvDetails.manageseries": "管理影集",
+  "components.Settings.restartrequiredTooltip": "Overseerr 必須重新啟動才能應用設定的變更",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.movierequests": "電影請求",
+  "components.Layout.UserDropdown.MiniQuotaDisplay.seriesrequests": "影集請求",
+  "components.Layout.UserDropdown.requests": "請求",
+  "components.TvDetails.seasonstitle": "季數",
+  "components.RequestBlock.decline": "拒絕請求",
+  "components.RequestBlock.edit": "編輯請求",
+  "components.RequestBlock.lastmodifiedby": "最後修改者",
+  "components.RequestBlock.requestdate": "請求日期",
+  "components.RequestCard.approverequest": "批准請求",
+  "components.RequestCard.cancelrequest": "取消請求",
+  "components.RequestCard.declinerequest": "拒絕請求",
+  "components.TvDetails.seasonnumber": "第 {seasonNumber} 季",
+  "components.RequestBlock.approve": "批准請求",
+  "components.RequestBlock.delete": "刪除請求",
+  "components.RequestCard.editrequest": "編輯請求",
+  "components.RequestBlock.requestedby": "請求者",
+  "components.StatusBadge.playonplex": "在 Plex 上觀看",
+  "components.StatusBadge.managemedia": "管理{mediaType}",
+  "components.StatusBadge.openinarr": "開啟 {arr} 伺服器",
+  "components.TvDetails.status4k": "4K 版{status}",
+  "components.TvDetails.episodeCount": "{episodeCount} 集",
+  "components.AirDateBadge.airedrelative": "{relativeTime}播出",
+  "components.MovieDetails.rtaudiencescore": "爛番茄觀眾評分",
+  "components.TvDetails.Season.somethingwentwrong": "檢索數據時出了點問題。",
+  "components.TvDetails.tmdbuserscore": "TMDB 使用者評分",
+  "components.TvDetails.rtcriticsscore": "爛番茄專業評分",
+  "components.AirDateBadge.airsrelative": "{relativeTime}播出",
+  "components.MovieDetails.tmdbuserscore": "TMDB 使用者評分",
+  "components.MovieDetails.rtcriticsscore": "爛番茄專業評分",
+  "components.TvDetails.rtaudiencescore": "爛番茄觀眾評分",
+  "components.RequestModal.requestmovietitle": "提出電影請求",
+  "components.RequestModal.requestmovie4ktitle": "提出 4K 電影請求",
+  "components.RequestModal.requestcollection4ktitle": "提出 4K 電影系列請求",
+  "components.RequestModal.requestseriestitle": "提出影集請求",
+  "components.RequestModal.requestseries4ktitle": "提出 4K 影集請求",
+  "components.RequestModal.requestcollectiontitle": "提出電影系列請求",
+  "components.RequestModal.SearchByNameModal.nomatches": "找不到此影集的數據。",
+  "components.UserProfile.emptywatchlist": "您的 <PlexWatchlistSupportLink>Plex 關注列表</PlexWatchlistSupportLink>中的媒體會顯示在這裡。",
+  "components.Discover.emptywatchlist": "您的 <PlexWatchlistSupportLink>Plex 關注列表</PlexWatchlistSupportLink>中的媒體會顯示在這裡。",
+  "components.Settings.advancedTooltip": "錯誤的設定可能會破壞應用程式功能",
+  "components.Settings.experimentalTooltip": "啟用此設定可能會出現意外的應用程式行為",
+  "components.Settings.SettingsJobsCache.editJobScheduleCurrent": "目前的頻率"
 }
diff --git a/src/pages/404.tsx b/src/pages/404.tsx
index f4589467..3df55fc1 100644
--- a/src/pages/404.tsx
+++ b/src/pages/404.tsx
@@ -1,8 +1,7 @@
+import PageTitle from '@app/components/Common/PageTitle';
 import { ArrowCircleRightIcon } from '@heroicons/react/outline';
 import Link from 'next/link';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
-import PageTitle from '../components/Common/PageTitle';
 
 const messages = defineMessages({
   errormessagewithcode: '{statusCode} - {error}',
@@ -10,7 +9,7 @@ const messages = defineMessages({
   returnHome: 'Return Home',
 });
 
-const Custom404: React.FC = () => {
+const Custom404 = () => {
   const intl = useIntl();
 
   return (
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx
index dd6c3e97..d467e61b 100644
--- a/src/pages/_app.tsx
+++ b/src/pages/_app.tsx
@@ -1,28 +1,33 @@
+import Layout from '@app/components/Layout';
+import LoadingBar from '@app/components/LoadingBar';
+import PWAHeader from '@app/components/PWAHeader';
+import ServiceWorkerSetup from '@app/components/ServiceWorkerSetup';
+import StatusChecker from '@app/components/StatusChecker';
+import Toast from '@app/components/Toast';
+import ToastContainer from '@app/components/ToastContainer';
+import { InteractionProvider } from '@app/context/InteractionContext';
+import type { AvailableLocale } from '@app/context/LanguageContext';
+import { LanguageContext } from '@app/context/LanguageContext';
+import { SettingsProvider } from '@app/context/SettingsContext';
+import { UserContext } from '@app/context/UserContext';
+import type { User } from '@app/hooks/useUser';
+import '@app/styles/globals.css';
+import { polyfillIntl } from '@app/utils/polyfillIntl';
+import type { PublicSettingsResponse } from '@server/interfaces/api/settingsInterfaces';
 import axios from 'axios';
-import App, { AppInitialProps, AppProps } from 'next/app';
+import type { AppInitialProps, AppProps } from 'next/app';
+import App from 'next/app';
 import Head from 'next/head';
-import React, { useEffect, useState } from 'react';
+import { useEffect, useState } from 'react';
 import { IntlProvider } from 'react-intl';
 import { ToastProvider } from 'react-toast-notifications';
 import { SWRConfig } from 'swr';
-import { PublicSettingsResponse } from '../../server/interfaces/api/settingsInterfaces';
-import Layout from '../components/Layout';
-import LoadingBar from '../components/LoadingBar';
-import PWAHeader from '../components/PWAHeader';
-import ServiceWorkerSetup from '../components/ServiceWorkerSetup';
-import StatusChecker from '../components/StatusChacker';
-import Toast from '../components/Toast';
-import ToastContainer from '../components/ToastContainer';
-import { InteractionProvider } from '../context/InteractionContext';
-import { AvailableLocale, LanguageContext } from '../context/LanguageContext';
-import { SettingsProvider } from '../context/SettingsContext';
-import { UserContext } from '../context/UserContext';
-import { User } from '../hooks/useUser';
-import '../styles/globals.css';
 
 // eslint-disable-next-line @typescript-eslint/no-explicit-any
 const loadLocaleData = (locale: AvailableLocale): Promise<any> => {
   switch (locale) {
+    case 'ar':
+      return import('../i18n/locale/ar.json');
     case 'ca':
       return import('../i18n/locale/ca.json');
     case 'cs':
@@ -37,12 +42,14 @@ const loadLocaleData = (locale: AvailableLocale): Promise<any> => {
       return import('../i18n/locale/es.json');
     case 'fr':
       return import('../i18n/locale/fr.json');
+    case 'hu':
+      return import('../i18n/locale/hu.json');
     case 'it':
       return import('../i18n/locale/it.json');
     case 'ja':
       return import('../i18n/locale/ja.json');
-    case 'hu':
-      return import('../i18n/locale/hu.json');
+    case 'lt':
+      return import('../i18n/locale/lt.json');
     case 'nb-NO':
       return import('../i18n/locale/nb_NO.json');
     case 'nl':
@@ -118,6 +125,9 @@ const CoreApp: Omit<NextAppComponentType, 'origGetInitialProps'> = ({
     <SWRConfig
       value={{
         fetcher: (url) => axios.get(url).then((res) => res.data),
+        fallback: {
+          '/api/v1/auth/me': user,
+        },
       }}
     >
       <LanguageContext.Provider value={{ locale: currentLocale, setLocale }}>
@@ -235,6 +245,7 @@ CoreApp.getInitialProps = async (initialProps) => {
     : currentSettings.locale;
 
   const messages = await loadLocaleData(locale as AvailableLocale);
+  await polyfillIntl(locale);
 
   return { ...appInitialProps, user, messages, locale, currentSettings };
 };
diff --git a/src/pages/_document.tsx b/src/pages/_document.tsx
index 9cd04471..32df8a3b 100644
--- a/src/pages/_document.tsx
+++ b/src/pages/_document.tsx
@@ -1,12 +1,5 @@
-import Document, {
-  DocumentContext,
-  DocumentInitialProps,
-  Head,
-  Html,
-  Main,
-  NextScript,
-} from 'next/document';
-import React from 'react';
+import type { DocumentContext, DocumentInitialProps } from 'next/document';
+import Document, { Head, Html, Main, NextScript } from 'next/document';
 
 class MyDocument extends Document {
   static async getInitialProps(
diff --git a/src/pages/_error.tsx b/src/pages/_error.tsx
index 0241bf7f..2d5102c4 100644
--- a/src/pages/_error.tsx
+++ b/src/pages/_error.tsx
@@ -1,10 +1,9 @@
+import PageTitle from '@app/components/Common/PageTitle';
+import type { Undefinable } from '@app/utils/typeHelpers';
 import { ArrowCircleRightIcon } from '@heroicons/react/outline';
 import type { NextPage } from 'next';
 import Link from 'next/link';
-import React from 'react';
 import { defineMessages, useIntl } from 'react-intl';
-import PageTitle from '../components/Common/PageTitle';
-import type { Undefinable } from '../utils/typeHelpers';
 
 interface ErrorProps {
   statusCode?: number;
diff --git a/src/pages/collection/[collectionId]/index.tsx b/src/pages/collection/[collectionId]/index.tsx
index 82214aa8..5802577b 100644
--- a/src/pages/collection/[collectionId]/index.tsx
+++ b/src/pages/collection/[collectionId]/index.tsx
@@ -1,8 +1,7 @@
+import CollectionDetails from '@app/components/CollectionDetails';
+import type { Collection } from '@server/models/Collection';
 import axios from 'axios';
-import { GetServerSideProps, NextPage } from 'next';
-import React from 'react';
-import type { Collection } from '../../../../server/models/Collection';
-import CollectionDetails from '../../../components/CollectionDetails';
+import type { GetServerSideProps, NextPage } from 'next';
 
 interface CollectionPageProps {
   collection?: Collection;
diff --git a/src/pages/discover/movies/genre/[genreId]/index.tsx b/src/pages/discover/movies/genre/[genreId]/index.tsx
index 71fd2b01..3bbb960c 100644
--- a/src/pages/discover/movies/genre/[genreId]/index.tsx
+++ b/src/pages/discover/movies/genre/[genreId]/index.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import { NextPage } from 'next';
-import DiscoverMovieGenre from '../../../../../components/Discover/DiscoverMovieGenre';
+import DiscoverMovieGenre from '@app/components/Discover/DiscoverMovieGenre';
+import type { NextPage } from 'next';
 
 const DiscoverMoviesGenrePage: NextPage = () => {
   return <DiscoverMovieGenre />;
diff --git a/src/pages/discover/movies/genres.tsx b/src/pages/discover/movies/genres.tsx
index 13a4cfe8..fdf4a252 100644
--- a/src/pages/discover/movies/genres.tsx
+++ b/src/pages/discover/movies/genres.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import { NextPage } from 'next';
-import MovieGenreList from '../../../components/Discover/MovieGenreList';
+import MovieGenreList from '@app/components/Discover/MovieGenreList';
+import type { NextPage } from 'next';
 
 const MovieGenresPage: NextPage = () => {
   return <MovieGenreList />;
diff --git a/src/pages/discover/movies/index.tsx b/src/pages/discover/movies/index.tsx
index 823898e8..9eadf132 100644
--- a/src/pages/discover/movies/index.tsx
+++ b/src/pages/discover/movies/index.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import { NextPage } from 'next';
-import DiscoverMovies from '../../../components/Discover/DiscoverMovies';
+import DiscoverMovies from '@app/components/Discover/DiscoverMovies';
+import type { NextPage } from 'next';
 
 const DiscoverMoviesPage: NextPage = () => {
   return <DiscoverMovies />;
diff --git a/src/pages/discover/movies/language/[language]/index.tsx b/src/pages/discover/movies/language/[language]/index.tsx
index a1fba4fe..b0525237 100644
--- a/src/pages/discover/movies/language/[language]/index.tsx
+++ b/src/pages/discover/movies/language/[language]/index.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import { NextPage } from 'next';
-import DiscoverMovieLanguage from '../../../../../components/Discover/DiscoverMovieLanguage';
+import DiscoverMovieLanguage from '@app/components/Discover/DiscoverMovieLanguage';
+import type { NextPage } from 'next';
 
 const DiscoverMovieLanguagePage: NextPage = () => {
   return <DiscoverMovieLanguage />;
diff --git a/src/pages/discover/movies/studio/[studioId]/index.tsx b/src/pages/discover/movies/studio/[studioId]/index.tsx
index 4756ffbf..5de5088e 100644
--- a/src/pages/discover/movies/studio/[studioId]/index.tsx
+++ b/src/pages/discover/movies/studio/[studioId]/index.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import { NextPage } from 'next';
-import DiscoverMovieStudio from '../../../../../components/Discover/DiscoverStudio';
+import DiscoverMovieStudio from '@app/components/Discover/DiscoverStudio';
+import type { NextPage } from 'next';
 
 const DiscoverMoviesStudioPage: NextPage = () => {
   return <DiscoverMovieStudio />;
diff --git a/src/pages/discover/movies/upcoming.tsx b/src/pages/discover/movies/upcoming.tsx
index 13c62cc0..c917674d 100644
--- a/src/pages/discover/movies/upcoming.tsx
+++ b/src/pages/discover/movies/upcoming.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import { NextPage } from 'next';
-import UpcomingMovies from '../../../components/Discover/Upcoming';
+import UpcomingMovies from '@app/components/Discover/Upcoming';
+import type { NextPage } from 'next';
 
 const UpcomingMoviesPage: NextPage = () => {
   return <UpcomingMovies />;
diff --git a/src/pages/discover/trending.tsx b/src/pages/discover/trending.tsx
index 1ab2e951..17c50c84 100644
--- a/src/pages/discover/trending.tsx
+++ b/src/pages/discover/trending.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
+import Trending from '@app/components/Discover/Trending';
 import type { NextPage } from 'next';
-import Trending from '../../components/Discover/Trending';
 
 const TrendingPage: NextPage = () => {
   return <Trending />;
diff --git a/src/pages/discover/tv/genre/[genreId]/index.tsx b/src/pages/discover/tv/genre/[genreId]/index.tsx
index bb5cbd0e..639fe1ce 100644
--- a/src/pages/discover/tv/genre/[genreId]/index.tsx
+++ b/src/pages/discover/tv/genre/[genreId]/index.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import { NextPage } from 'next';
-import DiscoverTvGenre from '../../../../../components/Discover/DiscoverTvGenre';
+import DiscoverTvGenre from '@app/components/Discover/DiscoverTvGenre';
+import type { NextPage } from 'next';
 
 const DiscoverTvGenrePage: NextPage = () => {
   return <DiscoverTvGenre />;
diff --git a/src/pages/discover/tv/genres.tsx b/src/pages/discover/tv/genres.tsx
index 36475e91..ae9632e0 100644
--- a/src/pages/discover/tv/genres.tsx
+++ b/src/pages/discover/tv/genres.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import { NextPage } from 'next';
-import TvGenreList from '../../../components/Discover/TvGenreList';
+import TvGenreList from '@app/components/Discover/TvGenreList';
+import type { NextPage } from 'next';
 
 const TvGenresPage: NextPage = () => {
   return <TvGenreList />;
diff --git a/src/pages/discover/tv/index.tsx b/src/pages/discover/tv/index.tsx
index 19369440..b4dbc3c2 100644
--- a/src/pages/discover/tv/index.tsx
+++ b/src/pages/discover/tv/index.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import { NextPage } from 'next';
-import DiscoverTv from '../../../components/Discover/DiscoverTv';
+import DiscoverTv from '@app/components/Discover/DiscoverTv';
+import type { NextPage } from 'next';
 
 const DiscoverTvPage: NextPage = () => {
   return <DiscoverTv />;
diff --git a/src/pages/discover/tv/language/[language]/index.tsx b/src/pages/discover/tv/language/[language]/index.tsx
index 7d81b6c4..f3069513 100644
--- a/src/pages/discover/tv/language/[language]/index.tsx
+++ b/src/pages/discover/tv/language/[language]/index.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import { NextPage } from 'next';
-import DiscoverTvLanguage from '../../../../../components/Discover/DiscoverTvLanguage';
+import DiscoverTvLanguage from '@app/components/Discover/DiscoverTvLanguage';
+import type { NextPage } from 'next';
 
 const DiscoverTvLanguagePage: NextPage = () => {
   return <DiscoverTvLanguage />;
diff --git a/src/pages/discover/tv/network/[networkId]/index.tsx b/src/pages/discover/tv/network/[networkId]/index.tsx
index d864a4f9..38ca80bc 100644
--- a/src/pages/discover/tv/network/[networkId]/index.tsx
+++ b/src/pages/discover/tv/network/[networkId]/index.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import { NextPage } from 'next';
-import DiscoverNetwork from '../../../../../components/Discover/DiscoverNetwork';
+import DiscoverNetwork from '@app/components/Discover/DiscoverNetwork';
+import type { NextPage } from 'next';
 
 const DiscoverTvNetworkPage: NextPage = () => {
   return <DiscoverNetwork />;
diff --git a/src/pages/discover/tv/upcoming.tsx b/src/pages/discover/tv/upcoming.tsx
index 62af7996..c6de6473 100644
--- a/src/pages/discover/tv/upcoming.tsx
+++ b/src/pages/discover/tv/upcoming.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import { NextPage } from 'next';
-import DiscoverTvUpcoming from '../../../components/Discover/DiscoverTvUpcoming';
+import DiscoverTvUpcoming from '@app/components/Discover/DiscoverTvUpcoming';
+import type { NextPage } from 'next';
 
 const DiscoverTvPage: NextPage = () => {
   return <DiscoverTvUpcoming />;
diff --git a/src/pages/discover/watchlist.tsx b/src/pages/discover/watchlist.tsx
new file mode 100644
index 00000000..d7f0ecf1
--- /dev/null
+++ b/src/pages/discover/watchlist.tsx
@@ -0,0 +1,8 @@
+import DiscoverWatchlist from '@app/components/Discover/DiscoverWatchlist';
+import type { NextPage } from 'next';
+
+const WatchlistPage: NextPage = () => {
+  return <DiscoverWatchlist />;
+};
+
+export default WatchlistPage;
diff --git a/src/pages/index.tsx b/src/pages/index.tsx
index 1c15c0bd..5854c5a2 100644
--- a/src/pages/index.tsx
+++ b/src/pages/index.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
+import Discover from '@app/components/Discover';
 import type { NextPage } from 'next';
-import Discover from '../components/Discover';
 
 const Index: NextPage = () => {
   return <Discover />;
diff --git a/src/pages/issues/[issueId]/index.tsx b/src/pages/issues/[issueId]/index.tsx
index 48aadebf..bcf6d596 100644
--- a/src/pages/issues/[issueId]/index.tsx
+++ b/src/pages/issues/[issueId]/index.tsx
@@ -1,8 +1,7 @@
-import { NextPage } from 'next';
-import React from 'react';
-import IssueDetails from '../../../components/IssueDetails';
-import useRouteGuard from '../../../hooks/useRouteGuard';
-import { Permission } from '../../../hooks/useUser';
+import IssueDetails from '@app/components/IssueDetails';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const IssuePage: NextPage = () => {
   useRouteGuard(
diff --git a/src/pages/issues/index.tsx b/src/pages/issues/index.tsx
index f352b89b..69fe3d6f 100644
--- a/src/pages/issues/index.tsx
+++ b/src/pages/issues/index.tsx
@@ -1,8 +1,7 @@
-import { NextPage } from 'next';
-import React from 'react';
-import IssueList from '../../components/IssueList';
-import useRouteGuard from '../../hooks/useRouteGuard';
-import { Permission } from '../../hooks/useUser';
+import IssueList from '@app/components/IssueList';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const IssuePage: NextPage = () => {
   useRouteGuard(
diff --git a/src/pages/login/index.tsx b/src/pages/login/index.tsx
index 25c21909..67281121 100644
--- a/src/pages/login/index.tsx
+++ b/src/pages/login/index.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
+import Login from '@app/components/Login';
 import type { NextPage } from 'next';
-import Login from '../../components/Login';
 
 const LoginPage: NextPage = () => {
   return <Login />;
diff --git a/src/pages/login/plex/loading.tsx b/src/pages/login/plex/loading.tsx
index c8ba268a..e23d0aec 100644
--- a/src/pages/login/plex/loading.tsx
+++ b/src/pages/login/plex/loading.tsx
@@ -1,7 +1,6 @@
-import React from 'react';
-import LoadingSpinner from '../../../components/Common/LoadingSpinner';
+import LoadingSpinner from '@app/components/Common/LoadingSpinner';
 
-const PlexLoading: React.FC = () => {
+const PlexLoading = () => {
   return (
     <div>
       <LoadingSpinner />
diff --git a/src/pages/movie/[movieId]/cast.tsx b/src/pages/movie/[movieId]/cast.tsx
index ea23d091..803d3720 100644
--- a/src/pages/movie/[movieId]/cast.tsx
+++ b/src/pages/movie/[movieId]/cast.tsx
@@ -1,6 +1,5 @@
-import { NextPage } from 'next';
-import React from 'react';
-import MovieCast from '../../../components/MovieDetails/MovieCast';
+import MovieCast from '@app/components/MovieDetails/MovieCast';
+import type { NextPage } from 'next';
 
 const MovieCastPage: NextPage = () => {
   return <MovieCast />;
diff --git a/src/pages/movie/[movieId]/crew.tsx b/src/pages/movie/[movieId]/crew.tsx
index 6ba59053..5f5f391e 100644
--- a/src/pages/movie/[movieId]/crew.tsx
+++ b/src/pages/movie/[movieId]/crew.tsx
@@ -1,6 +1,5 @@
-import { NextPage } from 'next';
-import React from 'react';
-import MovieCrew from '../../../components/MovieDetails/MovieCrew';
+import MovieCrew from '@app/components/MovieDetails/MovieCrew';
+import type { NextPage } from 'next';
 
 const MovieCrewPage: NextPage = () => {
   return <MovieCrew />;
diff --git a/src/pages/movie/[movieId]/index.tsx b/src/pages/movie/[movieId]/index.tsx
index c69fbfef..2bb971c1 100644
--- a/src/pages/movie/[movieId]/index.tsx
+++ b/src/pages/movie/[movieId]/index.tsx
@@ -1,8 +1,7 @@
+import MovieDetails from '@app/components/MovieDetails';
+import type { MovieDetails as MovieDetailsType } from '@server/models/Movie';
 import axios from 'axios';
-import { NextPage } from 'next';
-import React from 'react';
-import type { MovieDetails as MovieDetailsType } from '../../../../server/models/Movie';
-import MovieDetails from '../../../components/MovieDetails';
+import type { NextPage } from 'next';
 
 interface MoviePageProps {
   movie?: MovieDetailsType;
diff --git a/src/pages/movie/[movieId]/recommendations.tsx b/src/pages/movie/[movieId]/recommendations.tsx
index 3fd1d622..9b848e79 100644
--- a/src/pages/movie/[movieId]/recommendations.tsx
+++ b/src/pages/movie/[movieId]/recommendations.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import { NextPage } from 'next';
-import MovieRecommendations from '../../../components/MovieDetails/MovieRecommendations';
+import MovieRecommendations from '@app/components/MovieDetails/MovieRecommendations';
+import type { NextPage } from 'next';
 
 const MovieRecommendationsPage: NextPage = () => {
   return <MovieRecommendations />;
diff --git a/src/pages/movie/[movieId]/similar.tsx b/src/pages/movie/[movieId]/similar.tsx
index 90ee37d9..efb639d4 100644
--- a/src/pages/movie/[movieId]/similar.tsx
+++ b/src/pages/movie/[movieId]/similar.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import { NextPage } from 'next';
-import MovieSimilar from '../../../components/MovieDetails/MovieSimilar';
+import MovieSimilar from '@app/components/MovieDetails/MovieSimilar';
+import type { NextPage } from 'next';
 
 const MovieSimilarPage: NextPage = () => {
   return <MovieSimilar />;
diff --git a/src/pages/person/[personId]/index.tsx b/src/pages/person/[personId]/index.tsx
index d905ef54..45099631 100644
--- a/src/pages/person/[personId]/index.tsx
+++ b/src/pages/person/[personId]/index.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import { NextPage } from 'next';
-import PersonDetails from '../../../components/PersonDetails';
+import PersonDetails from '@app/components/PersonDetails';
+import type { NextPage } from 'next';
 
 const MoviePage: NextPage = () => {
   return <PersonDetails />;
diff --git a/src/pages/profile/index.tsx b/src/pages/profile/index.tsx
index 22fef09e..0aa8c9f3 100644
--- a/src/pages/profile/index.tsx
+++ b/src/pages/profile/index.tsx
@@ -1,6 +1,5 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserProfile from '../../components/UserProfile';
+import UserProfile from '@app/components/UserProfile';
+import type { NextPage } from 'next';
 
 const UserPage: NextPage = () => {
   return <UserProfile />;
diff --git a/src/pages/profile/requests.tsx b/src/pages/profile/requests.tsx
new file mode 100644
index 00000000..f70b0f79
--- /dev/null
+++ b/src/pages/profile/requests.tsx
@@ -0,0 +1,8 @@
+import RequestList from '@app/components/RequestList';
+import type { NextPage } from 'next';
+
+const UserRequestsPage: NextPage = () => {
+  return <RequestList />;
+};
+
+export default UserRequestsPage;
diff --git a/src/pages/profile/settings/index.tsx b/src/pages/profile/settings/index.tsx
index 40fb7d2d..52e26473 100644
--- a/src/pages/profile/settings/index.tsx
+++ b/src/pages/profile/settings/index.tsx
@@ -1,7 +1,6 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../components/UserProfile/UserSettings';
-import UserGeneralSettings from '../../../components/UserProfile/UserSettings/UserGeneralSettings';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserGeneralSettings from '@app/components/UserProfile/UserSettings/UserGeneralSettings';
+import type { NextPage } from 'next';
 
 const UserSettingsPage: NextPage = () => {
   return (
diff --git a/src/pages/profile/settings/main.tsx b/src/pages/profile/settings/main.tsx
index 083358e0..cbe08f23 100644
--- a/src/pages/profile/settings/main.tsx
+++ b/src/pages/profile/settings/main.tsx
@@ -1,7 +1,6 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../components/UserProfile/UserSettings';
-import UserGeneralSettings from '../../../components/UserProfile/UserSettings/UserGeneralSettings';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserGeneralSettings from '@app/components/UserProfile/UserSettings/UserGeneralSettings';
+import type { NextPage } from 'next';
 
 const UserSettingsMainPage: NextPage = () => {
   return (
diff --git a/src/pages/profile/settings/notifications/discord.tsx b/src/pages/profile/settings/notifications/discord.tsx
index 06e580ff..383a3be0 100644
--- a/src/pages/profile/settings/notifications/discord.tsx
+++ b/src/pages/profile/settings/notifications/discord.tsx
@@ -1,8 +1,7 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../../components/UserProfile/UserSettings';
-import UserNotificationSettings from '../../../../components/UserProfile/UserSettings/UserNotificationSettings';
-import UserNotificationsDiscord from '../../../../components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsDiscord';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserNotificationSettings from '@app/components/UserProfile/UserSettings/UserNotificationSettings';
+import UserNotificationsDiscord from '@app/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsDiscord';
+import type { NextPage } from 'next';
 
 const NotificationsPage: NextPage = () => {
   return (
diff --git a/src/pages/profile/settings/notifications/email.tsx b/src/pages/profile/settings/notifications/email.tsx
index 370258ca..72995e0b 100644
--- a/src/pages/profile/settings/notifications/email.tsx
+++ b/src/pages/profile/settings/notifications/email.tsx
@@ -1,8 +1,7 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../../components/UserProfile/UserSettings';
-import UserNotificationSettings from '../../../../components/UserProfile/UserSettings/UserNotificationSettings';
-import UserNotificationsEmail from '../../../../components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsEmail';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserNotificationSettings from '@app/components/UserProfile/UserSettings/UserNotificationSettings';
+import UserNotificationsEmail from '@app/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsEmail';
+import type { NextPage } from 'next';
 
 const NotificationsPage: NextPage = () => {
   return (
diff --git a/src/pages/profile/settings/notifications/pushbullet.tsx b/src/pages/profile/settings/notifications/pushbullet.tsx
index 12afd941..56411c89 100644
--- a/src/pages/profile/settings/notifications/pushbullet.tsx
+++ b/src/pages/profile/settings/notifications/pushbullet.tsx
@@ -1,8 +1,7 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../../components/UserProfile/UserSettings';
-import UserNotificationSettings from '../../../../components/UserProfile/UserSettings/UserNotificationSettings';
-import UserNotificationsPushbullet from '../../../../components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushbullet';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserNotificationSettings from '@app/components/UserProfile/UserSettings/UserNotificationSettings';
+import UserNotificationsPushbullet from '@app/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushbullet';
+import type { NextPage } from 'next';
 
 const NotificationsPage: NextPage = () => {
   return (
diff --git a/src/pages/profile/settings/notifications/pushover.tsx b/src/pages/profile/settings/notifications/pushover.tsx
index 83b8d71d..6c688cdd 100644
--- a/src/pages/profile/settings/notifications/pushover.tsx
+++ b/src/pages/profile/settings/notifications/pushover.tsx
@@ -1,8 +1,7 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../../components/UserProfile/UserSettings';
-import UserNotificationSettings from '../../../../components/UserProfile/UserSettings/UserNotificationSettings';
-import UserNotificationsPushover from '../../../../components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushover';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserNotificationSettings from '@app/components/UserProfile/UserSettings/UserNotificationSettings';
+import UserNotificationsPushover from '@app/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushover';
+import type { NextPage } from 'next';
 
 const NotificationsPage: NextPage = () => {
   return (
diff --git a/src/pages/profile/settings/notifications/telegram.tsx b/src/pages/profile/settings/notifications/telegram.tsx
index 3a641aab..4cdd4146 100644
--- a/src/pages/profile/settings/notifications/telegram.tsx
+++ b/src/pages/profile/settings/notifications/telegram.tsx
@@ -1,8 +1,7 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../../components/UserProfile/UserSettings';
-import UserNotificationSettings from '../../../../components/UserProfile/UserSettings/UserNotificationSettings';
-import UserNotificationsTelegram from '../../../../components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsTelegram';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserNotificationSettings from '@app/components/UserProfile/UserSettings/UserNotificationSettings';
+import UserNotificationsTelegram from '@app/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsTelegram';
+import type { NextPage } from 'next';
 
 const NotificationsPage: NextPage = () => {
   return (
diff --git a/src/pages/profile/settings/notifications/webpush.tsx b/src/pages/profile/settings/notifications/webpush.tsx
index a44f254c..8dce6a96 100644
--- a/src/pages/profile/settings/notifications/webpush.tsx
+++ b/src/pages/profile/settings/notifications/webpush.tsx
@@ -1,8 +1,7 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../../components/UserProfile/UserSettings';
-import UserNotificationSettings from '../../../../components/UserProfile/UserSettings/UserNotificationSettings';
-import UserWebPushSettings from '../../../../components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsWebPush';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserNotificationSettings from '@app/components/UserProfile/UserSettings/UserNotificationSettings';
+import UserWebPushSettings from '@app/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsWebPush';
+import type { NextPage } from 'next';
 
 const WebPushProfileNotificationsPage: NextPage = () => {
   return (
diff --git a/src/pages/profile/settings/password.tsx b/src/pages/profile/settings/password.tsx
index 304e29aa..4c30eb7f 100644
--- a/src/pages/profile/settings/password.tsx
+++ b/src/pages/profile/settings/password.tsx
@@ -1,7 +1,6 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../components/UserProfile/UserSettings';
-import UserPasswordChange from '../../../components/UserProfile/UserSettings/UserPasswordChange';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserPasswordChange from '@app/components/UserProfile/UserSettings/UserPasswordChange';
+import type { NextPage } from 'next';
 
 const UserPassswordPage: NextPage = () => {
   return (
diff --git a/src/pages/profile/settings/permissions.tsx b/src/pages/profile/settings/permissions.tsx
index 7926a2eb..9c68a84a 100644
--- a/src/pages/profile/settings/permissions.tsx
+++ b/src/pages/profile/settings/permissions.tsx
@@ -1,7 +1,6 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../components/UserProfile/UserSettings';
-import UserPermissions from '../../../components/UserProfile/UserSettings/UserPermissions';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserPermissions from '@app/components/UserProfile/UserSettings/UserPermissions';
+import type { NextPage } from 'next';
 
 const UserPermissionsPage: NextPage = () => {
   return (
diff --git a/src/pages/profile/watchlist.tsx b/src/pages/profile/watchlist.tsx
new file mode 100644
index 00000000..286578ab
--- /dev/null
+++ b/src/pages/profile/watchlist.tsx
@@ -0,0 +1,8 @@
+import DiscoverWatchlist from '@app/components/Discover/DiscoverWatchlist';
+import type { NextPage } from 'next';
+
+const UserWatchlistPage: NextPage = () => {
+  return <DiscoverWatchlist />;
+};
+
+export default UserWatchlistPage;
diff --git a/src/pages/requests/index.tsx b/src/pages/requests/index.tsx
index 225331ed..f0368bb5 100644
--- a/src/pages/requests/index.tsx
+++ b/src/pages/requests/index.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
+import RequestList from '@app/components/RequestList';
 import type { NextPage } from 'next';
-import RequestList from '../../components/RequestList';
 
 const RequestsPage: NextPage = () => {
   return <RequestList />;
diff --git a/src/pages/resetpassword/[guid]/index.tsx b/src/pages/resetpassword/[guid]/index.tsx
index bf5ac487..04334b57 100644
--- a/src/pages/resetpassword/[guid]/index.tsx
+++ b/src/pages/resetpassword/[guid]/index.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
+import ResetPassword from '@app/components/ResetPassword';
 import type { NextPage } from 'next';
-import ResetPassword from '../../../components/ResetPassword';
 
 const ResetPasswordPage: NextPage = () => {
   return <ResetPassword />;
diff --git a/src/pages/resetpassword/index.tsx b/src/pages/resetpassword/index.tsx
index f14ed663..6d1a904c 100644
--- a/src/pages/resetpassword/index.tsx
+++ b/src/pages/resetpassword/index.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
+import RequestResetLink from '@app/components/ResetPassword/RequestResetLink';
 import type { NextPage } from 'next';
-import RequestResetLink from '../../components/ResetPassword/RequestResetLink';
 
 const RequestResetLinkPage: NextPage = () => {
   return <RequestResetLink />;
diff --git a/src/pages/search.tsx b/src/pages/search.tsx
index 05ed18a8..333499d8 100644
--- a/src/pages/search.tsx
+++ b/src/pages/search.tsx
@@ -1,7 +1,6 @@
-import React from 'react';
-import Search from '../components/Search';
+import Search from '@app/components/Search';
 
-const SearchPage: React.FC = () => {
+const SearchPage = () => {
   return <Search />;
 };
 
diff --git a/src/pages/settings/about.tsx b/src/pages/settings/about.tsx
index 442669d9..2bec4f0e 100644
--- a/src/pages/settings/about.tsx
+++ b/src/pages/settings/about.tsx
@@ -1,12 +1,11 @@
-import { NextPage } from 'next';
-import React from 'react';
-import SettingsAbout from '../../components/Settings/SettingsAbout';
-import SettingsLayout from '../../components/Settings/SettingsLayout';
-import useRouteGuard from '../../hooks/useRouteGuard';
-import { Permission } from '../../hooks/useUser';
+import SettingsAbout from '@app/components/Settings/SettingsAbout';
+import SettingsLayout from '@app/components/Settings/SettingsLayout';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const SettingsAboutPage: NextPage = () => {
-  useRouteGuard(Permission.MANAGE_SETTINGS);
+  useRouteGuard(Permission.ADMIN);
   return (
     <SettingsLayout>
       <SettingsAbout />
diff --git a/src/pages/settings/index.tsx b/src/pages/settings/index.tsx
index e67d53b4..5ca5a150 100644
--- a/src/pages/settings/index.tsx
+++ b/src/pages/settings/index.tsx
@@ -1,12 +1,11 @@
-import React from 'react';
-import { NextPage } from 'next';
-import SettingsLayout from '../../components/Settings/SettingsLayout';
-import SettingsMain from '../../components/Settings/SettingsMain';
-import useRouteGuard from '../../hooks/useRouteGuard';
-import { Permission } from '../../hooks/useUser';
+import SettingsLayout from '@app/components/Settings/SettingsLayout';
+import SettingsMain from '@app/components/Settings/SettingsMain';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const SettingsPage: NextPage = () => {
-  useRouteGuard(Permission.MANAGE_SETTINGS);
+  useRouteGuard(Permission.ADMIN);
   return (
     <SettingsLayout>
       <SettingsMain />
diff --git a/src/pages/settings/jobs.tsx b/src/pages/settings/jobs.tsx
index 7c546c4f..97e6743d 100644
--- a/src/pages/settings/jobs.tsx
+++ b/src/pages/settings/jobs.tsx
@@ -1,12 +1,11 @@
-import React from 'react';
+import SettingsJobs from '@app/components/Settings/SettingsJobsCache';
+import SettingsLayout from '@app/components/Settings/SettingsLayout';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
 import type { NextPage } from 'next';
-import SettingsLayout from '../../components/Settings/SettingsLayout';
-import SettingsJobs from '../../components/Settings/SettingsJobsCache';
-import { Permission } from '../../hooks/useUser';
-import useRouteGuard from '../../hooks/useRouteGuard';
 
 const SettingsMainPage: NextPage = () => {
-  useRouteGuard(Permission.MANAGE_SETTINGS);
+  useRouteGuard(Permission.ADMIN);
   return (
     <SettingsLayout>
       <SettingsJobs />
diff --git a/src/pages/settings/logs.tsx b/src/pages/settings/logs.tsx
index 09c28fe0..8fbc3272 100644
--- a/src/pages/settings/logs.tsx
+++ b/src/pages/settings/logs.tsx
@@ -1,12 +1,11 @@
-import { NextPage } from 'next';
-import React from 'react';
-import SettingsLayout from '../../components/Settings/SettingsLayout';
-import SettingsLogs from '../../components/Settings/SettingsLogs';
-import useRouteGuard from '../../hooks/useRouteGuard';
-import { Permission } from '../../hooks/useUser';
+import SettingsLayout from '@app/components/Settings/SettingsLayout';
+import SettingsLogs from '@app/components/Settings/SettingsLogs';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const SettingsLogsPage: NextPage = () => {
-  useRouteGuard(Permission.MANAGE_SETTINGS);
+  useRouteGuard(Permission.ADMIN);
   return (
     <SettingsLayout>
       <SettingsLogs />
diff --git a/src/pages/settings/main.tsx b/src/pages/settings/main.tsx
index 7c450a37..1b44fd65 100644
--- a/src/pages/settings/main.tsx
+++ b/src/pages/settings/main.tsx
@@ -1,12 +1,11 @@
-import React from 'react';
-import { NextPage } from 'next';
-import SettingsLayout from '../../components/Settings/SettingsLayout';
-import SettingsMain from '../../components/Settings/SettingsMain';
-import { Permission } from '../../hooks/useUser';
-import useRouteGuard from '../../hooks/useRouteGuard';
+import SettingsLayout from '@app/components/Settings/SettingsLayout';
+import SettingsMain from '@app/components/Settings/SettingsMain';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const SettingsMainPage: NextPage = () => {
-  useRouteGuard(Permission.MANAGE_SETTINGS);
+  useRouteGuard(Permission.ADMIN);
   return (
     <SettingsLayout>
       <SettingsMain />
diff --git a/src/pages/settings/notifications/discord.tsx b/src/pages/settings/notifications/discord.tsx
index 6345b625..7a583a22 100644
--- a/src/pages/settings/notifications/discord.tsx
+++ b/src/pages/settings/notifications/discord.tsx
@@ -1,13 +1,12 @@
-import { NextPage } from 'next';
-import React from 'react';
-import NotificationsDiscord from '../../../components/Settings/Notifications/NotificationsDiscord';
-import SettingsLayout from '../../../components/Settings/SettingsLayout';
-import SettingsNotifications from '../../../components/Settings/SettingsNotifications';
-import useRouteGuard from '../../../hooks/useRouteGuard';
-import { Permission } from '../../../hooks/useUser';
+import NotificationsDiscord from '@app/components/Settings/Notifications/NotificationsDiscord';
+import SettingsLayout from '@app/components/Settings/SettingsLayout';
+import SettingsNotifications from '@app/components/Settings/SettingsNotifications';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const NotificationsPage: NextPage = () => {
-  useRouteGuard(Permission.MANAGE_SETTINGS);
+  useRouteGuard(Permission.ADMIN);
   return (
     <SettingsLayout>
       <SettingsNotifications>
diff --git a/src/pages/settings/notifications/email.tsx b/src/pages/settings/notifications/email.tsx
index c751f430..2193f176 100644
--- a/src/pages/settings/notifications/email.tsx
+++ b/src/pages/settings/notifications/email.tsx
@@ -1,13 +1,12 @@
-import { NextPage } from 'next';
-import React from 'react';
-import NotificationsEmail from '../../../components/Settings/Notifications/NotificationsEmail';
-import SettingsLayout from '../../../components/Settings/SettingsLayout';
-import SettingsNotifications from '../../../components/Settings/SettingsNotifications';
-import useRouteGuard from '../../../hooks/useRouteGuard';
-import { Permission } from '../../../hooks/useUser';
+import NotificationsEmail from '@app/components/Settings/Notifications/NotificationsEmail';
+import SettingsLayout from '@app/components/Settings/SettingsLayout';
+import SettingsNotifications from '@app/components/Settings/SettingsNotifications';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const NotificationsPage: NextPage = () => {
-  useRouteGuard(Permission.MANAGE_SETTINGS);
+  useRouteGuard(Permission.ADMIN);
   return (
     <SettingsLayout>
       <SettingsNotifications>
diff --git a/src/pages/settings/notifications/gotify.tsx b/src/pages/settings/notifications/gotify.tsx
index a47c9c28..6ca4bd98 100644
--- a/src/pages/settings/notifications/gotify.tsx
+++ b/src/pages/settings/notifications/gotify.tsx
@@ -1,13 +1,12 @@
-import { NextPage } from 'next';
-import React from 'react';
-import NotificationsGotify from '../../../components/Settings/Notifications/NotificationsGotify';
-import SettingsLayout from '../../../components/Settings/SettingsLayout';
-import SettingsNotifications from '../../../components/Settings/SettingsNotifications';
-import useRouteGuard from '../../../hooks/useRouteGuard';
-import { Permission } from '../../../hooks/useUser';
+import NotificationsGotify from '@app/components/Settings/Notifications/NotificationsGotify';
+import SettingsLayout from '@app/components/Settings/SettingsLayout';
+import SettingsNotifications from '@app/components/Settings/SettingsNotifications';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const NotificationsPage: NextPage = () => {
-  useRouteGuard(Permission.MANAGE_SETTINGS);
+  useRouteGuard(Permission.ADMIN);
   return (
     <SettingsLayout>
       <SettingsNotifications>
diff --git a/src/pages/settings/notifications/lunasea.tsx b/src/pages/settings/notifications/lunasea.tsx
index 070e6e3c..a9662fdd 100644
--- a/src/pages/settings/notifications/lunasea.tsx
+++ b/src/pages/settings/notifications/lunasea.tsx
@@ -1,13 +1,12 @@
-import { NextPage } from 'next';
-import React from 'react';
-import NotificationsLunaSea from '../../../components/Settings/Notifications/NotificationsLunaSea';
-import SettingsLayout from '../../../components/Settings/SettingsLayout';
-import SettingsNotifications from '../../../components/Settings/SettingsNotifications';
-import useRouteGuard from '../../../hooks/useRouteGuard';
-import { Permission } from '../../../hooks/useUser';
+import NotificationsLunaSea from '@app/components/Settings/Notifications/NotificationsLunaSea';
+import SettingsLayout from '@app/components/Settings/SettingsLayout';
+import SettingsNotifications from '@app/components/Settings/SettingsNotifications';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const NotificationsPage: NextPage = () => {
-  useRouteGuard(Permission.MANAGE_SETTINGS);
+  useRouteGuard(Permission.ADMIN);
   return (
     <SettingsLayout>
       <SettingsNotifications>
diff --git a/src/pages/settings/notifications/pushbullet.tsx b/src/pages/settings/notifications/pushbullet.tsx
index cdfa2d05..50c1d98b 100644
--- a/src/pages/settings/notifications/pushbullet.tsx
+++ b/src/pages/settings/notifications/pushbullet.tsx
@@ -1,13 +1,12 @@
-import { NextPage } from 'next';
-import React from 'react';
-import NotificationsPushbullet from '../../../components/Settings/Notifications/NotificationsPushbullet';
-import SettingsLayout from '../../../components/Settings/SettingsLayout';
-import SettingsNotifications from '../../../components/Settings/SettingsNotifications';
-import useRouteGuard from '../../../hooks/useRouteGuard';
-import { Permission } from '../../../hooks/useUser';
+import NotificationsPushbullet from '@app/components/Settings/Notifications/NotificationsPushbullet';
+import SettingsLayout from '@app/components/Settings/SettingsLayout';
+import SettingsNotifications from '@app/components/Settings/SettingsNotifications';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const NotificationsPage: NextPage = () => {
-  useRouteGuard(Permission.MANAGE_SETTINGS);
+  useRouteGuard(Permission.ADMIN);
   return (
     <SettingsLayout>
       <SettingsNotifications>
diff --git a/src/pages/settings/notifications/pushover.tsx b/src/pages/settings/notifications/pushover.tsx
index 23df0939..4211e668 100644
--- a/src/pages/settings/notifications/pushover.tsx
+++ b/src/pages/settings/notifications/pushover.tsx
@@ -1,13 +1,12 @@
-import { NextPage } from 'next';
-import React from 'react';
-import NotificationsPushover from '../../../components/Settings/Notifications/NotificationsPushover';
-import SettingsLayout from '../../../components/Settings/SettingsLayout';
-import SettingsNotifications from '../../../components/Settings/SettingsNotifications';
-import useRouteGuard from '../../../hooks/useRouteGuard';
-import { Permission } from '../../../hooks/useUser';
+import NotificationsPushover from '@app/components/Settings/Notifications/NotificationsPushover';
+import SettingsLayout from '@app/components/Settings/SettingsLayout';
+import SettingsNotifications from '@app/components/Settings/SettingsNotifications';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const NotificationsPage: NextPage = () => {
-  useRouteGuard(Permission.MANAGE_SETTINGS);
+  useRouteGuard(Permission.ADMIN);
   return (
     <SettingsLayout>
       <SettingsNotifications>
diff --git a/src/pages/settings/notifications/slack.tsx b/src/pages/settings/notifications/slack.tsx
index 768799b7..1ee8a963 100644
--- a/src/pages/settings/notifications/slack.tsx
+++ b/src/pages/settings/notifications/slack.tsx
@@ -1,13 +1,12 @@
-import { NextPage } from 'next';
-import React from 'react';
-import NotificationsSlack from '../../../components/Settings/Notifications/NotificationsSlack';
-import SettingsLayout from '../../../components/Settings/SettingsLayout';
-import SettingsNotifications from '../../../components/Settings/SettingsNotifications';
-import useRouteGuard from '../../../hooks/useRouteGuard';
-import { Permission } from '../../../hooks/useUser';
+import NotificationsSlack from '@app/components/Settings/Notifications/NotificationsSlack';
+import SettingsLayout from '@app/components/Settings/SettingsLayout';
+import SettingsNotifications from '@app/components/Settings/SettingsNotifications';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const NotificationsSlackPage: NextPage = () => {
-  useRouteGuard(Permission.MANAGE_SETTINGS);
+  useRouteGuard(Permission.ADMIN);
   return (
     <SettingsLayout>
       <SettingsNotifications>
diff --git a/src/pages/settings/notifications/telegram.tsx b/src/pages/settings/notifications/telegram.tsx
index a651ff69..e4d98d5c 100644
--- a/src/pages/settings/notifications/telegram.tsx
+++ b/src/pages/settings/notifications/telegram.tsx
@@ -1,13 +1,12 @@
-import { NextPage } from 'next';
-import React from 'react';
-import NotificationsTelegram from '../../../components/Settings/Notifications/NotificationsTelegram';
-import SettingsLayout from '../../../components/Settings/SettingsLayout';
-import SettingsNotifications from '../../../components/Settings/SettingsNotifications';
-import useRouteGuard from '../../../hooks/useRouteGuard';
-import { Permission } from '../../../hooks/useUser';
+import NotificationsTelegram from '@app/components/Settings/Notifications/NotificationsTelegram';
+import SettingsLayout from '@app/components/Settings/SettingsLayout';
+import SettingsNotifications from '@app/components/Settings/SettingsNotifications';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const NotificationsPage: NextPage = () => {
-  useRouteGuard(Permission.MANAGE_SETTINGS);
+  useRouteGuard(Permission.ADMIN);
   return (
     <SettingsLayout>
       <SettingsNotifications>
diff --git a/src/pages/settings/notifications/webhook.tsx b/src/pages/settings/notifications/webhook.tsx
index 4be0d30c..52ce2e01 100644
--- a/src/pages/settings/notifications/webhook.tsx
+++ b/src/pages/settings/notifications/webhook.tsx
@@ -1,13 +1,12 @@
-import { NextPage } from 'next';
-import React from 'react';
-import NotificationsWebhook from '../../../components/Settings/Notifications/NotificationsWebhook';
-import SettingsLayout from '../../../components/Settings/SettingsLayout';
-import SettingsNotifications from '../../../components/Settings/SettingsNotifications';
-import useRouteGuard from '../../../hooks/useRouteGuard';
-import { Permission } from '../../../hooks/useUser';
+import NotificationsWebhook from '@app/components/Settings/Notifications/NotificationsWebhook';
+import SettingsLayout from '@app/components/Settings/SettingsLayout';
+import SettingsNotifications from '@app/components/Settings/SettingsNotifications';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const NotificationsPage: NextPage = () => {
-  useRouteGuard(Permission.MANAGE_SETTINGS);
+  useRouteGuard(Permission.ADMIN);
   return (
     <SettingsLayout>
       <SettingsNotifications>
diff --git a/src/pages/settings/notifications/webpush.tsx b/src/pages/settings/notifications/webpush.tsx
index e91fe737..cf2e2956 100644
--- a/src/pages/settings/notifications/webpush.tsx
+++ b/src/pages/settings/notifications/webpush.tsx
@@ -1,13 +1,12 @@
-import { NextPage } from 'next';
-import React from 'react';
-import NotificationsWebPush from '../../../components/Settings/Notifications/NotificationsWebPush';
-import SettingsLayout from '../../../components/Settings/SettingsLayout';
-import SettingsNotifications from '../../../components/Settings/SettingsNotifications';
-import useRouteGuard from '../../../hooks/useRouteGuard';
-import { Permission } from '../../../hooks/useUser';
+import NotificationsWebPush from '@app/components/Settings/Notifications/NotificationsWebPush';
+import SettingsLayout from '@app/components/Settings/SettingsLayout';
+import SettingsNotifications from '@app/components/Settings/SettingsNotifications';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const NotificationsWebPushPage: NextPage = () => {
-  useRouteGuard(Permission.MANAGE_SETTINGS);
+  useRouteGuard(Permission.ADMIN);
   return (
     <SettingsLayout>
       <SettingsNotifications>
diff --git a/src/pages/settings/plex.tsx b/src/pages/settings/plex.tsx
index d5beaeeb..f2871da1 100644
--- a/src/pages/settings/plex.tsx
+++ b/src/pages/settings/plex.tsx
@@ -1,12 +1,11 @@
-import React from 'react';
+import SettingsLayout from '@app/components/Settings/SettingsLayout';
+import SettingsPlex from '@app/components/Settings/SettingsPlex';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
 import type { NextPage } from 'next';
-import SettingsLayout from '../../components/Settings/SettingsLayout';
-import SettingsPlex from '../../components/Settings/SettingsPlex';
-import { Permission } from '../../hooks/useUser';
-import useRouteGuard from '../../hooks/useRouteGuard';
 
 const PlexSettingsPage: NextPage = () => {
-  useRouteGuard(Permission.MANAGE_SETTINGS);
+  useRouteGuard(Permission.ADMIN);
   return (
     <SettingsLayout>
       <SettingsPlex />
diff --git a/src/pages/settings/services.tsx b/src/pages/settings/services.tsx
index 862b9b4d..a93e4217 100644
--- a/src/pages/settings/services.tsx
+++ b/src/pages/settings/services.tsx
@@ -1,12 +1,11 @@
-import React from 'react';
+import SettingsLayout from '@app/components/Settings/SettingsLayout';
+import SettingsServices from '@app/components/Settings/SettingsServices';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
 import type { NextPage } from 'next';
-import SettingsLayout from '../../components/Settings/SettingsLayout';
-import SettingsServices from '../../components/Settings/SettingsServices';
-import { Permission } from '../../hooks/useUser';
-import useRouteGuard from '../../hooks/useRouteGuard';
 
 const ServicesSettingsPage: NextPage = () => {
-  useRouteGuard(Permission.MANAGE_SETTINGS);
+  useRouteGuard(Permission.ADMIN);
   return (
     <SettingsLayout>
       <SettingsServices />
diff --git a/src/pages/settings/users.tsx b/src/pages/settings/users.tsx
index 1461d724..b1770d1e 100644
--- a/src/pages/settings/users.tsx
+++ b/src/pages/settings/users.tsx
@@ -1,12 +1,11 @@
-import React from 'react';
-import { NextPage } from 'next';
-import SettingsLayout from '../../components/Settings/SettingsLayout';
-import SettingsUsers from '../../components/Settings/SettingsUsers';
-import { Permission } from '../../hooks/useUser';
-import useRouteGuard from '../../hooks/useRouteGuard';
+import SettingsLayout from '@app/components/Settings/SettingsLayout';
+import SettingsUsers from '@app/components/Settings/SettingsUsers';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const SettingsUsersPage: NextPage = () => {
-  useRouteGuard(Permission.MANAGE_SETTINGS);
+  useRouteGuard(Permission.ADMIN);
   return (
     <SettingsLayout>
       <SettingsUsers />
diff --git a/src/pages/setup.tsx b/src/pages/setup.tsx
index 82a9c459..09c8e695 100644
--- a/src/pages/setup.tsx
+++ b/src/pages/setup.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import { NextPage } from 'next';
-import Setup from '../components/Setup';
+import Setup from '@app/components/Setup';
+import type { NextPage } from 'next';
 
 const SetupPage: NextPage = () => {
   return <Setup />;
diff --git a/src/pages/tv/[tvId]/cast.tsx b/src/pages/tv/[tvId]/cast.tsx
index b7cc28b2..91df3531 100644
--- a/src/pages/tv/[tvId]/cast.tsx
+++ b/src/pages/tv/[tvId]/cast.tsx
@@ -1,6 +1,5 @@
-import { NextPage } from 'next';
-import React from 'react';
-import TvCast from '../../../components/TvDetails/TvCast';
+import TvCast from '@app/components/TvDetails/TvCast';
+import type { NextPage } from 'next';
 
 const TvCastPage: NextPage = () => {
   return <TvCast />;
diff --git a/src/pages/tv/[tvId]/crew.tsx b/src/pages/tv/[tvId]/crew.tsx
index aec04080..aee6a473 100644
--- a/src/pages/tv/[tvId]/crew.tsx
+++ b/src/pages/tv/[tvId]/crew.tsx
@@ -1,6 +1,5 @@
-import { NextPage } from 'next';
-import React from 'react';
-import TvCrew from '../../../components/TvDetails/TvCrew';
+import TvCrew from '@app/components/TvDetails/TvCrew';
+import type { NextPage } from 'next';
 
 const TvCrewPage: NextPage = () => {
   return <TvCrew />;
diff --git a/src/pages/tv/[tvId]/index.tsx b/src/pages/tv/[tvId]/index.tsx
index 43e81709..69fe216f 100644
--- a/src/pages/tv/[tvId]/index.tsx
+++ b/src/pages/tv/[tvId]/index.tsx
@@ -1,8 +1,7 @@
+import TvDetails from '@app/components/TvDetails';
+import type { TvDetails as TvDetailsType } from '@server/models/Tv';
 import axios from 'axios';
-import { NextPage } from 'next';
-import React from 'react';
-import type { TvDetails as TvDetailsType } from '../../../../server/models/Tv';
-import TvDetails from '../../../components/TvDetails';
+import type { NextPage } from 'next';
 
 interface TvPageProps {
   tv?: TvDetailsType;
diff --git a/src/pages/tv/[tvId]/recommendations.tsx b/src/pages/tv/[tvId]/recommendations.tsx
index 37269e2d..0c6d9c81 100644
--- a/src/pages/tv/[tvId]/recommendations.tsx
+++ b/src/pages/tv/[tvId]/recommendations.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import { NextPage } from 'next';
-import TvRecommendations from '../../../components/TvDetails/TvRecommendations';
+import TvRecommendations from '@app/components/TvDetails/TvRecommendations';
+import type { NextPage } from 'next';
 
 const TvRecommendationsPage: NextPage = () => {
   return <TvRecommendations />;
diff --git a/src/pages/tv/[tvId]/similar.tsx b/src/pages/tv/[tvId]/similar.tsx
index cca4500a..b5179315 100644
--- a/src/pages/tv/[tvId]/similar.tsx
+++ b/src/pages/tv/[tvId]/similar.tsx
@@ -1,6 +1,5 @@
-import React from 'react';
-import { NextPage } from 'next';
-import TvSimilar from '../../../components/TvDetails/TvSimilar';
+import TvSimilar from '@app/components/TvDetails/TvSimilar';
+import type { NextPage } from 'next';
 
 const TvSimilarPage: NextPage = () => {
   return <TvSimilar />;
diff --git a/src/pages/users/[userId]/index.tsx b/src/pages/users/[userId]/index.tsx
index 4385981c..0aa8c9f3 100644
--- a/src/pages/users/[userId]/index.tsx
+++ b/src/pages/users/[userId]/index.tsx
@@ -1,6 +1,5 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserProfile from '../../../components/UserProfile';
+import UserProfile from '@app/components/UserProfile';
+import type { NextPage } from 'next';
 
 const UserPage: NextPage = () => {
   return <UserProfile />;
diff --git a/src/pages/users/[userId]/requests.tsx b/src/pages/users/[userId]/requests.tsx
index 105b56b4..f17968bf 100644
--- a/src/pages/users/[userId]/requests.tsx
+++ b/src/pages/users/[userId]/requests.tsx
@@ -1,8 +1,7 @@
-import { NextPage } from 'next';
-import React from 'react';
-import RequestList from '../../../components/RequestList';
-import useRouteGuard from '../../../hooks/useRouteGuard';
-import { Permission } from '../../../hooks/useUser';
+import RequestList from '@app/components/RequestList';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const UserRequestsPage: NextPage = () => {
   useRouteGuard([Permission.MANAGE_REQUESTS, Permission.REQUEST_VIEW], {
diff --git a/src/pages/users/[userId]/settings/index.tsx b/src/pages/users/[userId]/settings/index.tsx
index d6708b9f..b8886b01 100644
--- a/src/pages/users/[userId]/settings/index.tsx
+++ b/src/pages/users/[userId]/settings/index.tsx
@@ -1,9 +1,8 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../../components/UserProfile/UserSettings';
-import UserGeneralSettings from '../../../../components/UserProfile/UserSettings/UserGeneralSettings';
-import useRouteGuard from '../../../../hooks/useRouteGuard';
-import { Permission } from '../../../../hooks/useUser';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserGeneralSettings from '@app/components/UserProfile/UserSettings/UserGeneralSettings';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const UserSettingsPage: NextPage = () => {
   useRouteGuard(Permission.MANAGE_USERS);
diff --git a/src/pages/users/[userId]/settings/main.tsx b/src/pages/users/[userId]/settings/main.tsx
index a2d5e7fe..58b05405 100644
--- a/src/pages/users/[userId]/settings/main.tsx
+++ b/src/pages/users/[userId]/settings/main.tsx
@@ -1,9 +1,8 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../../components/UserProfile/UserSettings';
-import UserGeneralSettings from '../../../../components/UserProfile/UserSettings/UserGeneralSettings';
-import useRouteGuard from '../../../../hooks/useRouteGuard';
-import { Permission } from '../../../../hooks/useUser';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserGeneralSettings from '@app/components/UserProfile/UserSettings/UserGeneralSettings';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const UserSettingsMainPage: NextPage = () => {
   useRouteGuard(Permission.MANAGE_USERS);
diff --git a/src/pages/users/[userId]/settings/notifications/discord.tsx b/src/pages/users/[userId]/settings/notifications/discord.tsx
index f24b0810..727d542e 100644
--- a/src/pages/users/[userId]/settings/notifications/discord.tsx
+++ b/src/pages/users/[userId]/settings/notifications/discord.tsx
@@ -1,10 +1,9 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../../../components/UserProfile/UserSettings';
-import UserNotificationSettings from '../../../../../components/UserProfile/UserSettings/UserNotificationSettings';
-import UserNotificationsDiscord from '../../../../../components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsDiscord';
-import useRouteGuard from '../../../../../hooks/useRouteGuard';
-import { Permission } from '../../../../../hooks/useUser';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserNotificationSettings from '@app/components/UserProfile/UserSettings/UserNotificationSettings';
+import UserNotificationsDiscord from '@app/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsDiscord';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const NotificationsPage: NextPage = () => {
   useRouteGuard(Permission.MANAGE_USERS);
diff --git a/src/pages/users/[userId]/settings/notifications/email.tsx b/src/pages/users/[userId]/settings/notifications/email.tsx
index 7e62b127..8634c55e 100644
--- a/src/pages/users/[userId]/settings/notifications/email.tsx
+++ b/src/pages/users/[userId]/settings/notifications/email.tsx
@@ -1,10 +1,9 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../../../components/UserProfile/UserSettings';
-import UserNotificationSettings from '../../../../../components/UserProfile/UserSettings/UserNotificationSettings';
-import UserNotificationsEmail from '../../../../../components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsEmail';
-import useRouteGuard from '../../../../../hooks/useRouteGuard';
-import { Permission } from '../../../../../hooks/useUser';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserNotificationSettings from '@app/components/UserProfile/UserSettings/UserNotificationSettings';
+import UserNotificationsEmail from '@app/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsEmail';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const NotificationsPage: NextPage = () => {
   useRouteGuard(Permission.MANAGE_USERS);
diff --git a/src/pages/users/[userId]/settings/notifications/pushbullet.tsx b/src/pages/users/[userId]/settings/notifications/pushbullet.tsx
index cd7ca10c..210a47e4 100644
--- a/src/pages/users/[userId]/settings/notifications/pushbullet.tsx
+++ b/src/pages/users/[userId]/settings/notifications/pushbullet.tsx
@@ -1,10 +1,9 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../../../components/UserProfile/UserSettings';
-import UserNotificationSettings from '../../../../../components/UserProfile/UserSettings/UserNotificationSettings';
-import UserNotificationsPushbullet from '../../../../../components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushbullet';
-import useRouteGuard from '../../../../../hooks/useRouteGuard';
-import { Permission } from '../../../../../hooks/useUser';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserNotificationSettings from '@app/components/UserProfile/UserSettings/UserNotificationSettings';
+import UserNotificationsPushbullet from '@app/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushbullet';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const NotificationsPage: NextPage = () => {
   useRouteGuard(Permission.MANAGE_USERS);
diff --git a/src/pages/users/[userId]/settings/notifications/pushover.tsx b/src/pages/users/[userId]/settings/notifications/pushover.tsx
index b37a866f..3f747e03 100644
--- a/src/pages/users/[userId]/settings/notifications/pushover.tsx
+++ b/src/pages/users/[userId]/settings/notifications/pushover.tsx
@@ -1,10 +1,9 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../../../components/UserProfile/UserSettings';
-import UserNotificationSettings from '../../../../../components/UserProfile/UserSettings/UserNotificationSettings';
-import UserNotificationsPushover from '../../../../../components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushover';
-import useRouteGuard from '../../../../../hooks/useRouteGuard';
-import { Permission } from '../../../../../hooks/useUser';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserNotificationSettings from '@app/components/UserProfile/UserSettings/UserNotificationSettings';
+import UserNotificationsPushover from '@app/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsPushover';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const NotificationsPage: NextPage = () => {
   useRouteGuard(Permission.MANAGE_USERS);
diff --git a/src/pages/users/[userId]/settings/notifications/telegram.tsx b/src/pages/users/[userId]/settings/notifications/telegram.tsx
index d26ad8b4..62572b36 100644
--- a/src/pages/users/[userId]/settings/notifications/telegram.tsx
+++ b/src/pages/users/[userId]/settings/notifications/telegram.tsx
@@ -1,10 +1,9 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../../../components/UserProfile/UserSettings';
-import UserNotificationSettings from '../../../../../components/UserProfile/UserSettings/UserNotificationSettings';
-import UserNotificationsTelegram from '../../../../../components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsTelegram';
-import useRouteGuard from '../../../../../hooks/useRouteGuard';
-import { Permission } from '../../../../../hooks/useUser';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserNotificationSettings from '@app/components/UserProfile/UserSettings/UserNotificationSettings';
+import UserNotificationsTelegram from '@app/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsTelegram';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const NotificationsPage: NextPage = () => {
   useRouteGuard(Permission.MANAGE_USERS);
diff --git a/src/pages/users/[userId]/settings/notifications/webpush.tsx b/src/pages/users/[userId]/settings/notifications/webpush.tsx
index ddba1e3f..cb9d27a4 100644
--- a/src/pages/users/[userId]/settings/notifications/webpush.tsx
+++ b/src/pages/users/[userId]/settings/notifications/webpush.tsx
@@ -1,10 +1,9 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../../../components/UserProfile/UserSettings';
-import UserNotificationSettings from '../../../../../components/UserProfile/UserSettings/UserNotificationSettings';
-import UserWebPushSettings from '../../../../../components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsWebPush';
-import useRouteGuard from '../../../../../hooks/useRouteGuard';
-import { Permission } from '../../../../../hooks/useUser';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserNotificationSettings from '@app/components/UserProfile/UserSettings/UserNotificationSettings';
+import UserWebPushSettings from '@app/components/UserProfile/UserSettings/UserNotificationSettings/UserNotificationsWebPush';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const WebPushNotificationsPage: NextPage = () => {
   useRouteGuard(Permission.MANAGE_USERS);
diff --git a/src/pages/users/[userId]/settings/password.tsx b/src/pages/users/[userId]/settings/password.tsx
index ee1da6b9..f9c9c105 100644
--- a/src/pages/users/[userId]/settings/password.tsx
+++ b/src/pages/users/[userId]/settings/password.tsx
@@ -1,9 +1,8 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../../components/UserProfile/UserSettings';
-import UserPasswordChange from '../../../../components/UserProfile/UserSettings/UserPasswordChange';
-import useRouteGuard from '../../../../hooks/useRouteGuard';
-import { Permission } from '../../../../hooks/useUser';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserPasswordChange from '@app/components/UserProfile/UserSettings/UserPasswordChange';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const UserPassswordPage: NextPage = () => {
   useRouteGuard(Permission.MANAGE_USERS);
diff --git a/src/pages/users/[userId]/settings/permissions.tsx b/src/pages/users/[userId]/settings/permissions.tsx
index 82668936..23b218a4 100644
--- a/src/pages/users/[userId]/settings/permissions.tsx
+++ b/src/pages/users/[userId]/settings/permissions.tsx
@@ -1,9 +1,8 @@
-import { NextPage } from 'next';
-import React from 'react';
-import UserSettings from '../../../../components/UserProfile/UserSettings';
-import UserPermissions from '../../../../components/UserProfile/UserSettings/UserPermissions';
-import useRouteGuard from '../../../../hooks/useRouteGuard';
-import { Permission } from '../../../../hooks/useUser';
+import UserSettings from '@app/components/UserProfile/UserSettings';
+import UserPermissions from '@app/components/UserProfile/UserSettings/UserPermissions';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
 
 const UserPermissionsPage: NextPage = () => {
   useRouteGuard(Permission.MANAGE_USERS);
diff --git a/src/pages/users/[userId]/watchlist.tsx b/src/pages/users/[userId]/watchlist.tsx
new file mode 100644
index 00000000..3298bf61
--- /dev/null
+++ b/src/pages/users/[userId]/watchlist.tsx
@@ -0,0 +1,13 @@
+import DiscoverWatchlist from '@app/components/Discover/DiscoverWatchlist';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
+import type { NextPage } from 'next';
+
+const UserRequestsPage: NextPage = () => {
+  useRouteGuard([Permission.MANAGE_REQUESTS, Permission.WATCHLIST_VIEW], {
+    type: 'or',
+  });
+  return <DiscoverWatchlist />;
+};
+
+export default UserRequestsPage;
diff --git a/src/pages/users/index.tsx b/src/pages/users/index.tsx
index 25351b0e..53310504 100644
--- a/src/pages/users/index.tsx
+++ b/src/pages/users/index.tsx
@@ -1,8 +1,7 @@
-import React from 'react';
+import UserList from '@app/components/UserList';
+import useRouteGuard from '@app/hooks/useRouteGuard';
+import { Permission } from '@app/hooks/useUser';
 import type { NextPage } from 'next';
-import UserList from '../../components/UserList';
-import useRouteGuard from '../../hooks/useRouteGuard';
-import { Permission } from '../../hooks/useUser';
 
 const UsersPage: NextPage = () => {
   useRouteGuard(Permission.MANAGE_USERS);
diff --git a/src/styles/globals.css b/src/styles/globals.css
index 203b6a1c..a5f417dd 100644
--- a/src/styles/globals.css
+++ b/src/styles/globals.css
@@ -11,6 +11,7 @@
 
   body {
     @apply bg-gray-900;
+    overscroll-behavior-y: contain;
   }
 
   code {
@@ -36,8 +37,8 @@
   }
 
   .slideover {
-    padding-top: calc(1.5rem + env(safe-area-inset-top));
-    padding-bottom: 1.5rem;
+    padding-top: calc(1rem + env(safe-area-inset-top)) !important;
+    padding-bottom: calc(1rem + env(safe-area-inset-top)) !important;
   }
 
   .sidebar-close-button {
@@ -184,11 +185,11 @@
   }
 
   .media-ratings {
-    @apply flex items-center justify-center border-b border-gray-700 px-4 py-2 font-medium last:border-b-0;
+    @apply flex items-center justify-center space-x-5 border-b border-gray-700 px-4 py-2 font-medium last:border-b-0;
   }
 
   .media-rating {
-    @apply mr-4 flex items-center last:mr-0;
+    @apply flex items-center space-x-1;
   }
 
   .error-message {
@@ -307,7 +308,7 @@
   }
 
   button.input-action {
-    @apply relative -ml-px inline-flex items-center border border-gray-500 bg-indigo-600 px-3 py-2 text-sm font-medium leading-5 text-white transition duration-150 ease-in-out last:rounded-r-md hover:bg-indigo-500 active:bg-gray-100 active:text-gray-700 sm:px-3.5;
+    @apply relative -ml-px inline-flex items-center border border-gray-500 bg-indigo-600 bg-opacity-80 px-3 py-2 text-sm font-medium leading-5 text-white transition duration-150 ease-in-out last:rounded-r-md hover:bg-opacity-100 active:bg-gray-100 active:text-gray-700 sm:px-3.5;
   }
 
   .button-md svg,
@@ -320,14 +321,6 @@
     @apply ml-1.5 mr-1.5 h-4 w-4 first:ml-0 last:mr-0;
   }
 
-  .modal-icon {
-    @apply mx-auto flex h-12 w-12 flex-shrink-0 items-center justify-center rounded-full bg-gray-800 text-white ring-1 ring-gray-500 sm:mx-0 sm:h-10 sm:w-10;
-  }
-
-  .modal-icon svg {
-    @apply h-6 w-6;
-  }
-
   svg.icon-md {
     @apply h-5 w-5;
   }
@@ -451,9 +444,32 @@
     scrollbar-width: none; /* Firefox */
   }
 
+  .text-overseerr {
+    @apply bg-gradient-to-br from-indigo-400 to-purple-400 bg-clip-text text-transparent;
+  }
+
   @media all and (display-mode: browser) {
     .pwa-only {
       @apply hidden;
     }
   }
 }
+
+.ptr--ptr {
+  box-shadow: initial !important;
+  position: absolute !important;
+  z-index: 30 !important;
+}
+
+.ptr--refresh {
+  overflow: visible !important;
+  z-index: 30 !important;
+}
+
+.ptr--pull {
+  z-index: 30 !important;
+}
+
+.ptr--box {
+  margin-bottom: -13px !important;
+}
diff --git a/src/types/react-intl-auto.d.ts b/src/types/react-intl-auto.d.ts
index 23216860..7fa708a7 100644
--- a/src/types/react-intl-auto.d.ts
+++ b/src/types/react-intl-auto.d.ts
@@ -1,4 +1,4 @@
-import { MessageDescriptor } from 'react-intl';
+import type { MessageDescriptor } from 'react-intl';
 
 declare module 'react-intl' {
   interface ExtractableMessage {
diff --git a/src/utils/creditHelpers.ts b/src/utils/creditHelpers.ts
index 929f529d..7bbe9206 100644
--- a/src/utils/creditHelpers.ts
+++ b/src/utils/creditHelpers.ts
@@ -1,4 +1,4 @@
-import { Crew } from '../../server/models/common';
+import type { Crew } from '@server/models/common';
 const priorityJobs = [
   'Director',
   'Creator',
diff --git a/src/utils/polyfillIntl.ts b/src/utils/polyfillIntl.ts
new file mode 100644
index 00000000..fcaaa854
--- /dev/null
+++ b/src/utils/polyfillIntl.ts
@@ -0,0 +1,37 @@
+import { shouldPolyfill as shouldPolyfillDisplayNames } from '@formatjs/intl-displaynames/should-polyfill';
+import { shouldPolyfill as shouldPolyfillLocale } from '@formatjs/intl-locale/should-polyfill';
+import { shouldPolyfill as shouldPolyfillPluralrules } from '@formatjs/intl-pluralrules/should-polyfill';
+
+const polyfillLocale = async () => {
+  if (shouldPolyfillLocale()) {
+    await import('@formatjs/intl-locale/polyfill');
+  }
+};
+
+const polyfillPluralRules = async (locale: string) => {
+  const unsupportedLocale = shouldPolyfillPluralrules(locale);
+  // This locale is supported
+  if (!unsupportedLocale) {
+    return;
+  }
+  // Load the polyfill 1st BEFORE loading data
+  await import('@formatjs/intl-pluralrules/polyfill-force');
+  await import(`@formatjs/intl-pluralrules/locale-data/${unsupportedLocale}`);
+};
+
+const polyfillDisplayNames = async (locale: string) => {
+  const unsupportedLocale = shouldPolyfillDisplayNames(locale);
+  // This locale is supported
+  if (!unsupportedLocale) {
+    return;
+  }
+  // Load the polyfill 1st BEFORE loading data
+  await import('@formatjs/intl-displaynames/polyfill-force');
+  await import(`@formatjs/intl-displaynames/locale-data/${unsupportedLocale}`);
+};
+
+export const polyfillIntl = async (locale: string) => {
+  await polyfillLocale();
+  await polyfillPluralRules(locale);
+  await polyfillDisplayNames(locale);
+};
diff --git a/tailwind.config.js b/tailwind.config.js
index d1d023c0..96b5faad 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1,6 +1,7 @@
 // eslint-disable-next-line @typescript-eslint/no-var-requires
 const defaultTheme = require('tailwindcss/defaultTheme');
 
+/** @type {import('tailwindcss').Config} */
 module.exports = {
   mode: 'jit',
   content: ['./src/pages/**/*.{ts,tsx}', './src/components/**/*.{ts,tsx}'],
diff --git a/tsconfig.json b/tsconfig.json
index 41611f7d..5edcfbfe 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -17,7 +17,12 @@
     "experimentalDecorators": true,
     "emitDecoratorMetadata": true,
     "useUnknownInCatchVariables": false,
-    "incremental": true
+    "incremental": true,
+    "baseUrl": "src",
+    "paths": {
+      "@server/*": ["../server/*"],
+      "@app/*": ["*"]
+    }
   },
   "include": ["next-env.d.ts", "src/**/*.ts", "src/**/*.tsx"],
   "exclude": ["node_modules"]
diff --git a/yarn.lock b/yarn.lock
index b32edc90..3036e822 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3,11 +3,12 @@
 
 
 "@ampproject/remapping@^2.1.0":
-  version "2.1.2"
-  resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34"
-  integrity sha512-hoyByceqwKirw7w3Z7gnIIZC3Wx3J484Y3L/cMpXFbr7d9ZQj2mODrirNzcJa+SM3UlpWXYvKV4RlRpFXlWgXg==
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d"
+  integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==
   dependencies:
-    "@jridgewell/trace-mapping" "^0.3.0"
+    "@jridgewell/gen-mapping" "^0.1.0"
+    "@jridgewell/trace-mapping" "^0.3.9"
 
 "@apidevtools/json-schema-ref-parser@9.0.9":
   version "9.0.9"
@@ -19,19 +20,18 @@
     call-me-maybe "^1.0.1"
     js-yaml "^4.1.0"
 
-"@babel/cli@^7.17.6":
-  version "7.17.6"
-  resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.17.6.tgz#169e5935f1795f0b62ded5a2accafeedfe5c5363"
-  integrity sha512-l4w608nsDNlxZhiJ5tE3DbNmr61fIKMZ6fTBo171VEFuFMIYuJ3mHRhTLEkKKyvx2Mizkkv/0a8OJOnZqkKYNA==
+"@babel/cli@7.18.10":
+  version "7.18.10"
+  resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.18.10.tgz#4211adfc45ffa7d4f3cee6b60bb92e9fe68fe56a"
+  integrity sha512-dLvWH+ZDFAkd2jPBSghrsFBuXrREvFwjpDycXbmUoeochqKYe4zNSLEJYErpLg8dvxvZYe79/MkN461XCwpnGw==
   dependencies:
-    "@jridgewell/trace-mapping" "^0.3.4"
+    "@jridgewell/trace-mapping" "^0.3.8"
     commander "^4.0.1"
     convert-source-map "^1.1.0"
     fs-readdir-recursive "^1.1.0"
-    glob "^7.0.0"
+    glob "^7.2.0"
     make-dir "^2.1.0"
     slash "^2.0.0"
-    source-map "^0.5.0"
   optionalDependencies:
     "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents.3"
     chokidar "^3.4.0"
@@ -43,40 +43,82 @@
   dependencies:
     "@babel/highlight" "^7.16.7"
 
-"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.4", "@babel/compat-data@^7.16.8", "@babel/compat-data@^7.17.0":
-  version "7.17.0"
-  resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.0.tgz#86850b8597ea6962089770952075dcaabb8dba34"
-  integrity sha512-392byTlpGWXMv4FbyWw3sAZ/FrW/DrwqLGXpy0mbyNe9Taqv1mg9yON5/o0cnr8XYCkFTZbC1eV+c+LAROgrng==
+"@babel/code-frame@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a"
+  integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==
+  dependencies:
+    "@babel/highlight" "^7.18.6"
+
+"@babel/compat-data@^7.17.10":
+  version "7.17.10"
+  resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.10.tgz#711dc726a492dfc8be8220028b1b92482362baab"
+  integrity sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==
+
+"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.18.8":
+  version "7.18.8"
+  resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.8.tgz#2483f565faca607b8535590e84e7de323f27764d"
+  integrity sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==
 
-"@babel/core@^7.15.5", "@babel/core@^7.9.0":
-  version "7.17.5"
-  resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.17.5.tgz#6cd2e836058c28f06a4ca8ee7ed955bbf37c8225"
-  integrity sha512-/BBMw4EvjmyquN5O+t5eh0+YqB3XXJkYD2cjKpYtWOfFy4lQ4UozNSmxAcWT8r2XtZs0ewG+zrfsqeR15i1ajA==
+"@babel/core@^7.18.5":
+  version "7.18.10"
+  resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.10.tgz#39ad504991d77f1f3da91be0b8b949a5bc466fb8"
+  integrity sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==
+  dependencies:
+    "@ampproject/remapping" "^2.1.0"
+    "@babel/code-frame" "^7.18.6"
+    "@babel/generator" "^7.18.10"
+    "@babel/helper-compilation-targets" "^7.18.9"
+    "@babel/helper-module-transforms" "^7.18.9"
+    "@babel/helpers" "^7.18.9"
+    "@babel/parser" "^7.18.10"
+    "@babel/template" "^7.18.10"
+    "@babel/traverse" "^7.18.10"
+    "@babel/types" "^7.18.10"
+    convert-source-map "^1.7.0"
+    debug "^4.1.0"
+    gensync "^1.0.0-beta.2"
+    json5 "^2.2.1"
+    semver "^6.3.0"
+
+"@babel/core@^7.9.0":
+  version "7.18.2"
+  resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.2.tgz#87b2fcd7cce9becaa7f5acebdc4f09f3dd19d876"
+  integrity sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ==
   dependencies:
     "@ampproject/remapping" "^2.1.0"
     "@babel/code-frame" "^7.16.7"
-    "@babel/generator" "^7.17.3"
-    "@babel/helper-compilation-targets" "^7.16.7"
-    "@babel/helper-module-transforms" "^7.16.7"
-    "@babel/helpers" "^7.17.2"
-    "@babel/parser" "^7.17.3"
+    "@babel/generator" "^7.18.2"
+    "@babel/helper-compilation-targets" "^7.18.2"
+    "@babel/helper-module-transforms" "^7.18.0"
+    "@babel/helpers" "^7.18.2"
+    "@babel/parser" "^7.18.0"
     "@babel/template" "^7.16.7"
-    "@babel/traverse" "^7.17.3"
-    "@babel/types" "^7.17.0"
+    "@babel/traverse" "^7.18.2"
+    "@babel/types" "^7.18.2"
     convert-source-map "^1.7.0"
     debug "^4.1.0"
     gensync "^1.0.0-beta.2"
-    json5 "^2.1.2"
+    json5 "^2.2.1"
     semver "^6.3.0"
 
-"@babel/generator@^7.17.3":
-  version "7.17.3"
-  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.17.3.tgz#a2c30b0c4f89858cb87050c3ffdfd36bdf443200"
-  integrity sha512-+R6Dctil/MgUsZsZAkYgK+ADNSZzJRRy0TvY65T71z/CR854xHQ1EweBYXdfT+HNeN7w0cSJJEzgxZMv40pxsg==
+"@babel/generator@^7.18.10":
+  version "7.18.12"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.12.tgz#fa58daa303757bd6f5e4bbca91b342040463d9f4"
+  integrity sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==
   dependencies:
-    "@babel/types" "^7.17.0"
+    "@babel/types" "^7.18.10"
+    "@jridgewell/gen-mapping" "^0.3.2"
+    jsesc "^2.5.1"
+
+"@babel/generator@^7.18.2":
+  version "7.18.2"
+  resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.2.tgz#33873d6f89b21efe2da63fe554460f3df1c5880d"
+  integrity sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==
+  dependencies:
+    "@babel/types" "^7.18.2"
+    "@jridgewell/gen-mapping" "^0.3.0"
     jsesc "^2.5.1"
-    source-map "^0.5.0"
 
 "@babel/helper-annotate-as-pure@^7.16.7":
   version "7.16.7"
@@ -85,88 +127,114 @@
   dependencies:
     "@babel/types" "^7.16.7"
 
-"@babel/helper-builder-binary-assignment-operator-visitor@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz#38d138561ea207f0f69eb1626a418e4f7e6a580b"
-  integrity sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==
+"@babel/helper-annotate-as-pure@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb"
+  integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==
   dependencies:
-    "@babel/helper-explode-assignable-expression" "^7.16.7"
-    "@babel/types" "^7.16.7"
+    "@babel/types" "^7.18.6"
 
-"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.7.tgz#06e66c5f299601e6c7da350049315e83209d551b"
-  integrity sha512-mGojBwIWcwGD6rfqgRXVlVYmPAv7eOpIemUG3dGnDdCY4Pae70ROij3XmfrH6Fa1h1aiDylpglbZyktfzyo/hA==
+"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb"
+  integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==
   dependencies:
-    "@babel/compat-data" "^7.16.4"
+    "@babel/helper-explode-assignable-expression" "^7.18.6"
+    "@babel/types" "^7.18.9"
+
+"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz#69e64f57b524cde3e5ff6cc5a9f4a387ee5563bf"
+  integrity sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==
+  dependencies:
+    "@babel/compat-data" "^7.18.8"
+    "@babel/helper-validator-option" "^7.18.6"
+    browserslist "^4.20.2"
+    semver "^6.3.0"
+
+"@babel/helper-compilation-targets@^7.18.2":
+  version "7.18.2"
+  resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz#67a85a10cbd5fc7f1457fec2e7f45441dc6c754b"
+  integrity sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==
+  dependencies:
+    "@babel/compat-data" "^7.17.10"
     "@babel/helper-validator-option" "^7.16.7"
-    browserslist "^4.17.5"
+    browserslist "^4.20.2"
     semver "^6.3.0"
 
-"@babel/helper-create-class-features-plugin@^7.16.10", "@babel/helper-create-class-features-plugin@^7.16.7", "@babel/helper-create-class-features-plugin@^7.17.6":
-  version "7.17.6"
-  resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.17.6.tgz#3778c1ed09a7f3e65e6d6e0f6fbfcc53809d92c9"
-  integrity sha512-SogLLSxXm2OkBbSsHZMM4tUi8fUzjs63AT/d0YQIzr6GSd8Hxsbk2KYDX0k0DweAzGMj/YWeiCsorIdtdcW8Eg==
+"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.9.tgz#d802ee16a64a9e824fcbf0a2ffc92f19d58550ce"
+  integrity sha512-WvypNAYaVh23QcjpMR24CwZY2Nz6hqdOcFdPbNpV56hL5H6KiFheO7Xm1aPdlLQ7d5emYZX7VZwPp9x3z+2opw==
   dependencies:
-    "@babel/helper-annotate-as-pure" "^7.16.7"
-    "@babel/helper-environment-visitor" "^7.16.7"
-    "@babel/helper-function-name" "^7.16.7"
-    "@babel/helper-member-expression-to-functions" "^7.16.7"
-    "@babel/helper-optimise-call-expression" "^7.16.7"
-    "@babel/helper-replace-supers" "^7.16.7"
-    "@babel/helper-split-export-declaration" "^7.16.7"
+    "@babel/helper-annotate-as-pure" "^7.18.6"
+    "@babel/helper-environment-visitor" "^7.18.9"
+    "@babel/helper-function-name" "^7.18.9"
+    "@babel/helper-member-expression-to-functions" "^7.18.9"
+    "@babel/helper-optimise-call-expression" "^7.18.6"
+    "@babel/helper-replace-supers" "^7.18.9"
+    "@babel/helper-split-export-declaration" "^7.18.6"
 
-"@babel/helper-create-regexp-features-plugin@^7.16.7":
-  version "7.17.0"
-  resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.0.tgz#1dcc7d40ba0c6b6b25618997c5dbfd310f186fe1"
-  integrity sha512-awO2So99wG6KnlE+TPs6rn83gCz5WlEePJDTnLEqbchMVrBeAujURVphRdigsk094VhvZehFoNOihSlcBjwsXA==
+"@babel/helper-create-regexp-features-plugin@^7.16.7", "@babel/helper-create-regexp-features-plugin@^7.17.12":
+  version "7.17.12"
+  resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.12.tgz#bb37ca467f9694bbe55b884ae7a5cc1e0084e4fd"
+  integrity sha512-b2aZrV4zvutr9AIa6/gA3wsZKRwTKYoDxYiFKcESS3Ug2GTXzwBEvMuuFLhCQpEnRXs1zng4ISAXSUxxKBIcxw==
   dependencies:
     "@babel/helper-annotate-as-pure" "^7.16.7"
     regexpu-core "^5.0.1"
 
-"@babel/helper-define-polyfill-provider@^0.3.1":
-  version "0.3.1"
-  resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz#52411b445bdb2e676869e5a74960d2d3826d2665"
-  integrity sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==
+"@babel/helper-create-regexp-features-plugin@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz#3e35f4e04acbbf25f1b3534a657610a000543d3c"
+  integrity sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A==
   dependencies:
-    "@babel/helper-compilation-targets" "^7.13.0"
-    "@babel/helper-module-imports" "^7.12.13"
-    "@babel/helper-plugin-utils" "^7.13.0"
-    "@babel/traverse" "^7.13.0"
+    "@babel/helper-annotate-as-pure" "^7.18.6"
+    regexpu-core "^5.1.0"
+
+"@babel/helper-define-polyfill-provider@^0.3.2":
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.2.tgz#bd10d0aca18e8ce012755395b05a79f45eca5073"
+  integrity sha512-r9QJJ+uDWrd+94BSPcP6/de67ygLtvVy6cK4luE6MOuDsZIdoaPBnfSpbO/+LTifjPckbKXRuI9BB/Z2/y3iTg==
+  dependencies:
+    "@babel/helper-compilation-targets" "^7.17.7"
+    "@babel/helper-plugin-utils" "^7.16.7"
     debug "^4.1.1"
     lodash.debounce "^4.0.8"
     resolve "^1.14.2"
     semver "^6.1.2"
 
-"@babel/helper-environment-visitor@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.16.7.tgz#ff484094a839bde9d89cd63cba017d7aae80ecd7"
-  integrity sha512-SLLb0AAn6PkUeAfKJCCOl9e1R53pQlGAfc4y4XuMRZfqeMYLE0dM1LMhqbGAlGQY0lfw5/ohoYWAe9V1yibRag==
-  dependencies:
-    "@babel/types" "^7.16.7"
+"@babel/helper-environment-visitor@^7.16.7", "@babel/helper-environment-visitor@^7.18.2":
+  version "7.18.2"
+  resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz#8a6d2dedb53f6bf248e31b4baf38739ee4a637bd"
+  integrity sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==
 
-"@babel/helper-explode-assignable-expression@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz#12a6d8522fdd834f194e868af6354e8650242b7a"
-  integrity sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==
+"@babel/helper-environment-visitor@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be"
+  integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==
+
+"@babel/helper-explode-assignable-expression@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096"
+  integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==
   dependencies:
-    "@babel/types" "^7.16.7"
+    "@babel/types" "^7.18.6"
 
-"@babel/helper-function-name@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.7.tgz#f1ec51551fb1c8956bc8dd95f38523b6cf375f8f"
-  integrity sha512-QfDfEnIUyyBSR3HtrtGECuZ6DAyCkYFp7GHl75vFtTnn6pjKeK0T1DB5lLkFvBea8MdaiUABx3osbgLyInoejA==
+"@babel/helper-function-name@^7.17.9":
+  version "7.17.9"
+  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz#136fcd54bc1da82fcb47565cf16fd8e444b1ff12"
+  integrity sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==
   dependencies:
-    "@babel/helper-get-function-arity" "^7.16.7"
     "@babel/template" "^7.16.7"
-    "@babel/types" "^7.16.7"
+    "@babel/types" "^7.17.0"
 
-"@babel/helper-get-function-arity@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.7.tgz#ea08ac753117a669f1508ba06ebcc49156387419"
-  integrity sha512-flc+RLSOBXzNzVhcLu6ujeHUrD6tANAOU5ojrRx/as+tbzf8+stUCj7+IfRRoAbEZqj/ahXEMsjhOhgeZsrnTw==
+"@babel/helper-function-name@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz#940e6084a55dee867d33b4e487da2676365e86b0"
+  integrity sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==
   dependencies:
-    "@babel/types" "^7.16.7"
+    "@babel/template" "^7.18.6"
+    "@babel/types" "^7.18.9"
 
 "@babel/helper-hoist-variables@^7.16.7":
   version "7.16.7"
@@ -175,12 +243,19 @@
   dependencies:
     "@babel/types" "^7.16.7"
 
-"@babel/helper-member-expression-to-functions@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.7.tgz#42b9ca4b2b200123c3b7e726b0ae5153924905b0"
-  integrity sha512-VtJ/65tYiU/6AbMTDwyoXGPKHgTsfRarivm+YbB5uAzKUyuPjgZSgAFeG87FCigc7KNHu2Pegh1XIT3lXjvz3Q==
+"@babel/helper-hoist-variables@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678"
+  integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==
   dependencies:
-    "@babel/types" "^7.16.7"
+    "@babel/types" "^7.18.6"
+
+"@babel/helper-member-expression-to-functions@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815"
+  integrity sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==
+  dependencies:
+    "@babel/types" "^7.18.9"
 
 "@babel/helper-module-imports@^7.0.0", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7":
   version "7.16.7"
@@ -189,65 +264,99 @@
   dependencies:
     "@babel/types" "^7.16.7"
 
-"@babel/helper-module-transforms@^7.16.7":
-  version "7.17.6"
-  resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.17.6.tgz#3c3b03cc6617e33d68ef5a27a67419ac5199ccd0"
-  integrity sha512-2ULmRdqoOMpdvkbT8jONrZML/XALfzxlb052bldftkicAUy8AxSCkD5trDPQcwHNmolcl7wP6ehNqMlyUw6AaA==
+"@babel/helper-module-imports@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e"
+  integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==
+  dependencies:
+    "@babel/types" "^7.18.6"
+
+"@babel/helper-module-transforms@^7.18.0":
+  version "7.18.0"
+  resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz#baf05dec7a5875fb9235bd34ca18bad4e21221cd"
+  integrity sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==
   dependencies:
     "@babel/helper-environment-visitor" "^7.16.7"
     "@babel/helper-module-imports" "^7.16.7"
-    "@babel/helper-simple-access" "^7.16.7"
+    "@babel/helper-simple-access" "^7.17.7"
     "@babel/helper-split-export-declaration" "^7.16.7"
     "@babel/helper-validator-identifier" "^7.16.7"
     "@babel/template" "^7.16.7"
-    "@babel/traverse" "^7.17.3"
-    "@babel/types" "^7.17.0"
-
-"@babel/helper-optimise-call-expression@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz#a34e3560605abbd31a18546bd2aad3e6d9a174f2"
-  integrity sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==
-  dependencies:
-    "@babel/types" "^7.16.7"
-
-"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.16.7.tgz#aa3a8ab4c3cceff8e65eb9e73d87dc4ff320b2f5"
-  integrity sha512-Qg3Nk7ZxpgMrsox6HreY1ZNKdBq7K72tDSliA6dCl5f007jR4ne8iD5UzuNnCJH2xBf2BEEVGr+/OL6Gdp7RxA==
-
-"@babel/helper-remap-async-to-generator@^7.16.8":
-  version "7.16.8"
-  resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz#29ffaade68a367e2ed09c90901986918d25e57e3"
-  integrity sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==
-  dependencies:
-    "@babel/helper-annotate-as-pure" "^7.16.7"
-    "@babel/helper-wrap-function" "^7.16.8"
-    "@babel/types" "^7.16.8"
-
-"@babel/helper-replace-supers@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.7.tgz#e9f5f5f32ac90429c1a4bdec0f231ef0c2838ab1"
-  integrity sha512-y9vsWilTNaVnVh6xiJfABzsNpgDPKev9HnAgz6Gb1p6UUwf9NepdlsV7VXGCftJM+jqD5f7JIEubcpLjZj5dBw==
-  dependencies:
-    "@babel/helper-environment-visitor" "^7.16.7"
-    "@babel/helper-member-expression-to-functions" "^7.16.7"
-    "@babel/helper-optimise-call-expression" "^7.16.7"
-    "@babel/traverse" "^7.16.7"
-    "@babel/types" "^7.16.7"
-
-"@babel/helper-simple-access@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.7.tgz#d656654b9ea08dbb9659b69d61063ccd343ff0f7"
-  integrity sha512-ZIzHVyoeLMvXMN/vok/a4LWRy8G2v205mNP0XOuf9XRLyX5/u9CnVulUtDgUTama3lT+bf/UqucuZjqiGuTS1g==
-  dependencies:
-    "@babel/types" "^7.16.7"
-
-"@babel/helper-skip-transparent-expression-wrappers@^7.16.0":
-  version "7.16.0"
-  resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09"
-  integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==
-  dependencies:
-    "@babel/types" "^7.16.0"
+    "@babel/traverse" "^7.18.0"
+    "@babel/types" "^7.18.0"
+
+"@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz#5a1079c005135ed627442df31a42887e80fcb712"
+  integrity sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==
+  dependencies:
+    "@babel/helper-environment-visitor" "^7.18.9"
+    "@babel/helper-module-imports" "^7.18.6"
+    "@babel/helper-simple-access" "^7.18.6"
+    "@babel/helper-split-export-declaration" "^7.18.6"
+    "@babel/helper-validator-identifier" "^7.18.6"
+    "@babel/template" "^7.18.6"
+    "@babel/traverse" "^7.18.9"
+    "@babel/types" "^7.18.9"
+
+"@babel/helper-optimise-call-expression@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe"
+  integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==
+  dependencies:
+    "@babel/types" "^7.18.6"
+
+"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.17.12", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
+  version "7.17.12"
+  resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz#86c2347da5acbf5583ba0a10aed4c9bf9da9cf96"
+  integrity sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==
+
+"@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz#4b8aea3b069d8cb8a72cdfe28ddf5ceca695ef2f"
+  integrity sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==
+
+"@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519"
+  integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==
+  dependencies:
+    "@babel/helper-annotate-as-pure" "^7.18.6"
+    "@babel/helper-environment-visitor" "^7.18.9"
+    "@babel/helper-wrap-function" "^7.18.9"
+    "@babel/types" "^7.18.9"
+
+"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz#1092e002feca980fbbb0bd4d51b74a65c6a500e6"
+  integrity sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==
+  dependencies:
+    "@babel/helper-environment-visitor" "^7.18.9"
+    "@babel/helper-member-expression-to-functions" "^7.18.9"
+    "@babel/helper-optimise-call-expression" "^7.18.6"
+    "@babel/traverse" "^7.18.9"
+    "@babel/types" "^7.18.9"
+
+"@babel/helper-simple-access@^7.17.7":
+  version "7.18.2"
+  resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz#4dc473c2169ac3a1c9f4a51cfcd091d1c36fcff9"
+  integrity sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==
+  dependencies:
+    "@babel/types" "^7.18.2"
+
+"@babel/helper-simple-access@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz#d6d8f51f4ac2978068df934b569f08f29788c7ea"
+  integrity sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==
+  dependencies:
+    "@babel/types" "^7.18.6"
+
+"@babel/helper-skip-transparent-expression-wrappers@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz#778d87b3a758d90b471e7b9918f34a9a02eb5818"
+  integrity sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==
+  dependencies:
+    "@babel/types" "^7.18.9"
 
 "@babel/helper-split-export-declaration@^7.16.7":
   version "7.16.7"
@@ -256,192 +365,246 @@
   dependencies:
     "@babel/types" "^7.16.7"
 
+"@babel/helper-split-export-declaration@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075"
+  integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==
+  dependencies:
+    "@babel/types" "^7.18.6"
+
+"@babel/helper-string-parser@^7.18.10":
+  version "7.18.10"
+  resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz#181f22d28ebe1b3857fa575f5c290b1aaf659b56"
+  integrity sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==
+
 "@babel/helper-validator-identifier@^7.16.7":
   version "7.16.7"
   resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad"
   integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==
 
+"@babel/helper-validator-identifier@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz#9c97e30d31b2b8c72a1d08984f2ca9b574d7a076"
+  integrity sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==
+
 "@babel/helper-validator-option@^7.16.7":
   version "7.16.7"
   resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23"
   integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==
 
-"@babel/helper-wrap-function@^7.16.8":
-  version "7.16.8"
-  resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz#58afda087c4cd235de92f7ceedebca2c41274200"
-  integrity sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==
+"@babel/helper-validator-option@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8"
+  integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==
+
+"@babel/helper-wrap-function@^7.18.9":
+  version "7.18.11"
+  resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.18.11.tgz#bff23ace436e3f6aefb61f85ffae2291c80ed1fb"
+  integrity sha512-oBUlbv+rjZLh2Ks9SKi4aL7eKaAXBWleHzU89mP0G6BMUlRxSckk9tSIkgDGydhgFxHuGSlBQZfnaD47oBEB7w==
   dependencies:
-    "@babel/helper-function-name" "^7.16.7"
-    "@babel/template" "^7.16.7"
-    "@babel/traverse" "^7.16.8"
-    "@babel/types" "^7.16.8"
+    "@babel/helper-function-name" "^7.18.9"
+    "@babel/template" "^7.18.10"
+    "@babel/traverse" "^7.18.11"
+    "@babel/types" "^7.18.10"
 
-"@babel/helpers@^7.17.2":
-  version "7.17.2"
-  resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.17.2.tgz#23f0a0746c8e287773ccd27c14be428891f63417"
-  integrity sha512-0Qu7RLR1dILozr/6M0xgj+DFPmi6Bnulgm9M8BVa9ZCWxDqlSnqt3cf8IDPB5m45sVXUZ0kuQAgUrdSFFH79fQ==
+"@babel/helpers@^7.18.2":
+  version "7.18.2"
+  resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.2.tgz#970d74f0deadc3f5a938bfa250738eb4ac889384"
+  integrity sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==
   dependencies:
     "@babel/template" "^7.16.7"
-    "@babel/traverse" "^7.17.0"
-    "@babel/types" "^7.17.0"
+    "@babel/traverse" "^7.18.2"
+    "@babel/types" "^7.18.2"
+
+"@babel/helpers@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.9.tgz#4bef3b893f253a1eced04516824ede94dcfe7ff9"
+  integrity sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==
+  dependencies:
+    "@babel/template" "^7.18.6"
+    "@babel/traverse" "^7.18.9"
+    "@babel/types" "^7.18.9"
 
 "@babel/highlight@^7.16.7":
-  version "7.16.10"
-  resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.10.tgz#744f2eb81579d6eea753c227b0f570ad785aba88"
-  integrity sha512-5FnTQLSLswEj6IkgVw5KusNUUFY9ZGqe/TRFnP/BKYHYgfh7tc+C7mwiy95/yNP7Dh9x580Vv8r7u7ZfTBFxdw==
+  version "7.17.12"
+  resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.12.tgz#257de56ee5afbd20451ac0a75686b6b404257351"
+  integrity sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==
   dependencies:
     "@babel/helper-validator-identifier" "^7.16.7"
     chalk "^2.0.0"
     js-tokens "^4.0.0"
 
-"@babel/parser@^7.1.0", "@babel/parser@^7.16.7", "@babel/parser@^7.17.3", "@babel/parser@^7.6.0", "@babel/parser@^7.9.6":
-  version "7.17.3"
-  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.3.tgz#b07702b982990bf6fdc1da5049a23fece4c5c3d0"
-  integrity sha512-7yJPvPV+ESz2IUTPbOL+YkIGyCqOyNIzdguKQuJGnH7bg1WTIifuM21YqokFt/THWh1AkCRn9IgoykTRCBVpzA==
+"@babel/highlight@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf"
+  integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==
+  dependencies:
+    "@babel/helper-validator-identifier" "^7.18.6"
+    chalk "^2.0.0"
+    js-tokens "^4.0.0"
 
-"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.7.tgz#4eda6d6c2a0aa79c70fa7b6da67763dfe2141050"
-  integrity sha512-anv/DObl7waiGEnC24O9zqL0pSuI9hljihqiDuFHC8d7/bjr/4RLGPWuc8rYOff/QPzbEPSkzG8wGG9aDuhHRg==
+"@babel/parser@^7.1.0", "@babel/parser@^7.16.7", "@babel/parser@^7.18.0", "@babel/parser@^7.6.0", "@babel/parser@^7.9.6":
+  version "7.18.4"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.4.tgz#6774231779dd700e0af29f6ad8d479582d7ce5ef"
+  integrity sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==
+
+"@babel/parser@^7.18.10", "@babel/parser@^7.18.11":
+  version "7.18.11"
+  resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.11.tgz#68bb07ab3d380affa9a3f96728df07969645d2d9"
+  integrity sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==
+
+"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2"
+  integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.6"
 
-"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.7.tgz#cc001234dfc139ac45f6bcf801866198c8c72ff9"
-  integrity sha512-di8vUHRdf+4aJ7ltXhaDbPoszdkh59AQtJM5soLsuHpQJdFQZOA4uGj0V2u/CZ8bJ/u8ULDL5yq6FO/bCXnKHw==
+"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz#a11af19aa373d68d561f08e0a57242350ed0ec50"
+  integrity sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
-    "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0"
-    "@babel/plugin-proposal-optional-chaining" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.9"
+    "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9"
+    "@babel/plugin-proposal-optional-chaining" "^7.18.9"
 
-"@babel/plugin-proposal-async-generator-functions@^7.16.8":
-  version "7.16.8"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.8.tgz#3bdd1ebbe620804ea9416706cd67d60787504bc8"
-  integrity sha512-71YHIvMuiuqWJQkebWJtdhQTfd4Q4mF76q2IX37uZPkG9+olBxsX+rH1vkhFto4UeJZ9dPY2s+mDvhDm1u2BGQ==
+"@babel/plugin-proposal-async-generator-functions@^7.18.10":
+  version "7.18.10"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.10.tgz#85ea478c98b0095c3e4102bff3b67d306ed24952"
+  integrity sha512-1mFuY2TOsR1hxbjCo4QL+qlIjV07p4H4EUYw2J/WCqsvFV6V9X9z9YhXbWndc/4fw+hYGlDT7egYxliMp5O6Ew==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
-    "@babel/helper-remap-async-to-generator" "^7.16.8"
+    "@babel/helper-environment-visitor" "^7.18.9"
+    "@babel/helper-plugin-utils" "^7.18.9"
+    "@babel/helper-remap-async-to-generator" "^7.18.9"
     "@babel/plugin-syntax-async-generators" "^7.8.4"
 
-"@babel/plugin-proposal-class-properties@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.7.tgz#925cad7b3b1a2fcea7e59ecc8eb5954f961f91b0"
-  integrity sha512-IobU0Xme31ewjYOShSIqd/ZGM/r/cuOz2z0MDbNrhF5FW+ZVgi0f2lyeoj9KFPDOAqsYxmLWZte1WOwlvY9aww==
+"@babel/plugin-proposal-class-properties@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3"
+  integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==
   dependencies:
-    "@babel/helper-create-class-features-plugin" "^7.16.7"
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-create-class-features-plugin" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
 
-"@babel/plugin-proposal-class-static-block@^7.16.7":
-  version "7.17.6"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.17.6.tgz#164e8fd25f0d80fa48c5a4d1438a6629325ad83c"
-  integrity sha512-X/tididvL2zbs7jZCeeRJ8167U/+Ac135AM6jCAx6gYXDUviZV5Ku9UDvWS2NCuWlFjIRXklYhwo6HhAC7ETnA==
+"@babel/plugin-proposal-class-static-block@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz#8aa81d403ab72d3962fc06c26e222dacfc9b9020"
+  integrity sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==
   dependencies:
-    "@babel/helper-create-class-features-plugin" "^7.17.6"
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-create-class-features-plugin" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
     "@babel/plugin-syntax-class-static-block" "^7.14.5"
 
-"@babel/plugin-proposal-dynamic-import@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz#c19c897eaa46b27634a00fee9fb7d829158704b2"
-  integrity sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==
+"@babel/plugin-proposal-dynamic-import@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz#72bcf8d408799f547d759298c3c27c7e7faa4d94"
+  integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.6"
     "@babel/plugin-syntax-dynamic-import" "^7.8.3"
 
-"@babel/plugin-proposal-export-namespace-from@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.7.tgz#09de09df18445a5786a305681423ae63507a6163"
-  integrity sha512-ZxdtqDXLRGBL64ocZcs7ovt71L3jhC1RGSyR996svrCi3PYqHNkb3SwPJCs8RIzD86s+WPpt2S73+EHCGO+NUA==
+"@babel/plugin-proposal-export-namespace-from@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz#5f7313ab348cdb19d590145f9247540e94761203"
+  integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.9"
     "@babel/plugin-syntax-export-namespace-from" "^7.8.3"
 
-"@babel/plugin-proposal-json-strings@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.7.tgz#9732cb1d17d9a2626a08c5be25186c195b6fa6e8"
-  integrity sha512-lNZ3EEggsGY78JavgbHsK9u5P3pQaW7k4axlgFLYkMd7UBsiNahCITShLjNQschPyjtO6dADrL24757IdhBrsQ==
+"@babel/plugin-proposal-json-strings@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz#7e8788c1811c393aff762817e7dbf1ebd0c05f0b"
+  integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.6"
     "@babel/plugin-syntax-json-strings" "^7.8.3"
 
-"@babel/plugin-proposal-logical-assignment-operators@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.7.tgz#be23c0ba74deec1922e639832904be0bea73cdea"
-  integrity sha512-K3XzyZJGQCr00+EtYtrDjmwX7o7PLK6U9bi1nCwkQioRFVUv6dJoxbQjtWVtP+bCPy82bONBKG8NPyQ4+i6yjg==
+"@babel/plugin-proposal-logical-assignment-operators@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz#8148cbb350483bf6220af06fa6db3690e14b2e23"
+  integrity sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.9"
     "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
 
-"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.7.tgz#141fc20b6857e59459d430c850a0011e36561d99"
-  integrity sha512-aUOrYU3EVtjf62jQrCj63pYZ7k6vns2h/DQvHPWGmsJRYzWXZ6/AsfgpiRy6XiuIDADhJzP2Q9MwSMKauBQ+UQ==
+"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1"
+  integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.6"
     "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
 
-"@babel/plugin-proposal-numeric-separator@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz#d6b69f4af63fb38b6ca2558442a7fb191236eba9"
-  integrity sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==
+"@babel/plugin-proposal-numeric-separator@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75"
+  integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.6"
     "@babel/plugin-syntax-numeric-separator" "^7.10.4"
 
-"@babel/plugin-proposal-object-rest-spread@^7.16.7":
-  version "7.17.3"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.17.3.tgz#d9eb649a54628a51701aef7e0ea3d17e2b9dd390"
-  integrity sha512-yuL5iQA/TbZn+RGAfxQXfi7CNLmKi1f8zInn4IgobuCWcAb7i+zj4TYzQ9l8cEzVyJ89PDGuqxK1xZpUDISesw==
+"@babel/plugin-proposal-object-rest-spread@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz#f9434f6beb2c8cae9dfcf97d2a5941bbbf9ad4e7"
+  integrity sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q==
   dependencies:
-    "@babel/compat-data" "^7.17.0"
-    "@babel/helper-compilation-targets" "^7.16.7"
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/compat-data" "^7.18.8"
+    "@babel/helper-compilation-targets" "^7.18.9"
+    "@babel/helper-plugin-utils" "^7.18.9"
     "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
-    "@babel/plugin-transform-parameters" "^7.16.7"
+    "@babel/plugin-transform-parameters" "^7.18.8"
 
-"@babel/plugin-proposal-optional-catch-binding@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz#c623a430674ffc4ab732fd0a0ae7722b67cb74cf"
-  integrity sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==
+"@babel/plugin-proposal-optional-catch-binding@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb"
+  integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.6"
     "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
 
-"@babel/plugin-proposal-optional-chaining@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.7.tgz#7cd629564724816c0e8a969535551f943c64c39a"
-  integrity sha512-eC3xy+ZrUcBtP7x+sq62Q/HYd674pPTb/77XZMb5wbDPGWIdUbSr4Agr052+zaUPSb+gGRnjxXfKFvx5iMJ+DA==
+"@babel/plugin-proposal-optional-chaining@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz#e8e8fe0723f2563960e4bf5e9690933691915993"
+  integrity sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
-    "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0"
+    "@babel/helper-plugin-utils" "^7.18.9"
+    "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9"
     "@babel/plugin-syntax-optional-chaining" "^7.8.3"
 
-"@babel/plugin-proposal-private-methods@^7.16.11":
-  version "7.16.11"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.11.tgz#e8df108288555ff259f4527dbe84813aac3a1c50"
-  integrity sha512-F/2uAkPlXDr8+BHpZvo19w3hLFKge+k75XUprE6jaqKxjGkSYcK+4c+bup5PdW/7W/Rpjwql7FTVEDW+fRAQsw==
+"@babel/plugin-proposal-private-methods@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea"
+  integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==
   dependencies:
-    "@babel/helper-create-class-features-plugin" "^7.16.10"
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-create-class-features-plugin" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
 
-"@babel/plugin-proposal-private-property-in-object@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.7.tgz#b0b8cef543c2c3d57e59e2c611994861d46a3fce"
-  integrity sha512-rMQkjcOFbm+ufe3bTZLyOfsOUOxyvLXZJCTARhJr+8UMSoZmqTe1K1BgkFcrW37rAchWg57yI69ORxiWvUINuQ==
+"@babel/plugin-proposal-private-property-in-object@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz#a64137b232f0aca3733a67eb1a144c192389c503"
+  integrity sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==
   dependencies:
-    "@babel/helper-annotate-as-pure" "^7.16.7"
-    "@babel/helper-create-class-features-plugin" "^7.16.7"
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-annotate-as-pure" "^7.18.6"
+    "@babel/helper-create-class-features-plugin" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
     "@babel/plugin-syntax-private-property-in-object" "^7.14.5"
 
-"@babel/plugin-proposal-unicode-property-regex@^7.16.7", "@babel/plugin-proposal-unicode-property-regex@^7.4.4":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.7.tgz#635d18eb10c6214210ffc5ff4932552de08188a2"
-  integrity sha512-QRK0YI/40VLhNVGIjRNAAQkEHws0cswSdFFjpFyt943YmJIU1da9uW63Iu6NFV6CxTZW5eTDCrwZUstBWgp/Rg==
+"@babel/plugin-proposal-unicode-property-regex@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e"
+  integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==
   dependencies:
-    "@babel/helper-create-regexp-features-plugin" "^7.16.7"
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-create-regexp-features-plugin" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-proposal-unicode-property-regex@^7.4.4":
+  version "7.17.12"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.17.12.tgz#3dbd7a67bd7f94c8238b394da112d86aaf32ad4d"
+  integrity sha512-Wb9qLjXf3ZazqXA7IvI7ozqRIXIGPtSo+L5coFmEkhTQK18ao4UDDD0zdTGAarmbLj2urpRwrc6893cu5Bfh0A==
+  dependencies:
+    "@babel/helper-create-regexp-features-plugin" "^7.17.12"
+    "@babel/helper-plugin-utils" "^7.17.12"
 
 "@babel/plugin-syntax-async-generators@^7.8.4":
   version "7.8.4"
@@ -478,6 +641,13 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.8.3"
 
+"@babel/plugin-syntax-import-assertions@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz#cd6190500a4fa2fe31990a963ffab4b63e4505e4"
+  integrity sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.6"
+
 "@babel/plugin-syntax-json-strings@^7.8.3":
   version "7.8.3"
   resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a"
@@ -485,12 +655,19 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.8.0"
 
-"@babel/plugin-syntax-jsx@^7.12.13", "@babel/plugin-syntax-jsx@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.7.tgz#50b6571d13f764266a113d77c82b4a6508bbe665"
-  integrity sha512-Esxmk7YjA8QysKeT3VhTXvF6y77f/a91SIs4pWb4H2eWGQkCKFgQaG6hdoEVZtGsrAcb2K5BW66XsOErD4WU3Q==
+"@babel/plugin-syntax-jsx@^7.12.13":
+  version "7.17.12"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.17.12.tgz#834035b45061983a491f60096f61a2e7c5674a47"
+  integrity sha512-spyY3E3AURfxh/RHtjx5j6hs8am5NbUBGfcZ2vB3uShSpZdQyXSf5rR5Mk76vbtlAZOelyVQ71Fg0x9SG4fsog==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-syntax-jsx@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0"
+  integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.6"
 
 "@babel/plugin-syntax-logical-assignment-operators@^7.10.4":
   version "7.10.4"
@@ -548,72 +725,80 @@
   dependencies:
     "@babel/helper-plugin-utils" "^7.14.5"
 
-"@babel/plugin-syntax-typescript@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.7.tgz#39c9b55ee153151990fb038651d58d3fd03f98f8"
-  integrity sha512-YhUIJHHGkqPgEcMYkPCKTyGUdoGKWtopIycQyjJH8OjvRgOYsXsaKehLVPScKJWAULPxMa4N1vCe6szREFlZ7A==
+"@babel/plugin-syntax-typescript@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz#1c09cd25795c7c2b8a4ba9ae49394576d4133285"
+  integrity sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.6"
 
-"@babel/plugin-transform-arrow-functions@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.7.tgz#44125e653d94b98db76369de9c396dc14bef4154"
-  integrity sha512-9ffkFFMbvzTvv+7dTp/66xvZAWASuPD5Tl9LK3Z9vhOmANo6j94rik+5YMBt4CwHVMWLWpMsriIc2zsa3WW3xQ==
+"@babel/plugin-transform-arrow-functions@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe"
+  integrity sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.6"
 
-"@babel/plugin-transform-async-to-generator@^7.16.8":
-  version "7.16.8"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.8.tgz#b83dff4b970cf41f1b819f8b49cc0cfbaa53a808"
-  integrity sha512-MtmUmTJQHCnyJVrScNzNlofQJ3dLFuobYn3mwOTKHnSCMtbNsqvF71GQmJfFjdrXSsAA7iysFmYWw4bXZ20hOg==
+"@babel/plugin-transform-async-to-generator@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz#ccda3d1ab9d5ced5265fdb13f1882d5476c71615"
+  integrity sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==
   dependencies:
-    "@babel/helper-module-imports" "^7.16.7"
-    "@babel/helper-plugin-utils" "^7.16.7"
-    "@babel/helper-remap-async-to-generator" "^7.16.8"
+    "@babel/helper-module-imports" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
+    "@babel/helper-remap-async-to-generator" "^7.18.6"
 
-"@babel/plugin-transform-block-scoped-functions@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz#4d0d57d9632ef6062cdf354bb717102ee042a620"
-  integrity sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==
+"@babel/plugin-transform-block-scoped-functions@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8"
+  integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.6"
 
-"@babel/plugin-transform-block-scoping@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.7.tgz#f50664ab99ddeaee5bc681b8f3a6ea9d72ab4f87"
-  integrity sha512-ObZev2nxVAYA4bhyusELdo9hb3H+A56bxH3FZMbEImZFiEDYVHXQSJ1hQKFlDnlt8G9bBrCZ5ZpURZUrV4G5qQ==
+"@babel/plugin-transform-block-scoping@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz#f9b7e018ac3f373c81452d6ada8bd5a18928926d"
+  integrity sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.9"
 
-"@babel/plugin-transform-classes@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.7.tgz#8f4b9562850cd973de3b498f1218796eb181ce00"
-  integrity sha512-WY7og38SFAGYRe64BrjKf8OrE6ulEHtr5jEYaZMwox9KebgqPi67Zqz8K53EKk1fFEJgm96r32rkKZ3qA2nCWQ==
+"@babel/plugin-transform-classes@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.9.tgz#90818efc5b9746879b869d5ce83eb2aa48bbc3da"
+  integrity sha512-EkRQxsxoytpTlKJmSPYrsOMjCILacAjtSVkd4gChEe2kXjFCun3yohhW5I7plXJhCemM0gKsaGMcO8tinvCA5g==
   dependencies:
-    "@babel/helper-annotate-as-pure" "^7.16.7"
-    "@babel/helper-environment-visitor" "^7.16.7"
-    "@babel/helper-function-name" "^7.16.7"
-    "@babel/helper-optimise-call-expression" "^7.16.7"
-    "@babel/helper-plugin-utils" "^7.16.7"
-    "@babel/helper-replace-supers" "^7.16.7"
-    "@babel/helper-split-export-declaration" "^7.16.7"
+    "@babel/helper-annotate-as-pure" "^7.18.6"
+    "@babel/helper-environment-visitor" "^7.18.9"
+    "@babel/helper-function-name" "^7.18.9"
+    "@babel/helper-optimise-call-expression" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.9"
+    "@babel/helper-replace-supers" "^7.18.9"
+    "@babel/helper-split-export-declaration" "^7.18.6"
     globals "^11.1.0"
 
-"@babel/plugin-transform-computed-properties@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.7.tgz#66dee12e46f61d2aae7a73710f591eb3df616470"
-  integrity sha512-gN72G9bcmenVILj//sv1zLNaPyYcOzUho2lIJBMh/iakJ9ygCo/hEF9cpGb61SCMEDxbbyBoVQxrt+bWKu5KGw==
+"@babel/plugin-transform-computed-properties@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz#2357a8224d402dad623caf6259b611e56aec746e"
+  integrity sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.9"
 
-"@babel/plugin-transform-destructuring@^7.16.7":
-  version "7.17.3"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.17.3.tgz#c445f75819641788a27a0a3a759d9df911df6abc"
-  integrity sha512-dDFzegDYKlPqa72xIlbmSkly5MluLoaC1JswABGktyt6NTXSBcUuse/kWE/wvKFWJHPETpi158qJZFS3JmykJg==
+"@babel/plugin-transform-destructuring@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.9.tgz#68906549c021cb231bee1db21d3b5b095f8ee292"
+  integrity sha512-p5VCYNddPLkZTq4XymQIaIfZNJwT9YsjkPOhkVEqt6QIpQFZVM9IltqqYpOEkJoN1DPznmxUDyZ5CTZs/ZCuHA==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.9"
 
-"@babel/plugin-transform-dotall-regex@^7.16.7", "@babel/plugin-transform-dotall-regex@^7.4.4":
+"@babel/plugin-transform-dotall-regex@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8"
+  integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==
+  dependencies:
+    "@babel/helper-create-regexp-features-plugin" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-dotall-regex@^7.4.4":
   version "7.16.7"
   resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz#6b2d67686fab15fb6a7fd4bd895d5982cfc81241"
   integrity sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==
@@ -621,270 +806,273 @@
     "@babel/helper-create-regexp-features-plugin" "^7.16.7"
     "@babel/helper-plugin-utils" "^7.16.7"
 
-"@babel/plugin-transform-duplicate-keys@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.7.tgz#2207e9ca8f82a0d36a5a67b6536e7ef8b08823c9"
-  integrity sha512-03DvpbRfvWIXyK0/6QiR1KMTWeT6OcQ7tbhjrXyFS02kjuX/mu5Bvnh5SDSWHxyawit2g5aWhKwI86EE7GUnTw==
+"@babel/plugin-transform-duplicate-keys@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e"
+  integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.9"
 
-"@babel/plugin-transform-exponentiation-operator@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz#efa9862ef97e9e9e5f653f6ddc7b665e8536fe9b"
-  integrity sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==
+"@babel/plugin-transform-exponentiation-operator@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd"
+  integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==
   dependencies:
-    "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.7"
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
 
-"@babel/plugin-transform-for-of@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.7.tgz#649d639d4617dff502a9a158c479b3b556728d8c"
-  integrity sha512-/QZm9W92Ptpw7sjI9Nx1mbcsWz33+l8kuMIQnDwgQBG5s3fAfQvkRjQ7NqXhtNcKOnPkdICmUHyCaWW06HCsqg==
+"@babel/plugin-transform-for-of@^7.18.8":
+  version "7.18.8"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1"
+  integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.6"
 
-"@babel/plugin-transform-function-name@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz#5ab34375c64d61d083d7d2f05c38d90b97ec65cf"
-  integrity sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==
+"@babel/plugin-transform-function-name@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0"
+  integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==
   dependencies:
-    "@babel/helper-compilation-targets" "^7.16.7"
-    "@babel/helper-function-name" "^7.16.7"
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-compilation-targets" "^7.18.9"
+    "@babel/helper-function-name" "^7.18.9"
+    "@babel/helper-plugin-utils" "^7.18.9"
 
-"@babel/plugin-transform-literals@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.7.tgz#254c9618c5ff749e87cb0c0cef1a0a050c0bdab1"
-  integrity sha512-6tH8RTpTWI0s2sV6uq3e/C9wPo4PTqqZps4uF0kzQ9/xPLFQtipynvmT1g/dOfEJ+0EQsHhkQ/zyRId8J2b8zQ==
+"@babel/plugin-transform-literals@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc"
+  integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.9"
 
-"@babel/plugin-transform-member-expression-literals@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz#6e5dcf906ef8a098e630149d14c867dd28f92384"
-  integrity sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==
+"@babel/plugin-transform-member-expression-literals@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e"
+  integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.6"
 
-"@babel/plugin-transform-modules-amd@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.7.tgz#b28d323016a7daaae8609781d1f8c9da42b13186"
-  integrity sha512-KaaEtgBL7FKYwjJ/teH63oAmE3lP34N3kshz8mm4VMAw7U3PxjVwwUmxEFksbgsNUaO3wId9R2AVQYSEGRa2+g==
+"@babel/plugin-transform-modules-amd@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz#8c91f8c5115d2202f277549848874027d7172d21"
+  integrity sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==
   dependencies:
-    "@babel/helper-module-transforms" "^7.16.7"
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-module-transforms" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
     babel-plugin-dynamic-import-node "^2.3.3"
 
-"@babel/plugin-transform-modules-commonjs@^7.16.8":
-  version "7.16.8"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.8.tgz#cdee19aae887b16b9d331009aa9a219af7c86afe"
-  integrity sha512-oflKPvsLT2+uKQopesJt3ApiaIS2HW+hzHFcwRNtyDGieAeC/dIHZX8buJQ2J2X1rxGPy4eRcUijm3qcSPjYcA==
+"@babel/plugin-transform-modules-commonjs@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz#afd243afba166cca69892e24a8fd8c9f2ca87883"
+  integrity sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==
   dependencies:
-    "@babel/helper-module-transforms" "^7.16.7"
-    "@babel/helper-plugin-utils" "^7.16.7"
-    "@babel/helper-simple-access" "^7.16.7"
+    "@babel/helper-module-transforms" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
+    "@babel/helper-simple-access" "^7.18.6"
     babel-plugin-dynamic-import-node "^2.3.3"
 
-"@babel/plugin-transform-modules-systemjs@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.7.tgz#887cefaef88e684d29558c2b13ee0563e287c2d7"
-  integrity sha512-DuK5E3k+QQmnOqBR9UkusByy5WZWGRxfzV529s9nPra1GE7olmxfqO2FHobEOYSPIjPBTr4p66YDcjQnt8cBmw==
+"@babel/plugin-transform-modules-systemjs@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.9.tgz#545df284a7ac6a05125e3e405e536c5853099a06"
+  integrity sha512-zY/VSIbbqtoRoJKo2cDTewL364jSlZGvn0LKOf9ntbfxOvjfmyrdtEEOAdswOswhZEb8UH3jDkCKHd1sPgsS0A==
   dependencies:
-    "@babel/helper-hoist-variables" "^7.16.7"
-    "@babel/helper-module-transforms" "^7.16.7"
-    "@babel/helper-plugin-utils" "^7.16.7"
-    "@babel/helper-validator-identifier" "^7.16.7"
+    "@babel/helper-hoist-variables" "^7.18.6"
+    "@babel/helper-module-transforms" "^7.18.9"
+    "@babel/helper-plugin-utils" "^7.18.9"
+    "@babel/helper-validator-identifier" "^7.18.6"
     babel-plugin-dynamic-import-node "^2.3.3"
 
-"@babel/plugin-transform-modules-umd@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.7.tgz#23dad479fa585283dbd22215bff12719171e7618"
-  integrity sha512-EMh7uolsC8O4xhudF2F6wedbSHm1HHZ0C6aJ7K67zcDNidMzVcxWdGr+htW9n21klm+bOn+Rx4CBsAntZd3rEQ==
-  dependencies:
-    "@babel/helper-module-transforms" "^7.16.7"
-    "@babel/helper-plugin-utils" "^7.16.7"
-
-"@babel/plugin-transform-named-capturing-groups-regex@^7.16.8":
-  version "7.16.8"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.8.tgz#7f860e0e40d844a02c9dcf9d84965e7dfd666252"
-  integrity sha512-j3Jw+n5PvpmhRR+mrgIh04puSANCk/T/UA3m3P1MjJkhlK906+ApHhDIqBQDdOgL/r1UYpz4GNclTXxyZrYGSw==
-  dependencies:
-    "@babel/helper-create-regexp-features-plugin" "^7.16.7"
-
-"@babel/plugin-transform-new-target@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.7.tgz#9967d89a5c243818e0800fdad89db22c5f514244"
-  integrity sha512-xiLDzWNMfKoGOpc6t3U+etCE2yRnn3SM09BXqWPIZOBpL2gvVrBWUKnsJx0K/ADi5F5YC5f8APFfWrz25TdlGg==
-  dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
-
-"@babel/plugin-transform-object-super@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz#ac359cf8d32cf4354d27a46867999490b6c32a94"
-  integrity sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==
-  dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
-    "@babel/helper-replace-supers" "^7.16.7"
-
-"@babel/plugin-transform-parameters@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.7.tgz#a1721f55b99b736511cb7e0152f61f17688f331f"
-  integrity sha512-AT3MufQ7zZEhU2hwOA11axBnExW0Lszu4RL/tAlUJBuNoRak+wehQW8h6KcXOcgjY42fHtDxswuMhMjFEuv/aw==
-  dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
-
-"@babel/plugin-transform-property-literals@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz#2dadac85155436f22c696c4827730e0fe1057a55"
-  integrity sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==
-  dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
-
-"@babel/plugin-transform-react-constant-elements@^7.14.5":
-  version "7.17.6"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.17.6.tgz#6cc273c2f612a6a50cb657e63ee1303e5e68d10a"
-  integrity sha512-OBv9VkyyKtsHZiHLoSfCn+h6yU7YKX8nrs32xUmOa1SRSk+t03FosB6fBZ0Yz4BpD1WV7l73Nsad+2Tz7APpqw==
-  dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
-
-"@babel/plugin-transform-react-display-name@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz#7b6d40d232f4c0f550ea348593db3b21e2404340"
-  integrity sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==
-  dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
-
-"@babel/plugin-transform-react-jsx-development@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz#43a00724a3ed2557ed3f276a01a929e6686ac7b8"
-  integrity sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==
-  dependencies:
-    "@babel/plugin-transform-react-jsx" "^7.16.7"
-
-"@babel/plugin-transform-react-jsx@^7.16.7":
-  version "7.17.3"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.3.tgz#eac1565da176ccb1a715dae0b4609858808008c1"
-  integrity sha512-9tjBm4O07f7mzKSIlEmPdiE6ub7kfIe6Cd+w+oQebpATfTQMAgW+YOuWxogbKVTulA+MEO7byMeIUtQ1z+z+ZQ==
-  dependencies:
-    "@babel/helper-annotate-as-pure" "^7.16.7"
-    "@babel/helper-module-imports" "^7.16.7"
-    "@babel/helper-plugin-utils" "^7.16.7"
-    "@babel/plugin-syntax-jsx" "^7.16.7"
-    "@babel/types" "^7.17.0"
-
-"@babel/plugin-transform-react-pure-annotations@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.7.tgz#232bfd2f12eb551d6d7d01d13fe3f86b45eb9c67"
-  integrity sha512-hs71ToC97k3QWxswh2ElzMFABXHvGiJ01IB1TbYQDGeWRKWz/MPUTh5jGExdHvosYKpnJW5Pm3S4+TA3FyX+GA==
+"@babel/plugin-transform-modules-umd@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9"
+  integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==
   dependencies:
-    "@babel/helper-annotate-as-pure" "^7.16.7"
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-module-transforms" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
 
-"@babel/plugin-transform-regenerator@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.7.tgz#9e7576dc476cb89ccc5096fff7af659243b4adeb"
-  integrity sha512-mF7jOgGYCkSJagJ6XCujSQg+6xC1M77/03K2oBmVJWoFGNUtnVJO4WHKJk3dnPC8HCcj4xBQP1Egm8DWh3Pb3Q==
+"@babel/plugin-transform-named-capturing-groups-regex@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz#c89bfbc7cc6805d692f3a49bc5fc1b630007246d"
+  integrity sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg==
   dependencies:
-    regenerator-transform "^0.14.2"
+    "@babel/helper-create-regexp-features-plugin" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
 
-"@babel/plugin-transform-reserved-words@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.7.tgz#1d798e078f7c5958eec952059c460b220a63f586"
-  integrity sha512-KQzzDnZ9hWQBjwi5lpY5v9shmm6IVG0U9pB18zvMu2i4H90xpT4gmqwPYsn8rObiadYe2M0gmgsiOIF5A/2rtg==
+"@babel/plugin-transform-new-target@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8"
+  integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.6"
 
-"@babel/plugin-transform-shorthand-properties@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz#e8549ae4afcf8382f711794c0c7b6b934c5fbd2a"
-  integrity sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==
+"@babel/plugin-transform-object-super@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c"
+  integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.6"
+    "@babel/helper-replace-supers" "^7.18.6"
 
-"@babel/plugin-transform-spread@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.7.tgz#a303e2122f9f12e0105daeedd0f30fb197d8ff44"
-  integrity sha512-+pjJpgAngb53L0iaA5gU/1MLXJIfXcYepLgXB3esVRf4fqmj8f2cxM3/FKaHsZms08hFQJkFccEWuIpm429TXg==
+"@babel/plugin-transform-parameters@^7.18.8":
+  version "7.18.8"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz#ee9f1a0ce6d78af58d0956a9378ea3427cccb48a"
+  integrity sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
-    "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0"
+    "@babel/helper-plugin-utils" "^7.18.6"
 
-"@babel/plugin-transform-sticky-regex@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz#c84741d4f4a38072b9a1e2e3fd56d359552e8660"
-  integrity sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==
+"@babel/plugin-transform-property-literals@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3"
+  integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.6"
 
-"@babel/plugin-transform-template-literals@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.7.tgz#f3d1c45d28967c8e80f53666fc9c3e50618217ab"
-  integrity sha512-VwbkDDUeenlIjmfNeDX/V0aWrQH2QiVyJtwymVQSzItFDTpxfyJh3EVaQiS0rIN/CqbLGr0VcGmuwyTdZtdIsA==
+"@babel/plugin-transform-react-constant-elements@^7.17.12":
+  version "7.18.12"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.18.12.tgz#edf3bec47eb98f14e84fa0af137fcc6aad8e0443"
+  integrity sha512-Q99U9/ttiu+LMnRU8psd23HhvwXmKWDQIpocm0JKaICcZHnw+mdQbHm6xnSy7dOl8I5PELakYtNBubNQlBXbZw==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.9"
 
-"@babel/plugin-transform-typeof-symbol@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.7.tgz#9cdbe622582c21368bd482b660ba87d5545d4f7e"
-  integrity sha512-p2rOixCKRJzpg9JB4gjnG4gjWkWa89ZoYUnl9snJ1cWIcTH/hvxZqfO+WjG6T8DRBpctEol5jw1O5rA8gkCokQ==
+"@babel/plugin-transform-react-display-name@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz#8b1125f919ef36ebdfff061d664e266c666b9415"
+  integrity sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.6"
 
-"@babel/plugin-transform-typescript@^7.16.7":
-  version "7.16.8"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.8.tgz#591ce9b6b83504903fa9dd3652c357c2ba7a1ee0"
-  integrity sha512-bHdQ9k7YpBDO2d0NVfkj51DpQcvwIzIusJ7mEUaMlbZq3Kt/U47j24inXZHQ5MDiYpCs+oZiwnXyKedE8+q7AQ==
-  dependencies:
-    "@babel/helper-create-class-features-plugin" "^7.16.7"
-    "@babel/helper-plugin-utils" "^7.16.7"
-    "@babel/plugin-syntax-typescript" "^7.16.7"
-
-"@babel/plugin-transform-unicode-escapes@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz#da8717de7b3287a2c6d659750c964f302b31ece3"
-  integrity sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==
+"@babel/plugin-transform-react-jsx-development@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz#dbe5c972811e49c7405b630e4d0d2e1380c0ddc5"
+  integrity sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/plugin-transform-react-jsx" "^7.18.6"
 
-"@babel/plugin-transform-unicode-regex@^7.16.7":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz#0f7aa4a501198976e25e82702574c34cfebe9ef2"
-  integrity sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==
+"@babel/plugin-transform-react-jsx@^7.18.6":
+  version "7.18.10"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.18.10.tgz#ea47b2c4197102c196cbd10db9b3bb20daa820f1"
+  integrity sha512-gCy7Iikrpu3IZjYZolFE4M1Sm+nrh1/6za2Ewj77Z+XirT4TsbJcvOFOyF+fRPwU6AKKK136CZxx6L8AbSFG6A==
   dependencies:
-    "@babel/helper-create-regexp-features-plugin" "^7.16.7"
-    "@babel/helper-plugin-utils" "^7.16.7"
+    "@babel/helper-annotate-as-pure" "^7.18.6"
+    "@babel/helper-module-imports" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.9"
+    "@babel/plugin-syntax-jsx" "^7.18.6"
+    "@babel/types" "^7.18.10"
 
-"@babel/preset-env@^7.15.6":
-  version "7.16.11"
-  resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.11.tgz#5dd88fd885fae36f88fd7c8342475c9f0abe2982"
-  integrity sha512-qcmWG8R7ZW6WBRPZK//y+E3Cli151B20W1Rv7ln27vuPaXU/8TKms6jFdiJtF7UDTxcrb7mZd88tAeK9LjdT8g==
-  dependencies:
-    "@babel/compat-data" "^7.16.8"
-    "@babel/helper-compilation-targets" "^7.16.7"
-    "@babel/helper-plugin-utils" "^7.16.7"
-    "@babel/helper-validator-option" "^7.16.7"
-    "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.16.7"
-    "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.16.7"
-    "@babel/plugin-proposal-async-generator-functions" "^7.16.8"
-    "@babel/plugin-proposal-class-properties" "^7.16.7"
-    "@babel/plugin-proposal-class-static-block" "^7.16.7"
-    "@babel/plugin-proposal-dynamic-import" "^7.16.7"
-    "@babel/plugin-proposal-export-namespace-from" "^7.16.7"
-    "@babel/plugin-proposal-json-strings" "^7.16.7"
-    "@babel/plugin-proposal-logical-assignment-operators" "^7.16.7"
-    "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.7"
-    "@babel/plugin-proposal-numeric-separator" "^7.16.7"
-    "@babel/plugin-proposal-object-rest-spread" "^7.16.7"
-    "@babel/plugin-proposal-optional-catch-binding" "^7.16.7"
-    "@babel/plugin-proposal-optional-chaining" "^7.16.7"
-    "@babel/plugin-proposal-private-methods" "^7.16.11"
-    "@babel/plugin-proposal-private-property-in-object" "^7.16.7"
-    "@babel/plugin-proposal-unicode-property-regex" "^7.16.7"
+"@babel/plugin-transform-react-pure-annotations@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz#561af267f19f3e5d59291f9950fd7b9663d0d844"
+  integrity sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ==
+  dependencies:
+    "@babel/helper-annotate-as-pure" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-regenerator@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz#585c66cb84d4b4bf72519a34cfce761b8676ca73"
+  integrity sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.6"
+    regenerator-transform "^0.15.0"
+
+"@babel/plugin-transform-reserved-words@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a"
+  integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-shorthand-properties@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9"
+  integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-spread@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.9.tgz#6ea7a6297740f381c540ac56caf75b05b74fb664"
+  integrity sha512-39Q814wyoOPtIB/qGopNIL9xDChOE1pNU0ZY5dO0owhiVt/5kFm4li+/bBtwc7QotG0u5EPzqhZdjMtmqBqyQA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.9"
+    "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9"
+
+"@babel/plugin-transform-sticky-regex@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc"
+  integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-template-literals@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e"
+  integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.9"
+
+"@babel/plugin-transform-typeof-symbol@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0"
+  integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.9"
+
+"@babel/plugin-transform-typescript@^7.18.6":
+  version "7.18.12"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.18.12.tgz#712e9a71b9e00fde9f8c0238e0cceee86ab2f8fd"
+  integrity sha512-2vjjam0cum0miPkenUbQswKowuxs/NjMwIKEq0zwegRxXk12C9YOF9STXnaUptITOtOJHKHpzvvWYOjbm6tc0w==
+  dependencies:
+    "@babel/helper-create-class-features-plugin" "^7.18.9"
+    "@babel/helper-plugin-utils" "^7.18.9"
+    "@babel/plugin-syntax-typescript" "^7.18.6"
+
+"@babel/plugin-transform-unicode-escapes@^7.18.10":
+  version "7.18.10"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz#1ecfb0eda83d09bbcb77c09970c2dd55832aa246"
+  integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==
+  dependencies:
+    "@babel/helper-plugin-utils" "^7.18.9"
+
+"@babel/plugin-transform-unicode-regex@^7.18.6":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca"
+  integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==
+  dependencies:
+    "@babel/helper-create-regexp-features-plugin" "^7.18.6"
+    "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/preset-env@^7.18.2":
+  version "7.18.10"
+  resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.18.10.tgz#83b8dfe70d7eea1aae5a10635ab0a5fe60dfc0f4"
+  integrity sha512-wVxs1yjFdW3Z/XkNfXKoblxoHgbtUF7/l3PvvP4m02Qz9TZ6uZGxRVYjSQeR87oQmHco9zWitW5J82DJ7sCjvA==
+  dependencies:
+    "@babel/compat-data" "^7.18.8"
+    "@babel/helper-compilation-targets" "^7.18.9"
+    "@babel/helper-plugin-utils" "^7.18.9"
+    "@babel/helper-validator-option" "^7.18.6"
+    "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6"
+    "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.9"
+    "@babel/plugin-proposal-async-generator-functions" "^7.18.10"
+    "@babel/plugin-proposal-class-properties" "^7.18.6"
+    "@babel/plugin-proposal-class-static-block" "^7.18.6"
+    "@babel/plugin-proposal-dynamic-import" "^7.18.6"
+    "@babel/plugin-proposal-export-namespace-from" "^7.18.9"
+    "@babel/plugin-proposal-json-strings" "^7.18.6"
+    "@babel/plugin-proposal-logical-assignment-operators" "^7.18.9"
+    "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.6"
+    "@babel/plugin-proposal-numeric-separator" "^7.18.6"
+    "@babel/plugin-proposal-object-rest-spread" "^7.18.9"
+    "@babel/plugin-proposal-optional-catch-binding" "^7.18.6"
+    "@babel/plugin-proposal-optional-chaining" "^7.18.9"
+    "@babel/plugin-proposal-private-methods" "^7.18.6"
+    "@babel/plugin-proposal-private-property-in-object" "^7.18.6"
+    "@babel/plugin-proposal-unicode-property-regex" "^7.18.6"
     "@babel/plugin-syntax-async-generators" "^7.8.4"
     "@babel/plugin-syntax-class-properties" "^7.12.13"
     "@babel/plugin-syntax-class-static-block" "^7.14.5"
     "@babel/plugin-syntax-dynamic-import" "^7.8.3"
     "@babel/plugin-syntax-export-namespace-from" "^7.8.3"
+    "@babel/plugin-syntax-import-assertions" "^7.18.6"
     "@babel/plugin-syntax-json-strings" "^7.8.3"
     "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
     "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
@@ -894,44 +1082,44 @@
     "@babel/plugin-syntax-optional-chaining" "^7.8.3"
     "@babel/plugin-syntax-private-property-in-object" "^7.14.5"
     "@babel/plugin-syntax-top-level-await" "^7.14.5"
-    "@babel/plugin-transform-arrow-functions" "^7.16.7"
-    "@babel/plugin-transform-async-to-generator" "^7.16.8"
-    "@babel/plugin-transform-block-scoped-functions" "^7.16.7"
-    "@babel/plugin-transform-block-scoping" "^7.16.7"
-    "@babel/plugin-transform-classes" "^7.16.7"
-    "@babel/plugin-transform-computed-properties" "^7.16.7"
-    "@babel/plugin-transform-destructuring" "^7.16.7"
-    "@babel/plugin-transform-dotall-regex" "^7.16.7"
-    "@babel/plugin-transform-duplicate-keys" "^7.16.7"
-    "@babel/plugin-transform-exponentiation-operator" "^7.16.7"
-    "@babel/plugin-transform-for-of" "^7.16.7"
-    "@babel/plugin-transform-function-name" "^7.16.7"
-    "@babel/plugin-transform-literals" "^7.16.7"
-    "@babel/plugin-transform-member-expression-literals" "^7.16.7"
-    "@babel/plugin-transform-modules-amd" "^7.16.7"
-    "@babel/plugin-transform-modules-commonjs" "^7.16.8"
-    "@babel/plugin-transform-modules-systemjs" "^7.16.7"
-    "@babel/plugin-transform-modules-umd" "^7.16.7"
-    "@babel/plugin-transform-named-capturing-groups-regex" "^7.16.8"
-    "@babel/plugin-transform-new-target" "^7.16.7"
-    "@babel/plugin-transform-object-super" "^7.16.7"
-    "@babel/plugin-transform-parameters" "^7.16.7"
-    "@babel/plugin-transform-property-literals" "^7.16.7"
-    "@babel/plugin-transform-regenerator" "^7.16.7"
-    "@babel/plugin-transform-reserved-words" "^7.16.7"
-    "@babel/plugin-transform-shorthand-properties" "^7.16.7"
-    "@babel/plugin-transform-spread" "^7.16.7"
-    "@babel/plugin-transform-sticky-regex" "^7.16.7"
-    "@babel/plugin-transform-template-literals" "^7.16.7"
-    "@babel/plugin-transform-typeof-symbol" "^7.16.7"
-    "@babel/plugin-transform-unicode-escapes" "^7.16.7"
-    "@babel/plugin-transform-unicode-regex" "^7.16.7"
+    "@babel/plugin-transform-arrow-functions" "^7.18.6"
+    "@babel/plugin-transform-async-to-generator" "^7.18.6"
+    "@babel/plugin-transform-block-scoped-functions" "^7.18.6"
+    "@babel/plugin-transform-block-scoping" "^7.18.9"
+    "@babel/plugin-transform-classes" "^7.18.9"
+    "@babel/plugin-transform-computed-properties" "^7.18.9"
+    "@babel/plugin-transform-destructuring" "^7.18.9"
+    "@babel/plugin-transform-dotall-regex" "^7.18.6"
+    "@babel/plugin-transform-duplicate-keys" "^7.18.9"
+    "@babel/plugin-transform-exponentiation-operator" "^7.18.6"
+    "@babel/plugin-transform-for-of" "^7.18.8"
+    "@babel/plugin-transform-function-name" "^7.18.9"
+    "@babel/plugin-transform-literals" "^7.18.9"
+    "@babel/plugin-transform-member-expression-literals" "^7.18.6"
+    "@babel/plugin-transform-modules-amd" "^7.18.6"
+    "@babel/plugin-transform-modules-commonjs" "^7.18.6"
+    "@babel/plugin-transform-modules-systemjs" "^7.18.9"
+    "@babel/plugin-transform-modules-umd" "^7.18.6"
+    "@babel/plugin-transform-named-capturing-groups-regex" "^7.18.6"
+    "@babel/plugin-transform-new-target" "^7.18.6"
+    "@babel/plugin-transform-object-super" "^7.18.6"
+    "@babel/plugin-transform-parameters" "^7.18.8"
+    "@babel/plugin-transform-property-literals" "^7.18.6"
+    "@babel/plugin-transform-regenerator" "^7.18.6"
+    "@babel/plugin-transform-reserved-words" "^7.18.6"
+    "@babel/plugin-transform-shorthand-properties" "^7.18.6"
+    "@babel/plugin-transform-spread" "^7.18.9"
+    "@babel/plugin-transform-sticky-regex" "^7.18.6"
+    "@babel/plugin-transform-template-literals" "^7.18.9"
+    "@babel/plugin-transform-typeof-symbol" "^7.18.9"
+    "@babel/plugin-transform-unicode-escapes" "^7.18.10"
+    "@babel/plugin-transform-unicode-regex" "^7.18.6"
     "@babel/preset-modules" "^0.1.5"
-    "@babel/types" "^7.16.8"
-    babel-plugin-polyfill-corejs2 "^0.3.0"
-    babel-plugin-polyfill-corejs3 "^0.5.0"
-    babel-plugin-polyfill-regenerator "^0.3.0"
-    core-js-compat "^3.20.2"
+    "@babel/types" "^7.18.10"
+    babel-plugin-polyfill-corejs2 "^0.3.2"
+    babel-plugin-polyfill-corejs3 "^0.5.3"
+    babel-plugin-polyfill-regenerator "^0.4.0"
+    core-js-compat "^3.22.1"
     semver "^6.3.0"
 
 "@babel/preset-modules@^0.1.5":
@@ -945,39 +1133,46 @@
     "@babel/types" "^7.4.4"
     esutils "^2.0.2"
 
-"@babel/preset-react@^7.14.5":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.16.7.tgz#4c18150491edc69c183ff818f9f2aecbe5d93852"
-  integrity sha512-fWpyI8UM/HE6DfPBzD8LnhQ/OcH8AgTaqcqP2nGOXEUV+VKBR5JRN9hCk9ai+zQQ57vtm9oWeXguBCPNUjytgA==
+"@babel/preset-react@^7.17.12":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.18.6.tgz#979f76d6277048dc19094c217b507f3ad517dd2d"
+  integrity sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
-    "@babel/helper-validator-option" "^7.16.7"
-    "@babel/plugin-transform-react-display-name" "^7.16.7"
-    "@babel/plugin-transform-react-jsx" "^7.16.7"
-    "@babel/plugin-transform-react-jsx-development" "^7.16.7"
-    "@babel/plugin-transform-react-pure-annotations" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.6"
+    "@babel/helper-validator-option" "^7.18.6"
+    "@babel/plugin-transform-react-display-name" "^7.18.6"
+    "@babel/plugin-transform-react-jsx" "^7.18.6"
+    "@babel/plugin-transform-react-jsx-development" "^7.18.6"
+    "@babel/plugin-transform-react-pure-annotations" "^7.18.6"
 
-"@babel/preset-typescript@^7.15.0":
-  version "7.16.7"
-  resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.7.tgz#ab114d68bb2020afc069cd51b37ff98a046a70b9"
-  integrity sha512-WbVEmgXdIyvzB77AQjGBEyYPZx+8tTsO50XtfozQrkW8QB2rLJpH2lgx0TRw5EJrBxOZQ+wCcyPVQvS8tjEHpQ==
+"@babel/preset-typescript@^7.17.12":
+  version "7.18.6"
+  resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399"
+  integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==
   dependencies:
-    "@babel/helper-plugin-utils" "^7.16.7"
-    "@babel/helper-validator-option" "^7.16.7"
-    "@babel/plugin-transform-typescript" "^7.16.7"
+    "@babel/helper-plugin-utils" "^7.18.6"
+    "@babel/helper-validator-option" "^7.18.6"
+    "@babel/plugin-transform-typescript" "^7.18.6"
 
 "@babel/runtime-corejs3@^7.10.2":
-  version "7.17.2"
-  resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.17.2.tgz#fdca2cd05fba63388babe85d349b6801b008fd13"
-  integrity sha512-NcKtr2epxfIrNM4VOmPKO46TvDMCBhgi2CrSHaEarrz+Plk2K5r9QemmOFTGpZaoKnWoGH5MO+CzeRsih/Fcgg==
+  version "7.18.3"
+  resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.18.3.tgz#52f0241a31e0ec61a6187530af6227c2846bd60c"
+  integrity sha512-l4ddFwrc9rnR+EJsHsh+TJ4A35YqQz/UqcjtlX2ov53hlJYG5CxtQmNZxyajwDVmCxwy++rtvGU5HazCK4W41Q==
   dependencies:
     core-js-pure "^3.20.2"
     regenerator-runtime "^0.13.4"
 
-"@babel/runtime@^7.10.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.2", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
-  version "7.17.2"
-  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.17.2.tgz#66f68591605e59da47523c631416b18508779941"
-  integrity sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==
+"@babel/runtime@^7.10.2", "@babel/runtime@^7.12.0", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7":
+  version "7.18.3"
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.3.tgz#c7b654b57f6f63cf7f8b418ac9ca04408c4579f4"
+  integrity sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug==
+  dependencies:
+    regenerator-runtime "^0.13.4"
+
+"@babel/runtime@^7.18.3", "@babel/runtime@^7.18.9":
+  version "7.18.9"
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a"
+  integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==
   dependencies:
     regenerator-runtime "^0.13.4"
 
@@ -990,198 +1185,297 @@
     "@babel/parser" "^7.16.7"
     "@babel/types" "^7.16.7"
 
-"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.7", "@babel/traverse@^7.16.8", "@babel/traverse@^7.17.0", "@babel/traverse@^7.17.3", "@babel/traverse@^7.9.0":
-  version "7.17.3"
-  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.3.tgz#0ae0f15b27d9a92ba1f2263358ea7c4e7db47b57"
-  integrity sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==
+"@babel/template@^7.18.10", "@babel/template@^7.18.6":
+  version "7.18.10"
+  resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71"
+  integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==
+  dependencies:
+    "@babel/code-frame" "^7.18.6"
+    "@babel/parser" "^7.18.10"
+    "@babel/types" "^7.18.10"
+
+"@babel/traverse@^7.18.0", "@babel/traverse@^7.18.2", "@babel/traverse@^7.9.0":
+  version "7.18.2"
+  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.2.tgz#b77a52604b5cc836a9e1e08dca01cba67a12d2e8"
+  integrity sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA==
   dependencies:
     "@babel/code-frame" "^7.16.7"
-    "@babel/generator" "^7.17.3"
-    "@babel/helper-environment-visitor" "^7.16.7"
-    "@babel/helper-function-name" "^7.16.7"
+    "@babel/generator" "^7.18.2"
+    "@babel/helper-environment-visitor" "^7.18.2"
+    "@babel/helper-function-name" "^7.17.9"
     "@babel/helper-hoist-variables" "^7.16.7"
     "@babel/helper-split-export-declaration" "^7.16.7"
-    "@babel/parser" "^7.17.3"
-    "@babel/types" "^7.17.0"
+    "@babel/parser" "^7.18.0"
+    "@babel/types" "^7.18.2"
+    debug "^4.1.0"
+    globals "^11.1.0"
+
+"@babel/traverse@^7.18.10", "@babel/traverse@^7.18.11", "@babel/traverse@^7.18.9":
+  version "7.18.11"
+  resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.11.tgz#3d51f2afbd83ecf9912bcbb5c4d94e3d2ddaa16f"
+  integrity sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==
+  dependencies:
+    "@babel/code-frame" "^7.18.6"
+    "@babel/generator" "^7.18.10"
+    "@babel/helper-environment-visitor" "^7.18.9"
+    "@babel/helper-function-name" "^7.18.9"
+    "@babel/helper-hoist-variables" "^7.18.6"
+    "@babel/helper-split-export-declaration" "^7.18.6"
+    "@babel/parser" "^7.18.11"
+    "@babel/types" "^7.18.10"
     debug "^4.1.0"
     globals "^11.1.0"
 
-"@babel/types@^7.0.0", "@babel/types@^7.15.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.6.1", "@babel/types@^7.9.0", "@babel/types@^7.9.5", "@babel/types@^7.9.6":
-  version "7.17.0"
-  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.0.tgz#a826e368bccb6b3d84acd76acad5c0d87342390b"
-  integrity sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==
+"@babel/types@^7.0.0", "@babel/types@^7.16.7", "@babel/types@^7.17.0", "@babel/types@^7.18.0", "@babel/types@^7.18.2", "@babel/types@^7.3.0", "@babel/types@^7.4.4", "@babel/types@^7.6.1", "@babel/types@^7.9.0", "@babel/types@^7.9.5", "@babel/types@^7.9.6":
+  version "7.18.4"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.4.tgz#27eae9b9fd18e9dccc3f9d6ad051336f307be354"
+  integrity sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==
   dependencies:
     "@babel/helper-validator-identifier" "^7.16.7"
     to-fast-properties "^2.0.0"
 
+"@babel/types@^7.18.10", "@babel/types@^7.18.4", "@babel/types@^7.18.6", "@babel/types@^7.18.9":
+  version "7.18.10"
+  resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.10.tgz#4908e81b6b339ca7c6b7a555a5fc29446f26dde6"
+  integrity sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==
+  dependencies:
+    "@babel/helper-string-parser" "^7.18.10"
+    "@babel/helper-validator-identifier" "^7.18.6"
+    to-fast-properties "^2.0.0"
+
 "@colors/colors@1.5.0":
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
   integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
 
-"@commitlint/cli@^16.2.1":
-  version "16.2.1"
-  resolved "https://registry.yarnpkg.com/@commitlint/cli/-/cli-16.2.1.tgz#ca4e557829a2755f0e1f0cd69b56b83ce2510173"
-  integrity sha512-zfKf+B9osuiDbxGMJ7bWFv7XFCW8wlQYPtCffNp7Ukdb7mdrep5R9e03vPUZysnwp8NX6hg05kPEvnD/wRIGWw==
+"@commitlint/cli@17.0.3":
+  version "17.0.3"
+  resolved "https://registry.yarnpkg.com/@commitlint/cli/-/cli-17.0.3.tgz#50be9d9a8d79f6c47bfd2703638fe65215eb2526"
+  integrity sha512-oAo2vi5d8QZnAbtU5+0cR2j+A7PO8zuccux65R/EycwvsZrDVyW518FFrnJK2UQxbRtHFFIG+NjQ6vOiJV0Q8A==
   dependencies:
-    "@commitlint/format" "^16.2.1"
-    "@commitlint/lint" "^16.2.1"
-    "@commitlint/load" "^16.2.1"
-    "@commitlint/read" "^16.2.1"
-    "@commitlint/types" "^16.2.1"
+    "@commitlint/format" "^17.0.0"
+    "@commitlint/lint" "^17.0.3"
+    "@commitlint/load" "^17.0.3"
+    "@commitlint/read" "^17.0.0"
+    "@commitlint/types" "^17.0.0"
+    execa "^5.0.0"
     lodash "^4.17.19"
     resolve-from "5.0.0"
     resolve-global "1.0.0"
     yargs "^17.0.0"
 
-"@commitlint/config-conventional@^16.2.1":
-  version "16.2.1"
-  resolved "https://registry.yarnpkg.com/@commitlint/config-conventional/-/config-conventional-16.2.1.tgz#2cf47b505fb259777c063538c8498d8fd9b47779"
-  integrity sha512-cP9gArx7gnaj4IqmtCIcHdRjTYdRUi6lmGE+lOzGGjGe45qGOS8nyQQNvkNy2Ey2VqoSWuXXkD8zCUh6EHf1Ww==
+"@commitlint/config-conventional@17.0.3":
+  version "17.0.3"
+  resolved "https://registry.yarnpkg.com/@commitlint/config-conventional/-/config-conventional-17.0.3.tgz#61e937357ce63ea08a2017e58b918748fcf3abc5"
+  integrity sha512-HCnzTm5ATwwwzNVq5Y57poS0a1oOOcd5pc1MmBpLbGmSysc4i7F/++JuwtdFPu16sgM3H9J/j2zznRLOSGVO2A==
   dependencies:
-    conventional-changelog-conventionalcommits "^4.3.1"
+    conventional-changelog-conventionalcommits "^5.0.0"
 
-"@commitlint/config-validator@^16.2.1":
-  version "16.2.1"
-  resolved "https://registry.yarnpkg.com/@commitlint/config-validator/-/config-validator-16.2.1.tgz#794e769afd4756e4cf1bfd823b6612932e39c56d"
-  integrity sha512-hogSe0WGg7CKmp4IfNbdNES3Rq3UEI4XRPB8JL4EPgo/ORq5nrGTVzxJh78omibNuB8Ho4501Czb1Er1MoDWpw==
+"@commitlint/config-validator@^17.0.0":
+  version "17.0.0"
+  resolved "https://registry.yarnpkg.com/@commitlint/config-validator/-/config-validator-17.0.0.tgz#49ab09f3ca0ac3449e79ea389cb4942423162ac0"
+  integrity sha512-78IQjoZWR4kDHp/U5y17euEWzswJpPkA9TDL5F6oZZZaLIEreWzrDZD5PWtM8MsSRl/K2LDU/UrzYju2bKLMpA==
   dependencies:
-    "@commitlint/types" "^16.2.1"
+    "@commitlint/types" "^17.0.0"
     ajv "^6.12.6"
 
-"@commitlint/ensure@^16.2.1":
-  version "16.2.1"
-  resolved "https://registry.yarnpkg.com/@commitlint/ensure/-/ensure-16.2.1.tgz#0fc538173f95c1eb2694eeedb79cab478347f16f"
-  integrity sha512-/h+lBTgf1r5fhbDNHOViLuej38i3rZqTQnBTk+xEg+ehOwQDXUuissQ5GsYXXqI5uGy+261ew++sT4EA3uBJ+A==
+"@commitlint/config-validator@^17.0.3":
+  version "17.0.3"
+  resolved "https://registry.yarnpkg.com/@commitlint/config-validator/-/config-validator-17.0.3.tgz#5d1ec17eece1f85a0d06c05d168a039b313eb5d7"
+  integrity sha512-3tLRPQJKapksGE7Kee9axv+9z5I2GDHitDH4q63q7NmNA0wkB+DAorJ0RHz2/K00Zb1/MVdHzhCga34FJvDihQ==
+  dependencies:
+    "@commitlint/types" "^17.0.0"
+    ajv "^8.11.0"
+
+"@commitlint/ensure@^17.0.0":
+  version "17.0.0"
+  resolved "https://registry.yarnpkg.com/@commitlint/ensure/-/ensure-17.0.0.tgz#781ff5f8870cb98ce4496d5c71649a4cd122a0e0"
+  integrity sha512-M2hkJnNXvEni59S0QPOnqCKIK52G1XyXBGw51mvh7OXDudCmZ9tZiIPpU882p475Mhx48Ien1MbWjCP1zlyC0A==
   dependencies:
-    "@commitlint/types" "^16.2.1"
+    "@commitlint/types" "^17.0.0"
     lodash "^4.17.19"
 
-"@commitlint/execute-rule@^16.2.1":
-  version "16.2.1"
-  resolved "https://registry.yarnpkg.com/@commitlint/execute-rule/-/execute-rule-16.2.1.tgz#60be73be4b9af97a41546e7ce59fdd33787c65f8"
-  integrity sha512-oSls82fmUTLM6cl5V3epdVo4gHhbmBFvCvQGHBRdQ50H/690Uq1Dyd7hXMuKITCIdcnr9umyDkr8r5C6HZDF3g==
+"@commitlint/execute-rule@^17.0.0":
+  version "17.0.0"
+  resolved "https://registry.yarnpkg.com/@commitlint/execute-rule/-/execute-rule-17.0.0.tgz#186e9261fd36733922ae617497888c4bdb6e5c92"
+  integrity sha512-nVjL/w/zuqjCqSJm8UfpNaw66V9WzuJtQvEnCrK4jDw6qKTmZB+1JQ8m6BQVZbNBcwfYdDNKnhIhqI0Rk7lgpQ==
 
-"@commitlint/format@^16.2.1":
-  version "16.2.1"
-  resolved "https://registry.yarnpkg.com/@commitlint/format/-/format-16.2.1.tgz#6e673f710c799be78e68b2682323e04f75080d07"
-  integrity sha512-Yyio9bdHWmNDRlEJrxHKglamIk3d6hC0NkEUW6Ti6ipEh2g0BAhy8Od6t4vLhdZRa1I2n+gY13foy+tUgk0i1Q==
+"@commitlint/format@^17.0.0":
+  version "17.0.0"
+  resolved "https://registry.yarnpkg.com/@commitlint/format/-/format-17.0.0.tgz#2c991ac0df3955fe5d7d4d733967bd17e6cfd9e0"
+  integrity sha512-MZzJv7rBp/r6ZQJDEodoZvdRM0vXu1PfQvMTNWFb8jFraxnISMTnPBWMMjr2G/puoMashwaNM//fl7j8gGV5lA==
   dependencies:
-    "@commitlint/types" "^16.2.1"
-    chalk "^4.0.0"
+    "@commitlint/types" "^17.0.0"
+    chalk "^4.1.0"
 
-"@commitlint/is-ignored@^16.2.1":
-  version "16.2.1"
-  resolved "https://registry.yarnpkg.com/@commitlint/is-ignored/-/is-ignored-16.2.1.tgz#cc688ec73a3d204b90f8086821a08814da461e5e"
-  integrity sha512-exl8HRzTIfb1YvDJp2b2HU5z1BT+9tmgxR2XF0YEzkMiCIuEKh+XLeocPr1VcvAKXv3Cmv5X/OfNRp+i+/HIhQ==
-  dependencies:
-    "@commitlint/types" "^16.2.1"
-    semver "7.3.5"
-
-"@commitlint/lint@^16.2.1":
-  version "16.2.1"
-  resolved "https://registry.yarnpkg.com/@commitlint/lint/-/lint-16.2.1.tgz#c773f082cd4f69cb7807b805b691d2a52c732f97"
-  integrity sha512-fNINQ3X2ZqsCkNB3Z0Z8ElmhewqrS3gy2wgBTx97BkcjOWiyPAGwDJ752hwrsUnWAVBRztgw826n37xPzxsOgg==
-  dependencies:
-    "@commitlint/is-ignored" "^16.2.1"
-    "@commitlint/parse" "^16.2.1"
-    "@commitlint/rules" "^16.2.1"
-    "@commitlint/types" "^16.2.1"
-
-"@commitlint/load@>6.1.1", "@commitlint/load@^16.2.1":
-  version "16.2.1"
-  resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-16.2.1.tgz#301bda1bff66b3e40a85819f854eda72538d8e24"
-  integrity sha512-oSpz0jTyVI/A1AIImxJINTLDOMB8YF7lWGm+Jg5wVWM0r7ucpuhyViVvpSRTgvL0z09oIxlctyFGWUQQpI42uw==
-  dependencies:
-    "@commitlint/config-validator" "^16.2.1"
-    "@commitlint/execute-rule" "^16.2.1"
-    "@commitlint/resolve-extends" "^16.2.1"
-    "@commitlint/types" "^16.2.1"
+"@commitlint/is-ignored@^17.0.3":
+  version "17.0.3"
+  resolved "https://registry.yarnpkg.com/@commitlint/is-ignored/-/is-ignored-17.0.3.tgz#0e1c725c1e50aea5852fb1260bc92b2ee1856425"
+  integrity sha512-/wgCXAvPtFTQZxsVxj7owLeRf5wwzcXLaYmrZPR4a87iD4sCvUIRl1/ogYrtOyUmHwWfQsvjqIB4mWE/SqWSnA==
+  dependencies:
+    "@commitlint/types" "^17.0.0"
+    semver "7.3.7"
+
+"@commitlint/lint@^17.0.3":
+  version "17.0.3"
+  resolved "https://registry.yarnpkg.com/@commitlint/lint/-/lint-17.0.3.tgz#98542a48f03b5c144309e24cbe1c032366ea75e2"
+  integrity sha512-2o1fk7JUdxBUgszyt41sHC/8Nd5PXNpkmuOo9jvGIjDHzOwXyV0PSdbEVTH3xGz9NEmjohFHr5l+N+T9fcxong==
+  dependencies:
+    "@commitlint/is-ignored" "^17.0.3"
+    "@commitlint/parse" "^17.0.0"
+    "@commitlint/rules" "^17.0.0"
+    "@commitlint/types" "^17.0.0"
+
+"@commitlint/load@>6.1.1":
+  version "17.0.0"
+  resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-17.0.0.tgz#0bbefe6d8b99276714c5ea8ef32de2bd2f082698"
+  integrity sha512-XaiHF4yWQOPAI0O6wXvk+NYLtJn/Xb7jgZEeKd4C1ZWd7vR7u8z5h0PkWxSr0uLZGQsElGxv3fiZ32C5+q6M8w==
+  dependencies:
+    "@commitlint/config-validator" "^17.0.0"
+    "@commitlint/execute-rule" "^17.0.0"
+    "@commitlint/resolve-extends" "^17.0.0"
+    "@commitlint/types" "^17.0.0"
     "@types/node" ">=12"
-    chalk "^4.0.0"
+    chalk "^4.1.0"
     cosmiconfig "^7.0.0"
-    cosmiconfig-typescript-loader "^1.0.0"
+    cosmiconfig-typescript-loader "^2.0.0"
     lodash "^4.17.19"
     resolve-from "^5.0.0"
-    typescript "^4.4.3"
+    typescript "^4.6.4"
 
-"@commitlint/message@^16.2.1":
-  version "16.2.1"
-  resolved "https://registry.yarnpkg.com/@commitlint/message/-/message-16.2.1.tgz#bc6a0fa446a746ac2ca78cf372e4cec48daf620d"
-  integrity sha512-2eWX/47rftViYg7a3axYDdrgwKv32mxbycBJT6OQY/MJM7SUfYNYYvbMFOQFaA4xIVZt7t2Alyqslbl6blVwWw==
+"@commitlint/load@^17.0.3":
+  version "17.0.3"
+  resolved "https://registry.yarnpkg.com/@commitlint/load/-/load-17.0.3.tgz#683aa484a5515714512e442f2f4b11f75e66097a"
+  integrity sha512-3Dhvr7GcKbKa/ey4QJ5MZH3+J7QFlARohUow6hftQyNjzoXXROm+RwpBes4dDFrXG1xDw9QPXA7uzrOShCd4bw==
+  dependencies:
+    "@commitlint/config-validator" "^17.0.3"
+    "@commitlint/execute-rule" "^17.0.0"
+    "@commitlint/resolve-extends" "^17.0.3"
+    "@commitlint/types" "^17.0.0"
+    "@types/node" ">=12"
+    chalk "^4.1.0"
+    cosmiconfig "^7.0.0"
+    cosmiconfig-typescript-loader "^2.0.0"
+    lodash "^4.17.19"
+    resolve-from "^5.0.0"
+    typescript "^4.6.4"
 
-"@commitlint/parse@^16.2.1":
-  version "16.2.1"
-  resolved "https://registry.yarnpkg.com/@commitlint/parse/-/parse-16.2.1.tgz#50b359cb711ec566d2ee236a8e4c6baca07b77c0"
-  integrity sha512-2NP2dDQNL378VZYioLrgGVZhWdnJO4nAxQl5LXwYb08nEcN+cgxHN1dJV8OLJ5uxlGJtDeR8UZZ1mnQ1gSAD/g==
+"@commitlint/message@^17.0.0":
+  version "17.0.0"
+  resolved "https://registry.yarnpkg.com/@commitlint/message/-/message-17.0.0.tgz#ae0f8ec6a3e5c8d369792a2c391952c7596cca73"
+  integrity sha512-LpcwYtN+lBlfZijHUdVr8aNFTVpHjuHI52BnfoV01TF7iSLnia0jttzpLkrLmI8HNQz6Vhr9UrxDWtKZiMGsBw==
+
+"@commitlint/parse@^17.0.0":
+  version "17.0.0"
+  resolved "https://registry.yarnpkg.com/@commitlint/parse/-/parse-17.0.0.tgz#6d508a1e2aec76f348a447994f26e9b749c02091"
+  integrity sha512-cKcpfTIQYDG1ywTIr5AG0RAiLBr1gudqEsmAGCTtj8ffDChbBRxm6xXs2nv7GvmJN7msOt7vOKleLvcMmRa1+A==
   dependencies:
-    "@commitlint/types" "^16.2.1"
+    "@commitlint/types" "^17.0.0"
     conventional-changelog-angular "^5.0.11"
     conventional-commits-parser "^3.2.2"
 
-"@commitlint/read@^16.2.1":
-  version "16.2.1"
-  resolved "https://registry.yarnpkg.com/@commitlint/read/-/read-16.2.1.tgz#e0539205d77cdb6879b560f95e5fb251e0c6f562"
-  integrity sha512-tViXGuaxLTrw2r7PiYMQOFA2fueZxnnt0lkOWqKyxT+n2XdEMGYcI9ID5ndJKXnfPGPppD0w/IItKsIXlZ+alw==
+"@commitlint/read@^17.0.0":
+  version "17.0.0"
+  resolved "https://registry.yarnpkg.com/@commitlint/read/-/read-17.0.0.tgz#8ab01cf2f27350d8f81f21690962679a7cae5abf"
+  integrity sha512-zkuOdZayKX3J6F6mPnVMzohK3OBrsEdOByIqp4zQjA9VLw1hMsDEFQ18rKgUc2adkZar+4S01QrFreDCfZgbxA==
   dependencies:
-    "@commitlint/top-level" "^16.2.1"
-    "@commitlint/types" "^16.2.1"
+    "@commitlint/top-level" "^17.0.0"
+    "@commitlint/types" "^17.0.0"
     fs-extra "^10.0.0"
     git-raw-commits "^2.0.0"
 
-"@commitlint/resolve-extends@^16.2.1":
-  version "16.2.1"
-  resolved "https://registry.yarnpkg.com/@commitlint/resolve-extends/-/resolve-extends-16.2.1.tgz#2f7833a5a3a7aa79f508e59fcb0f1d33c45ed360"
-  integrity sha512-NbbCMPKTFf2J805kwfP9EO+vV+XvnaHRcBy6ud5dF35dxMsvdJqke54W3XazXF1ZAxC4a3LBy4i/GNVBAthsEg==
+"@commitlint/resolve-extends@^17.0.0":
+  version "17.0.0"
+  resolved "https://registry.yarnpkg.com/@commitlint/resolve-extends/-/resolve-extends-17.0.0.tgz#3a40ee08184b984acf475ebc962641f435e3a639"
+  integrity sha512-wi60WiJmwaQ7lzMXK8Vbc18Hq9tE2j/6iv2AFfPUGV7fvfY6Sf1iNKuUHirSqR0fquUyufIXe4y/K9A6LVIIvw==
   dependencies:
-    "@commitlint/config-validator" "^16.2.1"
-    "@commitlint/types" "^16.2.1"
+    "@commitlint/config-validator" "^17.0.0"
+    "@commitlint/types" "^17.0.0"
     import-fresh "^3.0.0"
     lodash "^4.17.19"
     resolve-from "^5.0.0"
     resolve-global "^1.0.0"
 
-"@commitlint/rules@^16.2.1":
-  version "16.2.1"
-  resolved "https://registry.yarnpkg.com/@commitlint/rules/-/rules-16.2.1.tgz#7264aa1c754e1c212aeceb27e5eb380cfa7bb233"
-  integrity sha512-ZFezJXQaBBso+BOTre/+1dGCuCzlWVaeLiVRGypI53qVgPMzQqZhkCcrxBFeqB87qeyzr4A4EoG++IvITwwpIw==
+"@commitlint/resolve-extends@^17.0.3":
+  version "17.0.3"
+  resolved "https://registry.yarnpkg.com/@commitlint/resolve-extends/-/resolve-extends-17.0.3.tgz#43b237899e2abd59d16af091521b888c8a071412"
+  integrity sha512-H/RFMvrcBeJCMdnVC4i8I94108UDccIHrTke2tyQEg9nXQnR5/Hd6MhyNWkREvcrxh9Y+33JLb+PiPiaBxCtBA==
   dependencies:
-    "@commitlint/ensure" "^16.2.1"
-    "@commitlint/message" "^16.2.1"
-    "@commitlint/to-lines" "^16.2.1"
-    "@commitlint/types" "^16.2.1"
+    "@commitlint/config-validator" "^17.0.3"
+    "@commitlint/types" "^17.0.0"
+    import-fresh "^3.0.0"
+    lodash "^4.17.19"
+    resolve-from "^5.0.0"
+    resolve-global "^1.0.0"
+
+"@commitlint/rules@^17.0.0":
+  version "17.0.0"
+  resolved "https://registry.yarnpkg.com/@commitlint/rules/-/rules-17.0.0.tgz#4eecc5d28cabbc5f3f73838fb02592b551f9bf62"
+  integrity sha512-45nIy3dERKXWpnwX9HeBzK5SepHwlDxdGBfmedXhL30fmFCkJOdxHyOJsh0+B0RaVsLGT01NELpfzJUmtpDwdQ==
+  dependencies:
+    "@commitlint/ensure" "^17.0.0"
+    "@commitlint/message" "^17.0.0"
+    "@commitlint/to-lines" "^17.0.0"
+    "@commitlint/types" "^17.0.0"
     execa "^5.0.0"
 
-"@commitlint/to-lines@^16.2.1":
-  version "16.2.1"
-  resolved "https://registry.yarnpkg.com/@commitlint/to-lines/-/to-lines-16.2.1.tgz#42d000f34dc0406f514991e86237fdab5e8affd0"
-  integrity sha512-9/VjpYj5j1QeY3eiog1zQWY6axsdWAc0AonUUfyZ7B0MVcRI0R56YsHAfzF6uK/g/WwPZaoe4Lb1QCyDVnpVaQ==
+"@commitlint/to-lines@^17.0.0":
+  version "17.0.0"
+  resolved "https://registry.yarnpkg.com/@commitlint/to-lines/-/to-lines-17.0.0.tgz#5766895836b8085b099a098482f88a03f070b411"
+  integrity sha512-nEi4YEz04Rf2upFbpnEorG8iymyH7o9jYIVFBG1QdzebbIFET3ir+8kQvCZuBE5pKCtViE4XBUsRZz139uFrRQ==
 
-"@commitlint/top-level@^16.2.1":
-  version "16.2.1"
-  resolved "https://registry.yarnpkg.com/@commitlint/top-level/-/top-level-16.2.1.tgz#bdaa53ab3d8970e0288879f1a342a8c2dfe01583"
-  integrity sha512-lS6GSieHW9y6ePL73ied71Z9bOKyK+Ib9hTkRsB8oZFAyQZcyRwq2w6nIa6Fngir1QW51oKzzaXfJL94qwImyw==
+"@commitlint/top-level@^17.0.0":
+  version "17.0.0"
+  resolved "https://registry.yarnpkg.com/@commitlint/top-level/-/top-level-17.0.0.tgz#ebd0df4c703c026c2fbdc20fa746836334f4ed15"
+  integrity sha512-dZrEP1PBJvodNWYPOYiLWf6XZergdksKQaT6i1KSROLdjf5Ai0brLOv5/P+CPxBeoj3vBxK4Ax8H1Pg9t7sHIQ==
   dependencies:
     find-up "^5.0.0"
 
-"@commitlint/types@^16.2.1":
-  version "16.2.1"
-  resolved "https://registry.yarnpkg.com/@commitlint/types/-/types-16.2.1.tgz#f25d373b88b01e51fc3fa44488101361945a61bd"
-  integrity sha512-7/z7pA7BM0i8XvMSBynO7xsB3mVQPUZbVn6zMIlp/a091XJ3qAXRXc+HwLYhiIdzzS5fuxxNIHZMGHVD4HJxdA==
+"@commitlint/types@^17.0.0":
+  version "17.0.0"
+  resolved "https://registry.yarnpkg.com/@commitlint/types/-/types-17.0.0.tgz#3b4604c1a0f06c340ce976e6c6903d4f56e3e690"
+  integrity sha512-hBAw6U+SkAT5h47zDMeOu3HSiD0SODw4Aq7rRNh1ceUmL7GyLKYhPbUvlRWqZ65XjBLPHZhFyQlRaPNz8qvUyQ==
   dependencies:
-    chalk "^4.0.0"
+    chalk "^4.1.0"
 
-"@cspotcode/source-map-consumer@0.8.0":
-  version "0.8.0"
-  resolved "https://registry.yarnpkg.com/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz#33bf4b7b39c178821606f669bbc447a6a629786b"
-  integrity sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==
+"@cspotcode/source-map-support@^0.8.0":
+  version "0.8.1"
+  resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1"
+  integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==
+  dependencies:
+    "@jridgewell/trace-mapping" "0.3.9"
 
-"@cspotcode/source-map-support@0.7.0":
-  version "0.7.0"
-  resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz#4789840aa859e46d2f3173727ab707c66bf344f5"
-  integrity sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==
+"@cypress/request@^2.88.10":
+  version "2.88.10"
+  resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.10.tgz#b66d76b07f860d3a4b8d7a0604d020c662752cce"
+  integrity sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg==
   dependencies:
-    "@cspotcode/source-map-consumer" "0.8.0"
+    aws-sign2 "~0.7.0"
+    aws4 "^1.8.0"
+    caseless "~0.12.0"
+    combined-stream "~1.0.6"
+    extend "~3.0.2"
+    forever-agent "~0.6.1"
+    form-data "~2.3.2"
+    http-signature "~1.3.6"
+    is-typedarray "~1.0.0"
+    isstream "~0.1.2"
+    json-stringify-safe "~5.0.1"
+    mime-types "~2.1.19"
+    performance-now "^2.1.0"
+    qs "~6.5.2"
+    safe-buffer "^5.1.2"
+    tough-cookie "~2.5.0"
+    tunnel-agent "^0.6.0"
+    uuid "^8.3.2"
+
+"@cypress/xvfb@^1.2.4":
+  version "1.2.4"
+  resolved "https://registry.yarnpkg.com/@cypress/xvfb/-/xvfb-1.2.4.tgz#2daf42e8275b39f4aa53c14214e557bd14e7748a"
+  integrity sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==
+  dependencies:
+    debug "^3.1.0"
+    lodash.once "^4.1.1"
 
 "@dabh/diagnostics@^2.0.2":
   version "2.0.3"
@@ -1193,9 +1487,9 @@
     kuler "^2.0.0"
 
 "@emotion/babel-plugin@^11.7.1":
-  version "11.7.2"
-  resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.7.2.tgz#fec75f38a6ab5b304b0601c74e2a5e77c95e5fa0"
-  integrity sha512-6mGSCWi9UzXut/ZAN6lGFu33wGR3SJisNl3c0tvlmb8XChH1b2SUvxvnOh7hvLpqyRdHHU9AiazV3Cwbk5SXKQ==
+  version "11.9.2"
+  resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.9.2.tgz#723b6d394c89fb2ef782229d92ba95a740576e95"
+  integrity sha512-Pr/7HGH6H6yKgnVFNEj2MVlreu3ADqftqjqwUvDy/OJzKFgxKeTQ+eeUf20FOTuHVkDON2iNa25rAXVYtWJCjw==
   dependencies:
     "@babel/helper-module-imports" "^7.12.13"
     "@babel/plugin-syntax-jsx" "^7.12.13"
@@ -1267,15 +1561,15 @@
   resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50"
   integrity sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ==
 
-"@emotion/react@^11.1.1":
-  version "11.8.2"
-  resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.8.2.tgz#e51f5e6372e22e82780836c9288da19af4b51e70"
-  integrity sha512-+1bcHBaNJv5nkIIgnGKVsie3otS0wF9f1T1hteF3WeVvMNQEtfZ4YyFpnphGoot3ilU/wWMgP2SgIDuHLE/wAA==
+"@emotion/react@^11.8.1":
+  version "11.9.0"
+  resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.9.0.tgz#b6d42b1db3bd7511e7a7c4151dc8bc82e14593b8"
+  integrity sha512-lBVSF5d0ceKtfKCDQJveNAtkC7ayxpVlgOohLgXqRwqWr9bOf4TZAFFyIcNngnV6xK6X4x2ZeXq7vliHkoVkxQ==
   dependencies:
     "@babel/runtime" "^7.13.10"
     "@emotion/babel-plugin" "^11.7.1"
     "@emotion/cache" "^11.7.1"
-    "@emotion/serialize" "^1.0.2"
+    "@emotion/serialize" "^1.0.3"
     "@emotion/utils" "^1.1.0"
     "@emotion/weak-memoize" "^0.2.5"
     hoist-non-react-statics "^3.3.1"
@@ -1291,10 +1585,10 @@
     "@emotion/utils" "0.11.3"
     csstype "^2.5.7"
 
-"@emotion/serialize@^1.0.2":
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.2.tgz#77cb21a0571c9f68eb66087754a65fa97bfcd965"
-  integrity sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==
+"@emotion/serialize@^1.0.2", "@emotion/serialize@^1.0.3":
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.3.tgz#99e2060c26c6292469fb30db41f4690e1c8fea63"
+  integrity sha512-2mSSvgLfyV3q+iVh3YWgNlUc2a9ZlDU7DjuP5MjK3AXRR0dYigCrP99aeFtaB2L/hjfEZdSThn5dsZ0ufqbvsA==
   dependencies:
     "@emotion/hash" "^0.8.0"
     "@emotion/memoize" "^0.7.4"
@@ -1337,28 +1631,28 @@
   resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46"
   integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==
 
-"@eslint/eslintrc@^1.2.1":
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.2.1.tgz#8b5e1c49f4077235516bc9ec7d41378c0f69b8c6"
-  integrity sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==
+"@eslint/eslintrc@^1.3.0":
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz#29f92c30bb3e771e4a2048c95fa6855392dfac4f"
+  integrity sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==
   dependencies:
     ajv "^6.12.4"
     debug "^4.3.2"
-    espree "^9.3.1"
-    globals "^13.9.0"
+    espree "^9.3.2"
+    globals "^13.15.0"
     ignore "^5.2.0"
     import-fresh "^3.2.1"
     js-yaml "^4.1.0"
-    minimatch "^3.0.4"
+    minimatch "^3.1.2"
     strip-json-comments "^3.1.1"
 
-"@formatjs/ecma402-abstract@1.11.3":
-  version "1.11.3"
-  resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.3.tgz#f25276dfd4ef3dac90da667c3961d8aa9732e384"
-  integrity sha512-kP/Buv5vVFMAYLHNvvUzr0lwRTU0u2WTy44Tqwku1X3C3lJ5dKqDCYVqA8wL+Y19Bq+MwHgxqd5FZJRCIsLRyQ==
+"@formatjs/ecma402-abstract@1.11.8":
+  version "1.11.8"
+  resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-1.11.8.tgz#f4015dfb6a837369d94c6ba82455c609e45bce20"
+  integrity sha512-fgLqyWlwmTEuqV/TSLEL/t9JOmHNLFvCdgzXB0jc2w+WOItPCOJ1T0eyN6fQBQKRPfSqqNlu+kWj7ijcOVTVVQ==
   dependencies:
-    "@formatjs/intl-localematcher" "0.2.24"
-    tslib "^2.1.0"
+    "@formatjs/intl-localematcher" "0.2.28"
+    tslib "2.4.0"
 
 "@formatjs/ecma402-abstract@1.4.0":
   version "1.4.0"
@@ -1374,54 +1668,70 @@
   dependencies:
     tslib "^2.0.1"
 
-"@formatjs/fast-memoize@1.2.1":
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-1.2.1.tgz#e6f5aee2e4fd0ca5edba6eba7668e2d855e0fc21"
-  integrity sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg==
+"@formatjs/fast-memoize@1.2.4":
+  version "1.2.4"
+  resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-1.2.4.tgz#4b5ddce9eb7803ff0bd4052387672151a8b7f8a0"
+  integrity sha512-9ARYoLR8AEzXvj2nYrOVHY/h1dDMDWGTnKDLXSISF1uoPakSmfcZuSqjiqZX2wRkEUimPxdwTu/agyozBtZRHA==
   dependencies:
-    tslib "^2.1.0"
+    tslib "2.4.0"
 
-"@formatjs/icu-messageformat-parser@2.0.18":
-  version "2.0.18"
-  resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.0.18.tgz#b09e8f16b88e988fd125e7c5810300e8a6dd2c42"
-  integrity sha512-vquIzsAJJmZ5jWVH8dEgUKcbG4yu3KqtyPet+q35SW5reLOvblkfeCXTRW2TpIwNXzdVqsJBwjbTiRiSU9JxwQ==
+"@formatjs/icu-messageformat-parser@2.1.4":
+  version "2.1.4"
+  resolved "https://registry.yarnpkg.com/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.1.4.tgz#f1e32b9937f151c1dd5c30536ce3e920b7f23813"
+  integrity sha512-3PqMvKWV1oyok0BuiXUAHIaotdhdTJw6OICqCZbfUgKT+ZRwRWO4IlCgvXJeCITaKS5p+PY0XXKjf/vUyIpWjQ==
   dependencies:
-    "@formatjs/ecma402-abstract" "1.11.3"
-    "@formatjs/icu-skeleton-parser" "1.3.5"
-    tslib "^2.1.0"
+    "@formatjs/ecma402-abstract" "1.11.8"
+    "@formatjs/icu-skeleton-parser" "1.3.10"
+    tslib "2.4.0"
 
-"@formatjs/icu-skeleton-parser@1.3.5":
-  version "1.3.5"
-  resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.3.5.tgz#babc93a1c36383cf87cbb3d2f2145d26c2f7cb40"
-  integrity sha512-Nhyo2/6kG7ZfgeEfo02sxviOuBcvtzH6SYUharj3DLCDJH3A/4OxkKcmx/2PWGX4bc6iSieh+FA94CsKDxnZBQ==
+"@formatjs/icu-skeleton-parser@1.3.10":
+  version "1.3.10"
+  resolved "https://registry.yarnpkg.com/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.3.10.tgz#2f504e56ac80137ee2baad55c7fa0b5dc7f4e4df"
+  integrity sha512-kXJmtLDqFF5aLTf8IxdJXnhrIX1Qb4Qp3a9jqRecGDYfzOa9hMhi9U0nKyhrJJ4cXxBzptcgb+LWkyeHL6nlBQ==
   dependencies:
-    "@formatjs/ecma402-abstract" "1.11.3"
-    tslib "^2.1.0"
+    "@formatjs/ecma402-abstract" "1.11.8"
+    tslib "2.4.0"
 
-"@formatjs/intl-displaynames@5.4.2":
-  version "5.4.2"
-  resolved "https://registry.yarnpkg.com/@formatjs/intl-displaynames/-/intl-displaynames-5.4.2.tgz#feb6b41087a88286d178032490a8ca78bafd4c56"
-  integrity sha512-SLesCDan9NCMqBbHPXMEwqAcPn3tnbQw0sv0rssH1JQDLDUQYwKXL93kz30X3yskTyQS7N+pd47bhoIe3kbXyw==
+"@formatjs/intl-displaynames@6.0.3":
+  version "6.0.3"
+  resolved "https://registry.yarnpkg.com/@formatjs/intl-displaynames/-/intl-displaynames-6.0.3.tgz#e648a91bccd9fb21519090eaafece3be9d15f480"
+  integrity sha512-Mxh6W1VOlmiEvO/QPBrBQHlXrIn5VxjJWyyEI0V7ZHNGl0ee8AjSlq7vIJG8GodRJqGUuutF6N3OB/6qFv0YWg==
   dependencies:
-    "@formatjs/ecma402-abstract" "1.11.3"
-    "@formatjs/intl-localematcher" "0.2.24"
-    tslib "^2.1.0"
+    "@formatjs/ecma402-abstract" "1.11.8"
+    "@formatjs/intl-localematcher" "0.2.28"
+    tslib "2.4.0"
 
-"@formatjs/intl-listformat@6.5.2":
-  version "6.5.2"
-  resolved "https://registry.yarnpkg.com/@formatjs/intl-listformat/-/intl-listformat-6.5.2.tgz#7fbc310db89e866250e34084e914894c67e09254"
-  integrity sha512-/IYagQJkzTvpBlhhaysGYNgM3o72WBg1ZWZcpookkgXEJbINwLP5kVagHxmgxffYKs1CDzQ8rmKHghu2qR/7zw==
+"@formatjs/intl-getcanonicallocales@2.0.2":
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/@formatjs/intl-getcanonicallocales/-/intl-getcanonicallocales-2.0.2.tgz#e9fd5d2215ce0dba4d8611b37ac87c5fae60a1a7"
+  integrity sha512-nMkPblAjgK49ORueVhyuKJDXOCq8at2h9Xf0lqabBZylaX3xLEeuAW2eMXuwJ/ascYYQnwuxeukd/qlzDkuJzQ==
   dependencies:
-    "@formatjs/ecma402-abstract" "1.11.3"
-    "@formatjs/intl-localematcher" "0.2.24"
-    tslib "^2.1.0"
+    tslib "2.4.0"
 
-"@formatjs/intl-localematcher@0.2.24":
-  version "0.2.24"
-  resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.2.24.tgz#b49fd753c0f54421f26a3c1d0e9cf98a3966e78f"
-  integrity sha512-K/HRGo6EMnCbhpth/y3u4rW4aXkmQNqRe1L2G+Y5jNr3v0gYhvaucV8WixNju/INAMbPBlbsRBRo/nfjnoOnxQ==
+"@formatjs/intl-listformat@7.0.3":
+  version "7.0.3"
+  resolved "https://registry.yarnpkg.com/@formatjs/intl-listformat/-/intl-listformat-7.0.3.tgz#8627969b77849559d148bc9536d0884c2271e6de"
+  integrity sha512-ampNLRGZl/08epHa3i5sRmcHGLneC6JrknexbbgnexYFNSmJ6AbL/dCzgrQzw2Efl+5AZK7UbNFxcDYY3RePvw==
   dependencies:
-    tslib "^2.1.0"
+    "@formatjs/ecma402-abstract" "1.11.8"
+    "@formatjs/intl-localematcher" "0.2.28"
+    tslib "2.4.0"
+
+"@formatjs/intl-locale@3.0.3":
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/@formatjs/intl-locale/-/intl-locale-3.0.3.tgz#ae112831c06209d1d7286b36e7b824a5e84ddd63"
+  integrity sha512-AZrh8z/GaR+4ogy9LR1lKouXwXWKRK4TDtwFv6SIFIJgF9SQ6l4gdJ1/k13susw6NMAQiKdtG9IdhEtKXsp+6w==
+  dependencies:
+    "@formatjs/ecma402-abstract" "1.11.8"
+    "@formatjs/intl-getcanonicallocales" "2.0.2"
+    tslib "2.4.0"
+
+"@formatjs/intl-localematcher@0.2.28":
+  version "0.2.28"
+  resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.2.28.tgz#412ea7fefbfc7ed33cd6b43aa304fc14d816e564"
+  integrity sha512-FLsc6Gifs1np/8HnCn/7Q+lHMmenrD5fuDhRT82yj0gi9O19kfaFwjQUw1gZsyILuRyT93GuzdifHj7TKRhBcw==
+  dependencies:
+    tslib "2.4.0"
 
 "@formatjs/intl-numberformat@^5.5.2":
   version "5.7.6"
@@ -1431,18 +1741,34 @@
     "@formatjs/ecma402-abstract" "1.4.0"
     tslib "^2.0.1"
 
-"@formatjs/intl@2.1.0":
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/@formatjs/intl/-/intl-2.1.0.tgz#383b186b1f26195ac896fc6912871abccf9dad2d"
-  integrity sha512-1iGGqKcCym+ZH+cktHa6YILVGn8Sve+yuYK7hJpN21JiPKCPJuFJViKFY6rDM5jnj5LDCeH8N5YbhQjccDVOVA==
-  dependencies:
-    "@formatjs/ecma402-abstract" "1.11.3"
-    "@formatjs/fast-memoize" "1.2.1"
-    "@formatjs/icu-messageformat-parser" "2.0.18"
-    "@formatjs/intl-displaynames" "5.4.2"
-    "@formatjs/intl-listformat" "6.5.2"
-    intl-messageformat "9.11.4"
-    tslib "^2.1.0"
+"@formatjs/intl-pluralrules@5.0.3":
+  version "5.0.3"
+  resolved "https://registry.yarnpkg.com/@formatjs/intl-pluralrules/-/intl-pluralrules-5.0.3.tgz#78d76da83470495e3e4d82df8cd6250578c1685c"
+  integrity sha512-av3ks022vDE1dbCUAqwYc8bnGRcAPKK6C7ZRINNjjQn43ZQVX1AXc7PY2RqO/GXzkixsSWfHFZjSgzzbhbd21A==
+  dependencies:
+    "@formatjs/ecma402-abstract" "1.11.8"
+    "@formatjs/intl-localematcher" "0.2.28"
+    tslib "2.4.0"
+
+"@formatjs/intl-utils@3.8.4":
+  version "3.8.4"
+  resolved "https://registry.yarnpkg.com/@formatjs/intl-utils/-/intl-utils-3.8.4.tgz#291baac91001db428fc3275c515a3e40fbe95945"
+  integrity sha512-j5C6NyfKevIxsfLK8KwO1C0vvP7k1+h4A9cFpc+cr6mEwCc1sPkr17dzh0Ke6k9U5pQccAQoXdcNBl3IYa4+ZQ==
+  dependencies:
+    emojis-list "^3.0.0"
+
+"@formatjs/intl@2.3.1":
+  version "2.3.1"
+  resolved "https://registry.yarnpkg.com/@formatjs/intl/-/intl-2.3.1.tgz#eccd6d03e4db18c256181f235b1d0a7f7aaebf5a"
+  integrity sha512-f06qZ/ukpeN24gc01qFjh3P+r3FU/ikY4yG+fDJu6dPNvpUQzDy98lYogA1dr6ig2UtrnoEk3xncyFPL1e9cZw==
+  dependencies:
+    "@formatjs/ecma402-abstract" "1.11.8"
+    "@formatjs/fast-memoize" "1.2.4"
+    "@formatjs/icu-messageformat-parser" "2.1.4"
+    "@formatjs/intl-displaynames" "6.0.3"
+    "@formatjs/intl-listformat" "7.0.3"
+    intl-messageformat "10.1.1"
+    tslib "2.4.0"
 
 "@formatjs/ts-transformer@2.13.0", "@formatjs/ts-transformer@^2.6.0":
   version "2.13.0"
@@ -1453,18 +1779,20 @@
     tslib "^2.0.1"
     typescript "^4.0"
 
-"@formatjs/ts-transformer@3.9.2":
-  version "3.9.2"
-  resolved "https://registry.yarnpkg.com/@formatjs/ts-transformer/-/ts-transformer-3.9.2.tgz#958582b16ed9125fd904c051a9dda1ecd2474a5a"
-  integrity sha512-Iff+ca1ue3IOb/PDNANR6++EArwlyMpW+t6AL4MG5sordpgflsIh8BMz6nGs+/tUOjP0xioNAu/acYiQ+rW5Bw==
+"@formatjs/ts-transformer@3.9.9":
+  version "3.9.9"
+  resolved "https://registry.yarnpkg.com/@formatjs/ts-transformer/-/ts-transformer-3.9.9.tgz#4804e0560e1944407e9dc5f5ae568a329d5668e4"
+  integrity sha512-V5BDpn5XW1wWBkpDn5SFHRH4Ndf3oyjxmuqWMxe2EwOKkV4XJvzZI73k3p/Hut3Xg55AxBQQmkFK9hyeBJPyIg==
   dependencies:
-    "@formatjs/icu-messageformat-parser" "2.0.18"
+    "@formatjs/icu-messageformat-parser" "2.1.4"
+    "@types/json-stable-stringify" "^1.0.32"
     "@types/node" "14 || 16 || 17"
     chalk "^4.0.0"
-    tslib "^2.1.0"
+    json-stable-stringify "^1.0.1"
+    tslib "2.4.0"
     typescript "^4.5"
 
-"@gar/promisify@^1.0.1":
+"@gar/promisify@^1.0.1", "@gar/promisify@^1.1.3":
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
   integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==
@@ -1477,29 +1805,34 @@
     "@hapi/hoek" "9.x.x"
 
 "@hapi/hoek@9.x.x":
-  version "9.2.1"
-  resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.2.1.tgz#9551142a1980503752536b5050fd99f4a7f13b17"
-  integrity sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw==
+  version "9.3.0"
+  resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
+  integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==
 
-"@headlessui/react@^1.5.0":
-  version "1.5.0"
-  resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.5.0.tgz#483b44ba2c8b8d4391e1d2c863898d7dd0cc0296"
-  integrity sha512-aaRnYxBb3MU2FNJf3Ut9RMTUqqU3as0aI1lQhgo2n9Fa67wRu14iOGqx93xB+uMNVfNwZ5B3y/Ndm7qZGuFeMQ==
+"@headlessui/react@0.0.0-insiders.b301f04":
+  version "0.0.0-insiders.b301f04"
+  resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-0.0.0-insiders.b301f04.tgz#12f209097f987cddbba72de40240a12648ebe12b"
+  integrity sha512-I+UUEUkdYp+AgKU1teWUZaICEg//OWl0R1UxCB50Jzfi3APu7aSY0Y+ABrgfEWDhBYTG9hNgXvMVTNCnFu49yA==
 
-"@heroicons/react@^1.0.6":
+"@heroicons/react@1.0.6":
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-1.0.6.tgz#35dd26987228b39ef2316db3b1245c42eb19e324"
   integrity sha512-JJCXydOFWMDpCP4q13iEplA503MQO3xLoZiKum+955ZCtHINWnx26CUxVxxFQu/uLb4LW3ge15ZpzIkXKkJ8oQ==
 
-"@humanwhocodes/config-array@^0.9.2":
-  version "0.9.5"
-  resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7"
-  integrity sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==
+"@humanwhocodes/config-array@^0.10.4":
+  version "0.10.4"
+  resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.10.4.tgz#01e7366e57d2ad104feea63e72248f22015c520c"
+  integrity sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==
   dependencies:
     "@humanwhocodes/object-schema" "^1.2.1"
     debug "^4.1.1"
     minimatch "^3.0.4"
 
+"@humanwhocodes/gitignore-to-minimatch@^1.0.2":
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz#316b0a63b91c10e53f242efb4ace5c3b34e8728d"
+  integrity sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==
+
 "@humanwhocodes/object-schema@^1.2.1":
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
@@ -1510,20 +1843,64 @@
   resolved "https://registry.yarnpkg.com/@isaacs/string-locale-compare/-/string-locale-compare-1.1.0.tgz#291c227e93fd407a96ecd59879a35809120e432b"
   integrity sha512-SQ7Kzhh9+D+ZW9MA0zkYv3VXhIDNx+LzM6EJ+/65I3QY+enU6Itte7E5XX7EWrqLW2FN4n06GWzBnPoC3th2aQ==
 
+"@jridgewell/gen-mapping@^0.1.0":
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996"
+  integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==
+  dependencies:
+    "@jridgewell/set-array" "^1.0.0"
+    "@jridgewell/sourcemap-codec" "^1.4.10"
+
+"@jridgewell/gen-mapping@^0.3.0":
+  version "0.3.1"
+  resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.1.tgz#cf92a983c83466b8c0ce9124fadeaf09f7c66ea9"
+  integrity sha512-GcHwniMlA2z+WFPWuY8lp3fsza0I8xPFMWL5+n8LYyP6PSvPrXf4+n8stDHZY2DM0zy9sVkRDy1jDI4XGzYVqg==
+  dependencies:
+    "@jridgewell/set-array" "^1.0.0"
+    "@jridgewell/sourcemap-codec" "^1.4.10"
+    "@jridgewell/trace-mapping" "^0.3.9"
+
+"@jridgewell/gen-mapping@^0.3.2":
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9"
+  integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==
+  dependencies:
+    "@jridgewell/set-array" "^1.0.1"
+    "@jridgewell/sourcemap-codec" "^1.4.10"
+    "@jridgewell/trace-mapping" "^0.3.9"
+
 "@jridgewell/resolve-uri@^3.0.3":
-  version "3.0.5"
-  resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.5.tgz#68eb521368db76d040a6315cdb24bf2483037b9c"
-  integrity sha512-VPeQ7+wH0itvQxnG+lIzWgkysKIr3L9sslimFW55rHMdGu/qCQ5z5h9zq4gI8uBtqkpHhsF4Z/OwExufUCThew==
+  version "3.0.7"
+  resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.0.7.tgz#30cd49820a962aff48c8fffc5cd760151fca61fe"
+  integrity sha512-8cXDaBBHOr2pQ7j77Y6Vp5VDT2sIqWyWQ56TjEq4ih/a4iST3dItRe8Q9fp0rrIl9DoKhWQtUQz/YpOxLkXbNA==
+
+"@jridgewell/set-array@^1.0.0":
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.1.tgz#36a6acc93987adcf0ba50c66908bd0b70de8afea"
+  integrity sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==
+
+"@jridgewell/set-array@^1.0.1":
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
+  integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
 
 "@jridgewell/sourcemap-codec@^1.4.10":
-  version "1.4.11"
-  resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.11.tgz#771a1d8d744eeb71b6adb35808e1a6c7b9b8c8ec"
-  integrity sha512-Fg32GrJo61m+VqYSdRSjRXMjQ06j8YIYfcTqndLYVAaHmroZHLJZCydsWBOTDqXS2v+mjxohBWEMfg97GXmYQg==
+  version "1.4.13"
+  resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.13.tgz#b6461fb0c2964356c469e115f504c95ad97ab88c"
+  integrity sha512-GryiOJmNcWbovBxTfZSF71V/mXbgcV3MewDe3kIMCLyIh5e7SKAeUZs+rMnJ8jkMolZ/4/VsdBmMrw3l+VdZ3w==
 
-"@jridgewell/trace-mapping@^0.3.0", "@jridgewell/trace-mapping@^0.3.4":
-  version "0.3.4"
-  resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.4.tgz#f6a0832dffd5b8a6aaa633b7d9f8e8e94c83a0c3"
-  integrity sha512-vFv9ttIedivx0ux3QSjhgtCVjPZd5l46ZOMDSCwnH1yUO2e964gO8LZGyv2QkqcgR6TnBU1v+1IFqmeoG+0UJQ==
+"@jridgewell/trace-mapping@0.3.9":
+  version "0.3.9"
+  resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9"
+  integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==
+  dependencies:
+    "@jridgewell/resolve-uri" "^3.0.3"
+    "@jridgewell/sourcemap-codec" "^1.4.10"
+
+"@jridgewell/trace-mapping@^0.3.8", "@jridgewell/trace-mapping@^0.3.9":
+  version "0.3.13"
+  resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea"
+  integrity sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==
   dependencies:
     "@jridgewell/resolve-uri" "^3.0.3"
     "@jridgewell/sourcemap-codec" "^1.4.10"
@@ -1560,14 +1937,14 @@
     tlds "^1.230.0"
 
 "@mapbox/node-pre-gyp@^1.0.0":
-  version "1.0.8"
-  resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.8.tgz#32abc8a5c624bc4e46c43d84dfb8b26d33a96f58"
-  integrity sha512-CMGKi28CF+qlbXh26hDe6NxCd7amqeAzEqnS6IHeO6LoaKyM/n+Xw3HT1COdq8cuioOdlKdqn/hCmqPUOMOywg==
+  version "1.0.9"
+  resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.9.tgz#09a8781a3a036151cdebbe8719d6f8b25d4058bc"
+  integrity sha512-aDF3S3rK9Q2gey/WAttUlISduDItz5BU3306M9Eyv6/oS40aMprnopshtlKTykxRNIBEZuRMaZAnbrQ4QtKGyw==
   dependencies:
-    detect-libc "^1.0.3"
+    detect-libc "^2.0.0"
     https-proxy-agent "^5.0.0"
     make-dir "^3.1.0"
-    node-fetch "^2.6.5"
+    node-fetch "^2.6.7"
     nopt "^5.0.0"
     npmlog "^5.0.1"
     rimraf "^3.0.2"
@@ -1610,72 +1987,82 @@
   dependencies:
     make-plural "^7.0.0"
 
-"@next/env@12.1.0":
-  version "12.1.0"
-  resolved "https://registry.yarnpkg.com/@next/env/-/env-12.1.0.tgz#73713399399b34aa5a01771fb73272b55b22c314"
-  integrity sha512-nrIgY6t17FQ9xxwH3jj0a6EOiQ/WDHUos35Hghtr+SWN/ntHIQ7UpuvSi0vaLzZVHQWaDupKI+liO5vANcDeTQ==
+"@next/env@12.2.5":
+  version "12.2.5"
+  resolved "https://registry.yarnpkg.com/@next/env/-/env-12.2.5.tgz#d908c57b35262b94db3e431e869b72ac3e1ad3e3"
+  integrity sha512-vLPLV3cpPGjUPT3PjgRj7e3nio9t6USkuew3JE/jMeon/9Mvp1WyR18v3iwnCuX7eUAm1HmAbJHHLAbcu/EJcw==
 
-"@next/eslint-plugin-next@12.1.0":
-  version "12.1.0"
-  resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.1.0.tgz#32586a11378b3ffa5a93ac40a3c44ad99d70e95a"
-  integrity sha512-WFiyvSM2G5cQmh32t/SiQuJ+I2O+FHVlK/RFw5b1565O2kEM/36EXncjt88Pa+X5oSc+1SS+tWxowWJd1lqI+g==
+"@next/eslint-plugin-next@12.2.5":
+  version "12.2.5"
+  resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-12.2.5.tgz#4f3acccd2ed4f9300fbf9fd480cc8a0b261889a8"
+  integrity sha512-VBjVbmqEzGiOTBq4+wpeVXt/KgknnGB6ahvC/AxiIGnN93/RCSyXhFRI4uSfftM2Ba3w7ZO7076bfKasZsA0fw==
   dependencies:
     glob "7.1.7"
 
-"@next/swc-android-arm64@12.1.0":
-  version "12.1.0"
-  resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.1.0.tgz#865ba3a9afc204ff2bdeea49dd64d58705007a39"
-  integrity sha512-/280MLdZe0W03stA69iL+v6I+J1ascrQ6FrXBlXGCsGzrfMaGr7fskMa0T5AhQIVQD4nA/46QQWxG//DYuFBcA==
-
-"@next/swc-darwin-arm64@12.1.0":
-  version "12.1.0"
-  resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.0.tgz#08e8b411b8accd095009ed12efbc2f1d4d547135"
-  integrity sha512-R8vcXE2/iONJ1Unf5Ptqjk6LRW3bggH+8drNkkzH4FLEQkHtELhvcmJwkXcuipyQCsIakldAXhRbZmm3YN1vXg==
-
-"@next/swc-darwin-x64@12.1.0":
-  version "12.1.0"
-  resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.1.0.tgz#fcd684497a76e8feaca88db3c394480ff0b007cd"
-  integrity sha512-ieAz0/J0PhmbZBB8+EA/JGdhRHBogF8BWaeqR7hwveb6SYEIJaDNQy0I+ZN8gF8hLj63bEDxJAs/cEhdnTq+ug==
-
-"@next/swc-linux-arm-gnueabihf@12.1.0":
-  version "12.1.0"
-  resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.1.0.tgz#9ec6380a27938a5799aaa6035c205b3c478468a7"
-  integrity sha512-njUd9hpl6o6A5d08dC0cKAgXKCzm5fFtgGe6i0eko8IAdtAPbtHxtpre3VeSxdZvuGFh+hb0REySQP9T1ttkog==
-
-"@next/swc-linux-arm64-gnu@12.1.0":
-  version "12.1.0"
-  resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.1.0.tgz#7f4196dff1049cea479607c75b81033ae2dbd093"
-  integrity sha512-OqangJLkRxVxMhDtcb7Qn1xjzFA3s50EIxY7mljbSCLybU+sByPaWAHY4px97ieOlr2y4S0xdPKkQ3BCAwyo6Q==
-
-"@next/swc-linux-arm64-musl@12.1.0":
-  version "12.1.0"
-  resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.1.0.tgz#b445f767569cdc2dddee785ca495e1a88c025566"
-  integrity sha512-hB8cLSt4GdmOpcwRe2UzI5UWn6HHO/vLkr5OTuNvCJ5xGDwpPXelVkYW/0+C3g5axbDW2Tym4S+MQCkkH9QfWA==
-
-"@next/swc-linux-x64-gnu@12.1.0":
-  version "12.1.0"
-  resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.1.0.tgz#67610e9be4fbc987de7535f1bcb17e45fe12f90e"
-  integrity sha512-OKO4R/digvrVuweSw/uBM4nSdyzsBV5EwkUeeG4KVpkIZEe64ZwRpnFB65bC6hGwxIBnTv5NMSnJ+0K/WmG78A==
-
-"@next/swc-linux-x64-musl@12.1.0":
-  version "12.1.0"
-  resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.1.0.tgz#ea19a23db08a9f2e34ac30401f774cf7d1669d31"
-  integrity sha512-JohhgAHZvOD3rQY7tlp7NlmvtvYHBYgY0x5ZCecUT6eCCcl9lv6iV3nfu82ErkxNk1H893fqH0FUpznZ/H3pSw==
-
-"@next/swc-win32-arm64-msvc@12.1.0":
-  version "12.1.0"
-  resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.1.0.tgz#eadf054fc412085659b98e145435bbba200b5283"
-  integrity sha512-T/3gIE6QEfKIJ4dmJk75v9hhNiYZhQYAoYm4iVo1TgcsuaKLFa+zMPh4056AHiG6n9tn2UQ1CFE8EoybEsqsSw==
-
-"@next/swc-win32-ia32-msvc@12.1.0":
-  version "12.1.0"
-  resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.1.0.tgz#68faeae10c89f698bf9d28759172b74c9c21bda1"
-  integrity sha512-iwnKgHJdqhIW19H9PRPM9j55V6RdcOo6rX+5imx832BCWzkDbyomWnlzBfr6ByUYfhohb8QuH4hSGEikpPqI0Q==
-
-"@next/swc-win32-x64-msvc@12.1.0":
-  version "12.1.0"
-  resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.0.tgz#d27e7e76c87a460a4da99c5bfdb1618dcd6cd064"
-  integrity sha512-aBvcbMwuanDH4EMrL2TthNJy+4nP59Bimn8egqv6GHMVj0a44cU6Au4PjOhLNqEh9l+IpRGBqMTzec94UdC5xg==
+"@next/swc-android-arm-eabi@12.2.5":
+  version "12.2.5"
+  resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.2.5.tgz#903a5479ab4c2705d9c08d080907475f7bacf94d"
+  integrity sha512-cPWClKxGhgn2dLWnspW+7psl3MoLQUcNqJqOHk2BhNcou9ARDtC0IjQkKe5qcn9qg7I7U83Gp1yh2aesZfZJMA==
+
+"@next/swc-android-arm64@12.2.5":
+  version "12.2.5"
+  resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.2.5.tgz#2f9a98ec4166c7860510963b31bda1f57a77c792"
+  integrity sha512-vMj0efliXmC5b7p+wfcQCX0AfU8IypjkzT64GiKJD9PgiA3IILNiGJr1fw2lyUDHkjeWx/5HMlMEpLnTsQslwg==
+
+"@next/swc-darwin-arm64@12.2.5":
+  version "12.2.5"
+  resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.2.5.tgz#31b1c3c659d54be546120c488a1e1bad21c24a1d"
+  integrity sha512-VOPWbO5EFr6snla/WcxUKtvzGVShfs302TEMOtzYyWni6f9zuOetijJvVh9CCTzInnXAZMtHyNhefijA4HMYLg==
+
+"@next/swc-darwin-x64@12.2.5":
+  version "12.2.5"
+  resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.2.5.tgz#2e44dd82b2b7fef88238d1bc4d3bead5884cedfd"
+  integrity sha512-5o8bTCgAmtYOgauO/Xd27vW52G2/m3i5PX7MUYePquxXAnX73AAtqA3WgPXBRitEB60plSKZgOTkcpqrsh546A==
+
+"@next/swc-freebsd-x64@12.2.5":
+  version "12.2.5"
+  resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.2.5.tgz#e24e75d8c2581bfebc75e4f08f6ddbd116ce9dbd"
+  integrity sha512-yYUbyup1JnznMtEBRkK4LT56N0lfK5qNTzr6/DEyDw5TbFVwnuy2hhLBzwCBkScFVjpFdfiC6SQAX3FrAZzuuw==
+
+"@next/swc-linux-arm-gnueabihf@12.2.5":
+  version "12.2.5"
+  resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.2.5.tgz#46d8c514d834d2b5f67086013f0bd5e3081e10b9"
+  integrity sha512-2ZE2/G921Acks7UopJZVMgKLdm4vN4U0yuzvAMJ6KBavPzqESA2yHJlm85TV/K9gIjKhSk5BVtauIUntFRP8cg==
+
+"@next/swc-linux-arm64-gnu@12.2.5":
+  version "12.2.5"
+  resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.2.5.tgz#91f725ac217d3a1f4f9f53b553615ba582fd3d9f"
+  integrity sha512-/I6+PWVlz2wkTdWqhlSYYJ1pWWgUVva6SgX353oqTh8njNQp1SdFQuWDqk8LnM6ulheVfSsgkDzxrDaAQZnzjQ==
+
+"@next/swc-linux-arm64-musl@12.2.5":
+  version "12.2.5"
+  resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.2.5.tgz#e627e8c867920995810250303cd9b8e963598383"
+  integrity sha512-LPQRelfX6asXyVr59p5sTpx5l+0yh2Vjp/R8Wi4X9pnqcayqT4CUJLiHqCvZuLin3IsFdisJL0rKHMoaZLRfmg==
+
+"@next/swc-linux-x64-gnu@12.2.5":
+  version "12.2.5"
+  resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.2.5.tgz#83a5e224fbc4d119ef2e0f29d0d79c40cc43887e"
+  integrity sha512-0szyAo8jMCClkjNK0hknjhmAngUppoRekW6OAezbEYwHXN/VNtsXbfzgYOqjKWxEx3OoAzrT3jLwAF0HdX2MEw==
+
+"@next/swc-linux-x64-musl@12.2.5":
+  version "12.2.5"
+  resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.2.5.tgz#be700d48471baac1ec2e9539396625584a317e95"
+  integrity sha512-zg/Y6oBar1yVnW6Il1I/08/2ukWtOG6s3acdJdEyIdsCzyQi4RLxbbhkD/EGQyhqBvd3QrC6ZXQEXighQUAZ0g==
+
+"@next/swc-win32-arm64-msvc@12.2.5":
+  version "12.2.5"
+  resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.2.5.tgz#a93e958133ad3310373fda33a79aa10af2a0aa97"
+  integrity sha512-3/90DRNSqeeSRMMEhj4gHHQlLhhKg5SCCoYfE3kBjGpE63EfnblYUqsszGGZ9ekpKL/R4/SGB40iCQr8tR5Jiw==
+
+"@next/swc-win32-ia32-msvc@12.2.5":
+  version "12.2.5"
+  resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.2.5.tgz#4f5f7ba0a98ff89a883625d4af0125baed8b2e19"
+  integrity sha512-hGLc0ZRAwnaPL4ulwpp4D2RxmkHQLuI8CFOEEHdzZpS63/hMVzv81g8jzYA0UXbb9pus/iTc3VRbVbAM03SRrw==
+
+"@next/swc-win32-x64-msvc@12.2.5":
+  version "12.2.5"
+  resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.2.5.tgz#20fed129b04a0d3f632c6d0de135345bb623b1e4"
+  integrity sha512-7h5/ahY7NeaO2xygqVrSG/Y8Vs4cdjxIjowTZ5W6CKoTKn7tmnuxlUc2h74x06FKmbhAd9agOjr/AOKyxYYm9Q==
 
 "@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3":
   version "2.1.8-no-fsevents.3"
@@ -1703,34 +2090,34 @@
     "@nodelib/fs.scandir" "2.1.5"
     fastq "^1.6.0"
 
-"@npmcli/arborist@^5.0.0", "@npmcli/arborist@^5.0.2":
-  version "5.0.2"
-  resolved "https://registry.yarnpkg.com/@npmcli/arborist/-/arborist-5.0.2.tgz#6713c1be8f34668bf6032d7ff5789726156dbc99"
-  integrity sha512-QNfOdTCzglgiycfU1HRMWz02R6vP4DEwActG1YG9kyt8qO7EfQdvvVA7U/JTIgD5LrNDm2rQXkx5sGD5MsbiZw==
+"@npmcli/arborist@^5.0.0", "@npmcli/arborist@^5.0.4":
+  version "5.2.0"
+  resolved "https://registry.yarnpkg.com/@npmcli/arborist/-/arborist-5.2.0.tgz#ee40dfe1f81ae1524819ee39c8f3e7022b0d6269"
+  integrity sha512-zWV7scFGL0SmpvfQyIWnMFbU/0YgtMNyvJiJwR98kyjUSntJGWFFR0O600d5W+TrDcTg0GyDbY+HdzGEg+GXLg==
   dependencies:
     "@isaacs/string-locale-compare" "^1.1.0"
     "@npmcli/installed-package-contents" "^1.0.7"
-    "@npmcli/map-workspaces" "^2.0.0"
-    "@npmcli/metavuln-calculator" "^3.0.0"
-    "@npmcli/move-file" "^1.1.0"
+    "@npmcli/map-workspaces" "^2.0.3"
+    "@npmcli/metavuln-calculator" "^3.0.1"
+    "@npmcli/move-file" "^2.0.0"
     "@npmcli/name-from-folder" "^1.0.1"
-    "@npmcli/node-gyp" "^1.0.3"
-    "@npmcli/package-json" "^1.0.1"
+    "@npmcli/node-gyp" "^2.0.0"
+    "@npmcli/package-json" "^2.0.0"
     "@npmcli/run-script" "^3.0.0"
     bin-links "^3.0.0"
-    cacache "^15.0.3"
+    cacache "^16.0.6"
     common-ancestor-path "^1.0.1"
     json-parse-even-better-errors "^2.3.1"
     json-stringify-nice "^1.1.4"
     mkdirp "^1.0.4"
     mkdirp-infer-owner "^2.0.0"
     nopt "^5.0.0"
-    npm-install-checks "^4.0.0"
+    npm-install-checks "^5.0.0"
     npm-package-arg "^9.0.0"
     npm-pick-manifest "^7.0.0"
     npm-registry-fetch "^13.0.0"
-    npmlog "^6.0.1"
-    pacote "^13.0.2"
+    npmlog "^6.0.2"
+    pacote "^13.0.5"
     parse-conflict-json "^2.0.1"
     proc-log "^2.0.0"
     promise-all-reject-late "^1.0.0"
@@ -1738,9 +2125,9 @@
     read-package-json-fast "^2.0.2"
     readdir-scoped-modules "^1.1.0"
     rimraf "^3.0.2"
-    semver "^7.3.5"
-    ssri "^8.0.1"
-    treeverse "^1.0.4"
+    semver "^7.3.7"
+    ssri "^9.0.0"
+    treeverse "^2.0.0"
     walk-up-path "^1.0.0"
 
 "@npmcli/ci-detect@^2.0.0":
@@ -1748,13 +2135,13 @@
   resolved "https://registry.yarnpkg.com/@npmcli/ci-detect/-/ci-detect-2.0.0.tgz#e63c91bcd4185ac1e85720a34fc48e164ece5b89"
   integrity sha512-8yQtQ9ArHh/TzdUDKQwEvwCgpDuhSWTDAbiKMl3854PcT+Dk4UmWaiawuFTLy9n5twzXOBXVflWe+90/ffXQrA==
 
-"@npmcli/config@^4.0.1":
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/@npmcli/config/-/config-4.0.1.tgz#4aa4c184f766cef6f227d0439485e4b940968c04"
-  integrity sha512-pd9lYWFuDARcfXyXJKm/aHy7p9bYDKfUh/7Kg1L+3YYgCmqtqe4exFSnEIDuFO361A8xcKnj2Edev/Cj1cWbgg==
+"@npmcli/config@^4.1.0":
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/@npmcli/config/-/config-4.1.0.tgz#5c92e5ded2a44baf76b94926646329c3b39e79b8"
+  integrity sha512-cPQmIQ2Q0vuOfrenrA3isikdMFMAHgzlXV+EmvZ8f2JeJsU5xTU2bG7ipXECiMvPF9nM+QDnMLuIg8QLw9H4xg==
   dependencies:
-    "@npmcli/map-workspaces" "^2.0.1"
-    ini "^2.0.0"
+    "@npmcli/map-workspaces" "^2.0.2"
+    ini "^3.0.0"
     mkdirp-infer-owner "^2.0.0"
     nopt "^5.0.0"
     proc-log "^2.0.0"
@@ -1762,10 +2149,10 @@
     semver "^7.3.5"
     walk-up-path "^1.0.0"
 
-"@npmcli/disparity-colors@^1.0.1":
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/@npmcli/disparity-colors/-/disparity-colors-1.0.1.tgz#b23c864c9658f9f0318d5aa6d17986619989535c"
-  integrity sha512-kQ1aCTTU45mPXN+pdAaRxlxr3OunkyztjbbxDY/aIcPS5CnCUrx+1+NvA6pTcYR7wmLZe37+Mi5v3nfbwPxq3A==
+"@npmcli/disparity-colors@^2.0.0":
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/@npmcli/disparity-colors/-/disparity-colors-2.0.0.tgz#cb518166ee21573b96241a3613fef70acb2a60ba"
+  integrity sha512-FFXGrIjhvd2qSZ8iS0yDvbI7nbjdyT2VNO7wotosjYZM2p2r8PN3B7Om3M5NO9KqW/OVzfzLB3L0V5Vo5QXC7A==
   dependencies:
     ansi-styles "^4.3.0"
 
@@ -1777,13 +2164,21 @@
     "@gar/promisify" "^1.0.1"
     semver "^7.3.5"
 
+"@npmcli/fs@^2.1.0":
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-2.1.0.tgz#f2a21c28386e299d1a9fae8051d35ad180e33109"
+  integrity sha512-DmfBvNXGaetMxj9LTp8NAN9vEidXURrf5ZTslQzEAi/6GbW+4yjaLFQc6Tue5cpZ9Frlk4OBo/Snf1Bh/S7qTQ==
+  dependencies:
+    "@gar/promisify" "^1.1.3"
+    semver "^7.3.5"
+
 "@npmcli/git@^3.0.0":
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/@npmcli/git/-/git-3.0.0.tgz#466a18980da6b646a8112a7676688ae5347deba3"
-  integrity sha512-xfSBJ+KBMZWWqRHFbEgIaXG/LtELHrQZMJ72Gkb3yWdHysu/7+VGOs8ME0c3td7QNQX57Ggo3kYL6ylcd70/kA==
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/@npmcli/git/-/git-3.0.1.tgz#049b99b1381a2ddf7dc56ba3e91eaf76ca803a8d"
+  integrity sha512-UU85F/T+F1oVn3IsB/L6k9zXIMpXBuUBE25QDH0SsURwT6IOBqkC7M16uqo2vVZIyji3X1K4XH9luip7YekH1A==
   dependencies:
-    "@npmcli/promise-spawn" "^1.3.2"
-    lru-cache "^7.3.1"
+    "@npmcli/promise-spawn" "^3.0.0"
+    lru-cache "^7.4.4"
     mkdirp "^1.0.4"
     npm-pick-manifest "^7.0.0"
     proc-log "^2.0.0"
@@ -1800,27 +2195,27 @@
     npm-bundled "^1.1.1"
     npm-normalize-package-bin "^1.0.1"
 
-"@npmcli/map-workspaces@^2.0.0", "@npmcli/map-workspaces@^2.0.1", "@npmcli/map-workspaces@^2.0.2":
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/@npmcli/map-workspaces/-/map-workspaces-2.0.2.tgz#dfc87ced615afeb98a081da2aa9bba072bf6712d"
-  integrity sha512-ED54EslGsHFWBPN5x8JAOszuWywuoXYSi9E3HQRsgVkWnqsdTBJDSM4IFMRwmmBUbCHAxmP3wGLu1WMm4fhrOw==
+"@npmcli/map-workspaces@^2.0.2", "@npmcli/map-workspaces@^2.0.3":
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/@npmcli/map-workspaces/-/map-workspaces-2.0.3.tgz#2d3c75119ee53246e9aa75bc469a55281cd5f08f"
+  integrity sha512-X6suAun5QyupNM8iHkNPh0AHdRC2rb1W+MTdMvvA/2ixgmqZwlq5cGUBgmKHUHT2LgrkKJMAXbfAoTxOigpK8Q==
   dependencies:
     "@npmcli/name-from-folder" "^1.0.1"
-    glob "^7.2.0"
+    glob "^8.0.1"
     minimatch "^5.0.1"
     read-package-json-fast "^2.0.3"
 
-"@npmcli/metavuln-calculator@^3.0.0":
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/@npmcli/metavuln-calculator/-/metavuln-calculator-3.0.0.tgz#25b47f7dc3c027ec561d8d46ca4fbd732439531d"
-  integrity sha512-tIzAdW3DAvlyuQyYvy7WuDKaJs55LoXFAIyglZTrHsc9DGZWP1YVL7+8WFKqx+lHyHUEkfk02Dc8ie4JWtNO6w==
+"@npmcli/metavuln-calculator@^3.0.1":
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/@npmcli/metavuln-calculator/-/metavuln-calculator-3.1.0.tgz#b1c2f0991c4f2d992b1615a54d4358c05efc3702"
+  integrity sha512-Q5fbQqGDlYqk7kWrbg6E2j/mtqQjZop0ZE6735wYA1tYNHguIDjAuWs+kFb5rJCkLIlXllfapvsyotYKiZOTBA==
   dependencies:
-    cacache "^15.3.0"
+    cacache "^16.0.0"
     json-parse-even-better-errors "^2.3.1"
-    pacote "^13.0.1"
+    pacote "^13.0.3"
     semver "^7.3.5"
 
-"@npmcli/move-file@^1.0.1", "@npmcli/move-file@^1.1.0":
+"@npmcli/move-file@^1.0.1":
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674"
   integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==
@@ -1828,38 +2223,46 @@
     mkdirp "^1.0.4"
     rimraf "^3.0.2"
 
+"@npmcli/move-file@^2.0.0":
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-2.0.0.tgz#417f585016081a0184cef3e38902cd917a9bbd02"
+  integrity sha512-UR6D5f4KEGWJV6BGPH3Qb2EtgH+t+1XQ1Tt85c7qicN6cezzuHPdZwwAxqZr4JLtnQu0LZsTza/5gmNmSl8XLg==
+  dependencies:
+    mkdirp "^1.0.4"
+    rimraf "^3.0.2"
+
 "@npmcli/name-from-folder@^1.0.1":
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/@npmcli/name-from-folder/-/name-from-folder-1.0.1.tgz#77ecd0a4fcb772ba6fe927e2e2e155fbec2e6b1a"
   integrity sha512-qq3oEfcLFwNfEYOQ8HLimRGKlD8WSeGEdtUa7hmzpR8Sa7haL1KVQrvgO6wqMjhWFFVjgtrh1gIxDz+P8sjUaA==
 
-"@npmcli/node-gyp@^1.0.3":
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/@npmcli/node-gyp/-/node-gyp-1.0.3.tgz#a912e637418ffc5f2db375e93b85837691a43a33"
-  integrity sha512-fnkhw+fmX65kiLqk6E3BFLXNC26rUhK90zVwe2yncPliVT/Qos3xjhTLE59Df8KnPlcwIERXKVlU1bXoUQ+liA==
+"@npmcli/node-gyp@^2.0.0":
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/@npmcli/node-gyp/-/node-gyp-2.0.0.tgz#8c20e53e34e9078d18815c1d2dda6f2420d75e35"
+  integrity sha512-doNI35wIe3bBaEgrlPfdJPaCpUR89pJWep4Hq3aRdh6gKazIVWfs0jHttvSSoq47ZXgC7h73kDsUl8AoIQUB+A==
 
-"@npmcli/package-json@^1.0.1":
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/@npmcli/package-json/-/package-json-1.0.1.tgz#1ed42f00febe5293c3502fd0ef785647355f6e89"
-  integrity sha512-y6jnu76E9C23osz8gEMBayZmaZ69vFOIk8vR1FJL/wbEJ54+9aVG9rLTjQKSXfgYZEr50nw1txBBFfBZZe+bYg==
+"@npmcli/package-json@^2.0.0":
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/@npmcli/package-json/-/package-json-2.0.0.tgz#3bbcf4677e21055adbe673d9f08c9f9cde942e4a"
+  integrity sha512-42jnZ6yl16GzjWSH7vtrmWyJDGVa/LXPdpN2rcUWolFjc9ON2N3uz0qdBbQACfmhuJZ2lbKYtmK5qx68ZPLHMA==
   dependencies:
     json-parse-even-better-errors "^2.3.1"
 
-"@npmcli/promise-spawn@^1.2.0", "@npmcli/promise-spawn@^1.3.2":
-  version "1.3.2"
-  resolved "https://registry.yarnpkg.com/@npmcli/promise-spawn/-/promise-spawn-1.3.2.tgz#42d4e56a8e9274fba180dabc0aea6e38f29274f5"
-  integrity sha512-QyAGYo/Fbj4MXeGdJcFzZ+FkDkomfRBrPM+9QYJSg+PxgAUL+LU3FneQk37rKR2/zjqkCV1BLHccX98wRXG3Sg==
+"@npmcli/promise-spawn@^3.0.0":
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/@npmcli/promise-spawn/-/promise-spawn-3.0.0.tgz#53283b5f18f855c6925f23c24e67c911501ef573"
+  integrity sha512-s9SgS+p3a9Eohe68cSI3fi+hpcZUmXq5P7w0kMlAsWVtR7XbK3ptkZqKT2cK1zLDObJ3sR+8P59sJE0w/KTL1g==
   dependencies:
     infer-owner "^1.0.4"
 
 "@npmcli/run-script@^3.0.0", "@npmcli/run-script@^3.0.1":
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-3.0.1.tgz#9d10b46586300074cc9e53ef320130a69567e1ce"
-  integrity sha512-o2fkld5hYwu9sKYzoXTpqEocMnDLaigobaPzLaGB63k/ExmLBTaB+KpfKlpcIePPnuP8RFR+0GDI4KopJCM6Xg==
+  version "3.0.3"
+  resolved "https://registry.yarnpkg.com/@npmcli/run-script/-/run-script-3.0.3.tgz#66afa6e0c4c3484056195f295fa6c1d1a45ddf58"
+  integrity sha512-ZXL6qgC5NjwfZJ2nET+ZSLEz/PJgJ/5CU90C2S66dZY4Jw73DasS4ZCXuy/KHWYP0imjJ4VtA+Gebb5BxxKp9Q==
   dependencies:
-    "@npmcli/node-gyp" "^1.0.3"
-    "@npmcli/promise-spawn" "^1.3.2"
-    node-gyp "^9.0.0"
+    "@npmcli/node-gyp" "^2.0.0"
+    "@npmcli/promise-spawn" "^3.0.0"
+    node-gyp "^8.4.1"
     read-package-json-fast "^2.0.3"
 
 "@octokit/auth-token@^2.4.4":
@@ -1963,96 +2366,101 @@
   dependencies:
     "@octokit/openapi-types" "^11.2.0"
 
-"@react-spring/animated@~9.4.4":
-  version "9.4.4"
-  resolved "https://registry.yarnpkg.com/@react-spring/animated/-/animated-9.4.4.tgz#15e21923e55c06ca2bcea432869b91b2f8b07519"
-  integrity sha512-e9xnuBaUTD+NolKikUmrGWjX8AVCPyj1GcEgjgq9E+0sXKv46UY7cm2EmB6mUDTxWIDVKebARY++xT4nGDraBQ==
-  dependencies:
-    "@react-spring/shared" "~9.4.4"
-    "@react-spring/types" "~9.4.4"
-
-"@react-spring/core@~9.4.4":
-  version "9.4.4"
-  resolved "https://registry.yarnpkg.com/@react-spring/core/-/core-9.4.4.tgz#7730988cec7302ba6e0977cf4c08c30249d95622"
-  integrity sha512-llgb0ljFyjMB0JhWsaFHOi9XFT8n1jBMVs1IFY2ipIBerWIRWrgUmIpakLPHTa4c4jwqTaDSwX90s2a0iN7dxQ==
-  dependencies:
-    "@react-spring/animated" "~9.4.4"
-    "@react-spring/rafz" "~9.4.4"
-    "@react-spring/shared" "~9.4.4"
-    "@react-spring/types" "~9.4.4"
-
-"@react-spring/konva@~9.4.4":
-  version "9.4.4"
-  resolved "https://registry.yarnpkg.com/@react-spring/konva/-/konva-9.4.4.tgz#e65e3b85274e9af36c6037dbafa402d9f01db076"
-  integrity sha512-ZHwsf4l/W5YzK8TwlvGXL9SYiHxxC6iEOAKStRs8WV6VuBvTFgIoGK5RNOTbsRC2N/spNWnN6JViz1PNbgrB+A==
-  dependencies:
-    "@react-spring/animated" "~9.4.4"
-    "@react-spring/core" "~9.4.4"
-    "@react-spring/shared" "~9.4.4"
-    "@react-spring/types" "~9.4.4"
-
-"@react-spring/native@~9.4.4":
-  version "9.4.4"
-  resolved "https://registry.yarnpkg.com/@react-spring/native/-/native-9.4.4.tgz#8581e03d0c4a11f3e5a1fc8cf505c81f9d9a5fcf"
-  integrity sha512-p0/JI59JVkgVjnoLvu+cpEgEkE0B3RDvzT1oNaCAx0ePaGQo4ICAS8PyOgPvN5IHUOy59CBLSMNnFyHV+IgaGQ==
-  dependencies:
-    "@react-spring/animated" "~9.4.4"
-    "@react-spring/core" "~9.4.4"
-    "@react-spring/shared" "~9.4.4"
-    "@react-spring/types" "~9.4.4"
-
-"@react-spring/rafz@~9.4.4":
-  version "9.4.4"
-  resolved "https://registry.yarnpkg.com/@react-spring/rafz/-/rafz-9.4.4.tgz#736c9ed1099baebeea20c357b9700b01b83ea9de"
-  integrity sha512-5ki/sQ06Mdf8AuFstSt5zbNNicRT4LZogiJttDAww1ozhuvemafNWEHxhzcULgCPCDu2s7HsroaISV7+GQWrhw==
-
-"@react-spring/shared@~9.4.4":
-  version "9.4.4"
-  resolved "https://registry.yarnpkg.com/@react-spring/shared/-/shared-9.4.4.tgz#e1ae00a77d170d86d77d9a19dc7015bdddc2d26f"
-  integrity sha512-ySVgScDZlhm/+Iy2smY9i/DDrShArY0j6zjTS/Re1lasKnhq8qigoGiAxe8xMPJNlCaj3uczCqHy3TY9bKRtfQ==
-  dependencies:
-    "@react-spring/rafz" "~9.4.4"
-    "@react-spring/types" "~9.4.4"
-
-"@react-spring/three@~9.4.4":
-  version "9.4.4"
-  resolved "https://registry.yarnpkg.com/@react-spring/three/-/three-9.4.4.tgz#a26de44854e166184ddba57313bfc52efce67368"
-  integrity sha512-z77ohxg8zG0CcZJojzfoJTTrjSbIyefNz2RlId68/4IypnOs1p8kB2Q1p+wX4KyWORpLg8ivsPcjtwBjGwfDtg==
-  dependencies:
-    "@react-spring/animated" "~9.4.4"
-    "@react-spring/core" "~9.4.4"
-    "@react-spring/shared" "~9.4.4"
-    "@react-spring/types" "~9.4.4"
-
-"@react-spring/types@~9.4.4":
-  version "9.4.4"
-  resolved "https://registry.yarnpkg.com/@react-spring/types/-/types-9.4.4.tgz#97c69881788e624d7cc68d4385fdaa9b5fd20642"
-  integrity sha512-KpxKt/D//q/t/6FBcde/RE36LKp8PpWu7kFEMLwpzMGl9RpcexunmYOQJWwmJWtkQjgE1YRr7DzBMryz6La1cQ==
-
-"@react-spring/web@~9.4.4":
-  version "9.4.4"
-  resolved "https://registry.yarnpkg.com/@react-spring/web/-/web-9.4.4.tgz#0d13356e61c1d47e83a36112e19e5db691f3fbe5"
-  integrity sha512-iJmOLdhcuizriUlu/xqBc5y8KaFts+UI+iC+GxyTwBtzxA9czKiSAZW2ESuhG8stafa3jncwjfTQQp84KN36cw==
-  dependencies:
-    "@react-spring/animated" "~9.4.4"
-    "@react-spring/core" "~9.4.4"
-    "@react-spring/shared" "~9.4.4"
-    "@react-spring/types" "~9.4.4"
-
-"@react-spring/zdog@~9.4.4":
-  version "9.4.4"
-  resolved "https://registry.yarnpkg.com/@react-spring/zdog/-/zdog-9.4.4.tgz#e0e19175a9a22d74614dbf3c624513fd35e69f9d"
-  integrity sha512-qmD8zRcodbQKTAFVMdgW2pYIZP1KttDnz2S2JEc7kx8I8F5ljn9czgRl5c4w9HJ0dpO8VTfPq4sKa4tlUL23yg==
-  dependencies:
-    "@react-spring/animated" "~9.4.4"
-    "@react-spring/core" "~9.4.4"
-    "@react-spring/shared" "~9.4.4"
-    "@react-spring/types" "~9.4.4"
-
-"@rushstack/eslint-patch@^1.0.8":
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.0.tgz#7f698254aadf921e48dda8c0a6b304026b8a9323"
-  integrity sha512-JLo+Y592QzIE+q7Dl2pMUtt4q8SKYI5jDrZxrozEQxnGVOyYE+GWK9eLkwTaeN9DDctlaRAQ3TBmzZ1qdLE30A==
+"@popperjs/core@^2.11.5":
+  version "2.11.6"
+  resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45"
+  integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==
+
+"@react-spring/animated@~9.5.2":
+  version "9.5.2"
+  resolved "https://registry.yarnpkg.com/@react-spring/animated/-/animated-9.5.2.tgz#42785b4f369d9715e9ee32c04b78483e7bb85489"
+  integrity sha512-oRlX+MmYLbK8IuUZR7SQUnRjXxJ4PMIZeBkBd1SUWVgVJAHMTfJzPltzm+I6p59qX+qLlklYHfnWaonQKDqLuQ==
+  dependencies:
+    "@react-spring/shared" "~9.5.2"
+    "@react-spring/types" "~9.5.2"
+
+"@react-spring/core@~9.5.2":
+  version "9.5.2"
+  resolved "https://registry.yarnpkg.com/@react-spring/core/-/core-9.5.2.tgz#c8450783ce87a82d3f9ab21e2650e42922398ff7"
+  integrity sha512-UMRtFH6EfebMp/NMDGCUY5+hZFXsg9iT9hzt/iPzJSz2WMXKBjLoFZHJXcmiVOrIhzHmg1O0pFECn1Wp6pZ5Gw==
+  dependencies:
+    "@react-spring/animated" "~9.5.2"
+    "@react-spring/rafz" "~9.5.2"
+    "@react-spring/shared" "~9.5.2"
+    "@react-spring/types" "~9.5.2"
+
+"@react-spring/konva@~9.5.2":
+  version "9.5.2"
+  resolved "https://registry.yarnpkg.com/@react-spring/konva/-/konva-9.5.2.tgz#cbc7c75c55c7946481f86c7392a6656bb5b1bf4a"
+  integrity sha512-FN8LpbGQtm2pllU9mOyYjYwvLtA9EiIPWk2NVuhhX+5lJZrdCWuEY7EyFpK8PtgZXBdVj8bj7eIu1LlTnARW/A==
+  dependencies:
+    "@react-spring/animated" "~9.5.2"
+    "@react-spring/core" "~9.5.2"
+    "@react-spring/shared" "~9.5.2"
+    "@react-spring/types" "~9.5.2"
+
+"@react-spring/native@~9.5.2":
+  version "9.5.2"
+  resolved "https://registry.yarnpkg.com/@react-spring/native/-/native-9.5.2.tgz#218fa228a746cb2f535ea59b317d2e99cdfed02d"
+  integrity sha512-G9BCAKVADLweLR43uyMnTrOnYDb4BboYvqKY+0X1fLs45PNrfbBXnSLot4g+5x3HjblypJgNq7CjHlqZKI980g==
+  dependencies:
+    "@react-spring/animated" "~9.5.2"
+    "@react-spring/core" "~9.5.2"
+    "@react-spring/shared" "~9.5.2"
+    "@react-spring/types" "~9.5.2"
+
+"@react-spring/rafz@~9.5.2":
+  version "9.5.2"
+  resolved "https://registry.yarnpkg.com/@react-spring/rafz/-/rafz-9.5.2.tgz#1264d5df09717cf46d55055da2c55ff84f59073f"
+  integrity sha512-xHSRXKKBI/wDUkZGrspkOm4VlgN6lZi8Tw9Jzibp9QKf3neoof+U2mDNgklvnLaasymtUwAq9o4ZfFvQIVNgPQ==
+
+"@react-spring/shared@~9.5.2":
+  version "9.5.2"
+  resolved "https://registry.yarnpkg.com/@react-spring/shared/-/shared-9.5.2.tgz#e0a252e06daa3927964460fef05d8092e7d78ffc"
+  integrity sha512-/OSf2sjwY4BUnjZL6xMC+H3WxOOhMUCk+yZwgdj40XuyUpk6E6tYyiPeD9Yq5GLsZHodkvE1syVMRVReL4ndAg==
+  dependencies:
+    "@react-spring/rafz" "~9.5.2"
+    "@react-spring/types" "~9.5.2"
+
+"@react-spring/three@~9.5.2":
+  version "9.5.2"
+  resolved "https://registry.yarnpkg.com/@react-spring/three/-/three-9.5.2.tgz#965ff4e729929ebbb9a1f8e84f3f4acb6acec4f9"
+  integrity sha512-3H7Lv8BJZ3dajh0yJA3m9rEbqz5ZNrTCAkhVOeLqgvBlcWU5qVs4luYA1Z7H4vZnLqVtzv+kHAyg3XIpuTOXhQ==
+  dependencies:
+    "@react-spring/animated" "~9.5.2"
+    "@react-spring/core" "~9.5.2"
+    "@react-spring/shared" "~9.5.2"
+    "@react-spring/types" "~9.5.2"
+
+"@react-spring/types@~9.5.2":
+  version "9.5.2"
+  resolved "https://registry.yarnpkg.com/@react-spring/types/-/types-9.5.2.tgz#cce1b03afbafb23edfb9cd8c517cc7462abffb65"
+  integrity sha512-n/wBRSHPqTmEd4BFWY6TeR1o/UY+3ujoqMxLjqy90CcY/ozJzDRuREL3c+pxMeTF2+B7dX33dTPCtFMX51nbxg==
+
+"@react-spring/web@~9.5.2":
+  version "9.5.2"
+  resolved "https://registry.yarnpkg.com/@react-spring/web/-/web-9.5.2.tgz#762ee6b3c8fea40281e1298f5cf1c0515ad6a794"
+  integrity sha512-cusTjbOGTgtbsnpBDjb6Ia+B0lQLE0Fk5rGDog6Sww7hWnLIQ521PMiOBnAWtkntB9eXDUfj7L91nwJviEC0lw==
+  dependencies:
+    "@react-spring/animated" "~9.5.2"
+    "@react-spring/core" "~9.5.2"
+    "@react-spring/shared" "~9.5.2"
+    "@react-spring/types" "~9.5.2"
+
+"@react-spring/zdog@~9.5.2":
+  version "9.5.2"
+  resolved "https://registry.yarnpkg.com/@react-spring/zdog/-/zdog-9.5.2.tgz#a3e451378c23caa4381b5821d3d52c3017740c55"
+  integrity sha512-zUX8RzX8gM51g8NJ5Qaf15KNKQgN3qN/8m5FvqmiqZ5ZGqjoHkbCoMD3o2MICTUN1l+d4eUu9TYrmiO2bgJo/g==
+  dependencies:
+    "@react-spring/animated" "~9.5.2"
+    "@react-spring/core" "~9.5.2"
+    "@react-spring/shared" "~9.5.2"
+    "@react-spring/types" "~9.5.2"
+
+"@rushstack/eslint-patch@^1.1.3":
+  version "1.1.3"
+  resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.3.tgz#6801033be7ff87a6b7cadaf5b337c9f366a3c4b0"
+  integrity sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==
 
 "@selderee/plugin-htmlparser2@^0.6.0":
   version "0.6.0"
@@ -2062,7 +2470,7 @@
     domhandler "^4.2.0"
     selderee "^0.6.0"
 
-"@semantic-release/changelog@^6.0.1":
+"@semantic-release/changelog@6.0.1":
   version "6.0.1"
   resolved "https://registry.yarnpkg.com/@semantic-release/changelog/-/changelog-6.0.1.tgz#8dd0334fd8c7d50cda747d2591e4f18f816b3c9c"
   integrity sha512-FT+tAGdWHr0RCM3EpWegWnvXJ05LQtBkQUaQRIExONoXjVjLuOILNm4DEKNaV+GAQyJjbLRVs57ti//GypH6PA==
@@ -2072,7 +2480,7 @@
     fs-extra "^9.0.0"
     lodash "^4.17.4"
 
-"@semantic-release/commit-analyzer@^9.0.2":
+"@semantic-release/commit-analyzer@9.0.2", "@semantic-release/commit-analyzer@^9.0.2":
   version "9.0.2"
   resolved "https://registry.yarnpkg.com/@semantic-release/commit-analyzer/-/commit-analyzer-9.0.2.tgz#a78e54f9834193b55f1073fa6258eecc9a545e03"
   integrity sha512-E+dr6L+xIHZkX4zNMe6Rnwg4YQrWNXK+rNsvwOPpdFppvZO1olE2fIgWhv89TkQErygevbjsZFSIxp+u6w2e5g==
@@ -2095,7 +2503,7 @@
   resolved "https://registry.yarnpkg.com/@semantic-release/error/-/error-3.0.0.tgz#30a3b97bbb5844d695eb22f9d3aa40f6a92770c2"
   integrity sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw==
 
-"@semantic-release/exec@^6.0.3":
+"@semantic-release/exec@6.0.3":
   version "6.0.3"
   resolved "https://registry.yarnpkg.com/@semantic-release/exec/-/exec-6.0.3.tgz#d212fdf19633bdfb553de6cb6c7f8781933224db"
   integrity sha512-bxAq8vLOw76aV89vxxICecEa8jfaWwYITw6X74zzlO0mc/Bgieqx9kBRz9z96pHectiTAtsCwsQcUyLYWnp3VQ==
@@ -2107,7 +2515,7 @@
     lodash "^4.17.4"
     parse-json "^5.0.0"
 
-"@semantic-release/git@^10.0.1":
+"@semantic-release/git@10.0.1":
   version "10.0.1"
   resolved "https://registry.yarnpkg.com/@semantic-release/git/-/git-10.0.1.tgz#c646e55d67fae623875bf3a06a634dd434904498"
   integrity sha512-eWrx5KguUcU2wUPaO6sfvZI0wPafUKAMNC18aXY4EnNcrZL86dEmpNVnC9uMpGZkmZJ9EfCVJBQx4pV4EMGT1w==
@@ -2122,9 +2530,9 @@
     p-reduce "^2.0.0"
 
 "@semantic-release/github@^8.0.0":
-  version "8.0.2"
-  resolved "https://registry.yarnpkg.com/@semantic-release/github/-/github-8.0.2.tgz#80114a41f6ec8ab6c0d38a436b48ff3f2223ab16"
-  integrity sha512-wIbfhOeuxlYzMTjtSAa2xgr54n7ZuPAS2gadyTWBpUt2PNAPgla7A6XxCXJnaKPgfVF0iFfSk3B+KlVKk6ByVg==
+  version "8.0.4"
+  resolved "https://registry.yarnpkg.com/@semantic-release/github/-/github-8.0.4.tgz#4ea242f6ad10a0474b0fbb09462e10c43518002a"
+  integrity sha512-But4e8oqqP3anZI5tjzZssZc2J6eoUdeeE0s7LVKKwyiAXJiQDWNNvtPOpgG2DsIz4+Exuse7cEQgjGMxwtLmg==
   dependencies:
     "@octokit/rest" "^18.0.0"
     "@semantic-release/error" "^2.2.0"
@@ -2178,161 +2586,155 @@
     lodash "^4.17.4"
     read-pkg-up "^7.0.0"
 
-"@sindresorhus/is@^0.14.0":
-  version "0.14.0"
-  resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
-  integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==
-
 "@sqltools/formatter@^1.2.2":
   version "1.2.3"
   resolved "https://registry.yarnpkg.com/@sqltools/formatter/-/formatter-1.2.3.tgz#1185726610acc37317ddab11c3c7f9066966bd20"
   integrity sha512-O3uyB/JbkAEMZaP3YqyHH7TMnex7tWyCbCI4EfJdOCoN6HIhqdJBWTM6aCCiWQ/5f5wxjgU735QAIpJbjDvmzg==
 
-"@supercharge/request-ip@^1.2.0":
+"@supercharge/request-ip@1.2.0":
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/@supercharge/request-ip/-/request-ip-1.2.0.tgz#b8a8164322e09de3fa9b6f556885795c4841a7d4"
   integrity sha512-wlt6JW69MHqLY2M6Sm/jVyCojNRKq2CBvwH0Hbx24SFhDQQGkgEjeKxVutDxHSyrWixFaOSLXC27euzxijhyMQ==
 
-"@svgr/babel-plugin-add-jsx-attribute@^6.0.0":
-  version "6.0.0"
-  resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.0.0.tgz#bd6d1ff32a31b82b601e73672a789cc41e84fe18"
-  integrity sha512-MdPdhdWLtQsjd29Wa4pABdhWbaRMACdM1h31BY+c6FghTZqNGT7pEYdBoaGeKtdTOBC/XNFQaKVj+r/Ei2ryWA==
-
-"@svgr/babel-plugin-remove-jsx-attribute@^6.0.0":
-  version "6.0.0"
-  resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.0.0.tgz#58654908beebfa069681a83332544b17e5237e89"
-  integrity sha512-aVdtfx9jlaaxc3unA6l+M9YRnKIZjOhQPthLKqmTXC8UVkBLDRGwPKo+r8n3VZN8B34+yVajzPTZ+ptTSuZZCw==
-
-"@svgr/babel-plugin-remove-jsx-empty-expression@^6.0.0":
-  version "6.0.0"
-  resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.0.0.tgz#d06dd6e8a8f603f92f9979bb9990a1f85a4f57ba"
-  integrity sha512-Ccj42ApsePD451AZJJf1QzTD1B/BOU392URJTeXFxSK709i0KUsGtbwyiqsKu7vsYxpTM0IA5clAKDyf9RCZyA==
-
-"@svgr/babel-plugin-replace-jsx-attribute-value@^6.0.0":
-  version "6.0.0"
-  resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.0.0.tgz#0b85837577b02c31c09c758a12932820f5245cee"
-  integrity sha512-88V26WGyt1Sfd1emBYmBJRWMmgarrExpKNVmI9vVozha4kqs6FzQJ/Kp5+EYli1apgX44518/0+t9+NU36lThQ==
-
-"@svgr/babel-plugin-svg-dynamic-title@^6.0.0":
-  version "6.0.0"
-  resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.0.0.tgz#28236ec26f7ab9d486a487d36ae52d58ba15676f"
-  integrity sha512-F7YXNLfGze+xv0KMQxrl2vkNbI9kzT9oDK55/kUuymh1ACyXkMV+VZWX1zEhSTfEKh7VkHVZGmVtHg8eTZ6PRg==
-
-"@svgr/babel-plugin-svg-em-dimensions@^6.0.0":
-  version "6.0.0"
-  resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.0.0.tgz#40267c5dea1b43c4f83a0eb6169e08b43d8bafce"
-  integrity sha512-+rghFXxdIqJNLQK08kwPBD3Z22/0b2tEZ9lKiL/yTfuyj1wW8HUXu4bo/XkogATIYuXSghVQOOCwURXzHGKyZA==
-
-"@svgr/babel-plugin-transform-react-native-svg@^6.0.0":
-  version "6.0.0"
-  resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.0.0.tgz#eb688d0a5f539e34d268d8a516e81f5d7fede7c9"
-  integrity sha512-VaphyHZ+xIKv5v0K0HCzyfAaLhPGJXSk2HkpYfXIOKb7DjLBv0soHDxNv6X0vr2titsxE7klb++u7iOf7TSrFQ==
-
-"@svgr/babel-plugin-transform-svg-component@^6.2.0":
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.2.0.tgz#7ba61d9fc1fb42b0ba1a04e4630019fa7e993c4f"
-  integrity sha512-bhYIpsORb++wpsp91fymbFkf09Z/YEKR0DnFjxvN+8JHeCUD2unnh18jIMKnDJTWtvpTaGYPXELVe4OOzFI0xg==
-
-"@svgr/babel-preset@^6.2.0":
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-6.2.0.tgz#1d3ad8c7664253a4be8e4a0f0e6872f30d8af627"
-  integrity sha512-4WQNY0J71JIaL03DRn0vLiz87JXx0b9dYm2aA8XHlQJQoixMl4r/soYHm8dsaJZ3jWtkCiOYy48dp9izvXhDkQ==
-  dependencies:
-    "@svgr/babel-plugin-add-jsx-attribute" "^6.0.0"
-    "@svgr/babel-plugin-remove-jsx-attribute" "^6.0.0"
-    "@svgr/babel-plugin-remove-jsx-empty-expression" "^6.0.0"
-    "@svgr/babel-plugin-replace-jsx-attribute-value" "^6.0.0"
-    "@svgr/babel-plugin-svg-dynamic-title" "^6.0.0"
-    "@svgr/babel-plugin-svg-em-dimensions" "^6.0.0"
-    "@svgr/babel-plugin-transform-react-native-svg" "^6.0.0"
-    "@svgr/babel-plugin-transform-svg-component" "^6.2.0"
-
-"@svgr/core@^6.2.1":
-  version "6.2.1"
-  resolved "https://registry.yarnpkg.com/@svgr/core/-/core-6.2.1.tgz#195de807a9f27f9e0e0d678e01084b05c54fdf61"
-  integrity sha512-NWufjGI2WUyrg46mKuySfviEJ6IxHUOm/8a3Ph38VCWSp+83HBraCQrpEM3F3dB6LBs5x8OElS8h3C0oOJaJAA==
-  dependencies:
-    "@svgr/plugin-jsx" "^6.2.1"
+"@svgr/babel-plugin-add-jsx-attribute@^6.3.1":
+  version "6.3.1"
+  resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.3.1.tgz#b9a5d84902be75a05ede92e70b338d28ab63fa74"
+  integrity sha512-jDBKArXYO1u0B1dmd2Nf8Oy6aTF5vLDfLoO9Oon/GLkqZ/NiggYWZA+a2HpUMH4ITwNqS3z43k8LWApB8S583w==
+
+"@svgr/babel-plugin-remove-jsx-attribute@^6.3.1":
+  version "6.3.1"
+  resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.3.1.tgz#4877995452efc997b36777abe1fde9705ef78e8b"
+  integrity sha512-dQzyJ4prwjcFd929T43Z8vSYiTlTu8eafV40Z2gO7zy/SV5GT+ogxRJRBIKWomPBOiaVXFg3jY4S5hyEN3IBjQ==
+
+"@svgr/babel-plugin-remove-jsx-empty-expression@^6.3.1":
+  version "6.3.1"
+  resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.3.1.tgz#2d67a0e92904c9be149a5b22d3a3797ce4d7b514"
+  integrity sha512-HBOUc1XwSU67fU26V5Sfb8MQsT0HvUyxru7d0oBJ4rA2s4HW3PhyAPC7fV/mdsSGpAvOdd8Wpvkjsr0fWPUO7A==
+
+"@svgr/babel-plugin-replace-jsx-attribute-value@^6.3.1":
+  version "6.3.1"
+  resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.3.1.tgz#306f5247139c53af70d1778f2719647c747998ee"
+  integrity sha512-C12e6aN4BXAolRrI601gPn5MDFCRHO7C4TM8Kks+rDtl8eEq+NN1sak0eAzJu363x3TmHXdZn7+Efd2nr9I5dA==
+
+"@svgr/babel-plugin-svg-dynamic-title@^6.3.1":
+  version "6.3.1"
+  resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.3.1.tgz#6ce26d34cbc93eb81737ef528528907c292e7aa2"
+  integrity sha512-6NU55Mmh3M5u2CfCCt6TX29/pPneutrkJnnDCHbKZnjukZmmgUAZLtZ2g6ZoSPdarowaQmAiBRgAHqHmG0vuqA==
+
+"@svgr/babel-plugin-svg-em-dimensions@^6.3.1":
+  version "6.3.1"
+  resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.3.1.tgz#5ade2a724b290873c30529d1d8cd23523856287a"
+  integrity sha512-HV1NGHYTTe1vCNKlBgq/gKuCSfaRlKcHIADn7P8w8U3Zvujdw1rmusutghJ1pZJV7pDt3Gt8ws+SVrqHnBO/Qw==
+
+"@svgr/babel-plugin-transform-react-native-svg@^6.3.1":
+  version "6.3.1"
+  resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.3.1.tgz#d654f509d692c3a09dfb475757a44bd9f6ad7ddf"
+  integrity sha512-2wZhSHvTolFNeKDAN/ZmIeSz2O9JSw72XD+o2bNp2QAaWqa8KGpn5Yk5WHso6xqfSAiRzAE+GXlsrBO4UP9LLw==
+
+"@svgr/babel-plugin-transform-svg-component@^6.3.1":
+  version "6.3.1"
+  resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.3.1.tgz#21a285dbffdce9567c437ebf0d081bf9210807e6"
+  integrity sha512-cZ8Tr6ZAWNUFfDeCKn/pGi976iWSkS8ijmEYKosP+6ktdZ7lW9HVLHojyusPw3w0j8PI4VBeWAXAmi/2G7owxw==
+
+"@svgr/babel-preset@^6.3.1":
+  version "6.3.1"
+  resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-6.3.1.tgz#8bd1ead79637d395e9362b01dd37cfd59702e152"
+  integrity sha512-tQtWtzuMMQ3opH7je+MpwfuRA1Hf3cKdSgTtAYwOBDfmhabP7rcTfBi3E7V3MuwJNy/Y02/7/RutvwS1W4Qv9g==
+  dependencies:
+    "@svgr/babel-plugin-add-jsx-attribute" "^6.3.1"
+    "@svgr/babel-plugin-remove-jsx-attribute" "^6.3.1"
+    "@svgr/babel-plugin-remove-jsx-empty-expression" "^6.3.1"
+    "@svgr/babel-plugin-replace-jsx-attribute-value" "^6.3.1"
+    "@svgr/babel-plugin-svg-dynamic-title" "^6.3.1"
+    "@svgr/babel-plugin-svg-em-dimensions" "^6.3.1"
+    "@svgr/babel-plugin-transform-react-native-svg" "^6.3.1"
+    "@svgr/babel-plugin-transform-svg-component" "^6.3.1"
+
+"@svgr/core@^6.3.1":
+  version "6.3.1"
+  resolved "https://registry.yarnpkg.com/@svgr/core/-/core-6.3.1.tgz#752adf49d8d5473b15d76ca741961de093f715bd"
+  integrity sha512-Sm3/7OdXbQreemf9aO25keerZSbnKMpGEfmH90EyYpj1e8wMD4TuwJIb3THDSgRMWk1kYJfSRulELBy4gVgZUA==
+  dependencies:
+    "@svgr/plugin-jsx" "^6.3.1"
     camelcase "^6.2.0"
     cosmiconfig "^7.0.1"
 
-"@svgr/hast-util-to-babel-ast@^6.2.1":
-  version "6.2.1"
-  resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.2.1.tgz#ae065567b74cbe745afae617053adf9a764bea25"
-  integrity sha512-pt7MMkQFDlWJVy9ULJ1h+hZBDGFfSCwlBNW1HkLnVi7jUhyEXUaGYWi1x6bM2IXuAR9l265khBT4Av4lPmaNLQ==
+"@svgr/hast-util-to-babel-ast@^6.3.1":
+  version "6.3.1"
+  resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.3.1.tgz#59614e24d2a4a28010e02089213b3448d905769d"
+  integrity sha512-NgyCbiTQIwe3wHe/VWOUjyxmpUmsrBjdoIxKpXt3Nqc3TN30BpJG22OxBvVzsAh9jqep0w0/h8Ywvdk3D9niNQ==
   dependencies:
-    "@babel/types" "^7.15.6"
-    entities "^3.0.1"
+    "@babel/types" "^7.18.4"
+    entities "^4.3.0"
 
-"@svgr/plugin-jsx@^6.2.1":
-  version "6.2.1"
-  resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-6.2.1.tgz#5668f1d2aa18c2f1bb7a1fc9f682d3f9aed263bd"
-  integrity sha512-u+MpjTsLaKo6r3pHeeSVsh9hmGRag2L7VzApWIaS8imNguqoUwDq/u6U/NDmYs/KAsrmtBjOEaAAPbwNGXXp1g==
+"@svgr/plugin-jsx@^6.3.1":
+  version "6.3.1"
+  resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-6.3.1.tgz#de7b2de824296b836d6b874d498377896e367f50"
+  integrity sha512-r9+0mYG3hD4nNtUgsTXWGYJomv/bNd7kC16zvsM70I/bGeoCi/3lhTmYqeN6ChWX317OtQCSZZbH4wq9WwoXbw==
   dependencies:
-    "@babel/core" "^7.15.5"
-    "@svgr/babel-preset" "^6.2.0"
-    "@svgr/hast-util-to-babel-ast" "^6.2.1"
-    svg-parser "^2.0.2"
+    "@babel/core" "^7.18.5"
+    "@svgr/babel-preset" "^6.3.1"
+    "@svgr/hast-util-to-babel-ast" "^6.3.1"
+    svg-parser "^2.0.4"
 
-"@svgr/plugin-svgo@^6.2.0":
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-6.2.0.tgz#4cbe6a33ccccdcae4e3b63ded64cc1cbe1faf48c"
-  integrity sha512-oDdMQONKOJEbuKwuy4Np6VdV6qoaLLvoY86hjvQEgU82Vx1MSWRyYms6Sl0f+NtqxLI/rDVufATbP/ev996k3Q==
+"@svgr/plugin-svgo@^6.3.1":
+  version "6.3.1"
+  resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-6.3.1.tgz#3c1ff2efaed10e5c5d35a6cae7bacaedc18b5d4a"
+  integrity sha512-yJIjTDKPYqzFVjmsbH5EdIwEsmKxjxdXSGJVLeUgwZOZPAkNQmD1v7LDbOdOKbR44FG8465Du+zWPdbYGnbMbw==
   dependencies:
     cosmiconfig "^7.0.1"
     deepmerge "^4.2.2"
-    svgo "^2.5.0"
-
-"@svgr/webpack@^6.2.1":
-  version "6.2.1"
-  resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-6.2.1.tgz#ef5d51c1b6be4e7537fb9f76b3f2b2e22b63c58d"
-  integrity sha512-h09ngMNd13hnePwgXa+Y5CgOjzlCvfWLHg+MBnydEedAnuLRzUHUJmGS3o2OsrhxTOOqEsPOFt5v/f6C5Qulcw==
-  dependencies:
-    "@babel/core" "^7.15.5"
-    "@babel/plugin-transform-react-constant-elements" "^7.14.5"
-    "@babel/preset-env" "^7.15.6"
-    "@babel/preset-react" "^7.14.5"
-    "@babel/preset-typescript" "^7.15.0"
-    "@svgr/core" "^6.2.1"
-    "@svgr/plugin-jsx" "^6.2.1"
-    "@svgr/plugin-svgo" "^6.2.0"
-
-"@szmarczak/http-timer@^1.1.2":
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421"
-  integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==
-  dependencies:
-    defer-to-connect "^1.0.1"
-
-"@tailwindcss/aspect-ratio@^0.4.0":
+    svgo "^2.8.0"
+
+"@svgr/webpack@6.3.1":
+  version "6.3.1"
+  resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-6.3.1.tgz#001d03236ebb03bf47c0a4b92d5423e05095ebe6"
+  integrity sha512-eODxwIUShLxSMaRjzJtrj9wg89D75JLczvWg9SaB5W+OtVTkiC1vdGd8+t+pf5fTlBOy4RRXAq7x1E3DUl3D0A==
+  dependencies:
+    "@babel/core" "^7.18.5"
+    "@babel/plugin-transform-react-constant-elements" "^7.17.12"
+    "@babel/preset-env" "^7.18.2"
+    "@babel/preset-react" "^7.17.12"
+    "@babel/preset-typescript" "^7.17.12"
+    "@svgr/core" "^6.3.1"
+    "@svgr/plugin-jsx" "^6.3.1"
+    "@svgr/plugin-svgo" "^6.3.1"
+
+"@swc/helpers@0.4.3":
+  version "0.4.3"
+  resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.3.tgz#16593dfc248c53b699d4b5026040f88ddb497012"
+  integrity sha512-6JrF+fdUK2zbGpJIlN7G3v966PQjyx/dPt1T9km2wj+EUBqgrxCk3uX4Kct16MIm9gGxfKRcfax2hVf5jvlTzA==
+  dependencies:
+    tslib "^2.4.0"
+
+"@tailwindcss/aspect-ratio@0.4.0":
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/@tailwindcss/aspect-ratio/-/aspect-ratio-0.4.0.tgz#c635dd7331cbcc1b111cebdc2647dd3493ebdd3e"
   integrity sha512-WJu0I4PpqNPuutpaA9zDUq2JXR+lorZ7PbLcKNLmb6GL9/HLfC7w3CRsMhJF4BbYd/lkY6CfXOvkYpuGnZfkpQ==
 
-"@tailwindcss/forms@^0.5.0":
-  version "0.5.0"
-  resolved "https://registry.yarnpkg.com/@tailwindcss/forms/-/forms-0.5.0.tgz#d4bea2560a10aac642573e72d3b4d62a88960449"
-  integrity sha512-KzWugryEBFkmoaYcBE18rs6gthWCFHHO7cAZm2/hv3hwD67AzwP7udSCa22E7R1+CEJL/FfhYsJWrc0b1aeSzw==
+"@tailwindcss/forms@0.5.2":
+  version "0.5.2"
+  resolved "https://registry.yarnpkg.com/@tailwindcss/forms/-/forms-0.5.2.tgz#4ef45f9916dcb37838cbe7fecdcc4ba7a7c2ab59"
+  integrity sha512-pSrFeJB6Bg1Mrg9CdQW3+hqZXAKsBrSG9MAfFLKy1pVA4Mb4W7C0k7mEhlmS2Dfo/otxrQOET7NJiJ9RrS563w==
   dependencies:
     mini-svg-data-uri "^1.2.3"
 
-"@tailwindcss/typography@^0.5.2":
-  version "0.5.2"
-  resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.2.tgz#24b069dab24d7a2467d01aca0dd432cb4b29f0ee"
-  integrity sha512-coq8DBABRPFcVhVIk6IbKyyHUt7YTEC/C992tatFB+yEx5WGBQrCgsSFjxHUr8AWXphWckadVJbominEduYBqw==
+"@tailwindcss/typography@0.5.4":
+  version "0.5.4"
+  resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.4.tgz#ad8c9e6808bae297bb7826742e4789f2a9f09a48"
+  integrity sha512-QEdg40EmGvE7kKoDei8zr5sf4D1pIayHj4R31bH3lX8x2BtTiR+jNejYPOkhbmy3DXgkMF9jC8xqNiGFAuL9Sg==
   dependencies:
     lodash.castarray "^4.4.0"
     lodash.isplainobject "^4.0.6"
     lodash.merge "^4.6.2"
 
-"@tanem/react-nprogress@^4.0.10":
-  version "4.0.10"
-  resolved "https://registry.yarnpkg.com/@tanem/react-nprogress/-/react-nprogress-4.0.10.tgz#e0a002324ea79ea9b261c02425d73c8ce80090b4"
-  integrity sha512-LGEMgPdXgLZ9e4XsCzFll3AJE5B6CqHMBaBPqYKmKuRVH+blp8ke2psiiOTqEGOlxuI0F0K/2u3N1qg9wI+p5Q==
+"@tanem/react-nprogress@5.0.11":
+  version "5.0.11"
+  resolved "https://registry.yarnpkg.com/@tanem/react-nprogress/-/react-nprogress-5.0.11.tgz#ac05edd3b93c88170b91ce33871e1dc71ca5af22"
+  integrity sha512-zLOsKXzTjXkCEgicC+wHxZiXl5/ONOQIFoZ1HBmHmNbrnMStg4/T6gmyBLRDu4lQ5cS00F1ElRwLSODd0xmNMg==
   dependencies:
-    "@babel/runtime" "^7.17.2"
+    "@babel/runtime" "^7.18.9"
     hoist-non-react-statics "^3.3.2"
-    prop-types "^15.8.1"
 
 "@tootallnate/once@1":
   version "1.1.2"
@@ -2370,9 +2772,9 @@
   integrity sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==
 
 "@types/babel__core@^7.1.7":
-  version "7.1.18"
-  resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.18.tgz#1a29abcc411a9c05e2094c98f9a1b7da6cdf49f8"
-  integrity sha512-S7unDjm/C7z2A2R9NzfKCK1I+BAALDtxEmsJBwlB3EzNfb929ykjL++1CK9LO++EIp2fQrC8O+BwjKvz6UeDyQ==
+  version "7.1.19"
+  resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.19.tgz#7b497495b7d1b4812bdb9d02804d0576f43ee460"
+  integrity sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==
   dependencies:
     "@babel/parser" "^7.1.0"
     "@babel/types" "^7.0.0"
@@ -2396,13 +2798,13 @@
     "@babel/types" "^7.0.0"
 
 "@types/babel__traverse@*":
-  version "7.14.2"
-  resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.14.2.tgz#ffcd470bbb3f8bf30481678fb5502278ca833a43"
-  integrity sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA==
+  version "7.17.1"
+  resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.17.1.tgz#1a0e73e8c28c7e832656db372b779bfd2ef37314"
+  integrity sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==
   dependencies:
     "@babel/types" "^7.3.0"
 
-"@types/bcrypt@^5.0.0":
+"@types/bcrypt@5.0.0":
   version "5.0.0"
   resolved "https://registry.yarnpkg.com/@types/bcrypt/-/bcrypt-5.0.0.tgz#a835afa2882d165aff5690893db314eaa98b9f20"
   integrity sha512-agtcFKaruL8TmcvqbndlqHPSJgsolhf/qPWchFlgnW1gECTN/nKbFcoFnvKAQRFfKbh+BO6A3SWdJu9t+xF3Lw==
@@ -2424,19 +2826,19 @@
   dependencies:
     "@types/node" "*"
 
-"@types/cookie-parser@^1.4.2":
-  version "1.4.2"
-  resolved "https://registry.yarnpkg.com/@types/cookie-parser/-/cookie-parser-1.4.2.tgz#e4d5c5ffda82b80672a88a4281aaceefb1bd9df5"
-  integrity sha512-uwcY8m6SDQqciHsqcKDGbo10GdasYsPCYkH3hVegj9qAah6pX5HivOnOuI3WYmyQMnOATV39zv/Ybs0bC/6iVg==
+"@types/cookie-parser@1.4.3":
+  version "1.4.3"
+  resolved "https://registry.yarnpkg.com/@types/cookie-parser/-/cookie-parser-1.4.3.tgz#3a01df117c5705cf89a84c876b50c5a1fd427a21"
+  integrity sha512-CqSKwFwefj4PzZ5n/iwad/bow2hTCh0FlNAeWLtQM3JA/NX/iYagIpWG2cf1bQKQ2c9gU2log5VUCrn7LDOs0w==
   dependencies:
     "@types/express" "*"
 
-"@types/country-flag-icons@^1.2.0":
+"@types/country-flag-icons@1.2.0":
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/@types/country-flag-icons/-/country-flag-icons-1.2.0.tgz#5d13276405a5701ca29bbd7f1026f45c0d2962be"
   integrity sha512-96aveJfAw9iSfBxAD8DCgFYjMFmLIGa+vBvg3cKiHjX+o4Szz5HHv2DSbEVm9a4kLixsYkioGB4SnJs17Zypzw==
 
-"@types/csurf@^1.11.2":
+"@types/csurf@1.11.2":
   version "1.11.2"
   resolved "https://registry.yarnpkg.com/@types/csurf/-/csurf-1.11.2.tgz#c1cba70f7af653c508b28db047e6c1be72411345"
   integrity sha512-9bc98EnwmC1S0aSJiA8rWwXtgXtXHHOQOsGHptImxFgqm6CeH+mIOunHRg6+/eg2tlmDMX3tY7XrWxo2M/nUNQ==
@@ -2455,7 +2857,7 @@
   dependencies:
     "@types/ms" "*"
 
-"@types/email-templates@^8.0.4":
+"@types/email-templates@8.0.4":
   version "8.0.4"
   resolved "https://registry.yarnpkg.com/@types/email-templates/-/email-templates-8.0.4.tgz#f4043273d2e3e503943d0ba0326c550c01ee3a3a"
   integrity sha512-HYvVoyG8qS6PrimZZOS4wMrtQ9MelKEl0sOpi4zVpz2Ds74v+UvWckIFz3NyGyTwAR1okMbwJkApgR2GL/ALjg==
@@ -2464,10 +2866,10 @@
     "@types/nodemailer" "*"
     juice "^7.0.0"
 
-"@types/eslint@8":
-  version "8.4.1"
-  resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.1.tgz#c48251553e8759db9e656de3efc846954ac32304"
-  integrity sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==
+"@types/eslint@7 || 8":
+  version "8.4.2"
+  resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.2.tgz#48f2ac58ab9c631cb68845c3d956b28f79fad575"
+  integrity sha512-Z1nseZON+GEnFjJc04sv4NSALGjhFwy6K0HXt7qsn5ArfAKtb63dXNJHf+1YW6IpOIYRBGUbu3GwJdj8DGnCjA==
   dependencies:
     "@types/estree" "*"
     "@types/json-schema" "*"
@@ -2486,14 +2888,14 @@
     "@types/qs" "*"
     "@types/range-parser" "*"
 
-"@types/express-session@^1.15.5", "@types/express-session@^1.17.4":
+"@types/express-session@1.17.4", "@types/express-session@^1.15.5":
   version "1.17.4"
   resolved "https://registry.yarnpkg.com/@types/express-session/-/express-session-1.17.4.tgz#97a30a35e853a61bdd26e727453b8ed314d6166b"
   integrity sha512-7cNlSI8+oOBUHTfPXMwDxF/Lchx5aJ3ho7+p9jJZYVg9dVDJFh3qdMXmJtRsysnvS+C6x46k9DRYmrmCkE+MVg==
   dependencies:
     "@types/express" "*"
 
-"@types/express@*", "@types/express@^4.17.13":
+"@types/express@*", "@types/express@4.17.13":
   version "4.17.13"
   resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034"
   integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==
@@ -2531,19 +2933,29 @@
   integrity sha512-54YF2fGmN4g62/w+T85uQ8n0FyBhMY5cjKZ1imsbIh4Pgbeno1mAaQktC/pv/+C2ToUYkTZis9ADgn9GRRz9nQ==
 
 "@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.6", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
-  version "7.0.9"
-  resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d"
-  integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==
+  version "7.0.11"
+  resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
+  integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
+
+"@types/json-stable-stringify@^1.0.32":
+  version "1.0.34"
+  resolved "https://registry.yarnpkg.com/@types/json-stable-stringify/-/json-stable-stringify-1.0.34.tgz#c0fb25e4d957e0ee2e497c1f553d7f8bb668fd75"
+  integrity sha512-s2cfwagOQAS8o06TcwKfr9Wx11dNGbH2E9vJz1cqV+a/LOyhWNLUNd6JSRYNzvB4d29UuJX2M0Dj9vE1T8fRXw==
 
 "@types/json5@^0.0.29":
   version "0.0.29"
   resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
-  integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4=
+  integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
 
-"@types/lodash@^4.14.175", "@types/lodash@^4.14.179":
-  version "4.14.179"
-  resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.179.tgz#490ec3288088c91295780237d2497a3aa9dfb5c5"
-  integrity sha512-uwc1x90yCKqGcIOAT6DwOSuxnrAbpkdPsUOZtwrXb4D/6wZs+6qG7QnIawDuZWg0sWpxl+ltIKCaLoMlna678w==
+"@types/lodash@4.14.183":
+  version "4.14.183"
+  resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.183.tgz#1173e843e858cff5b997c234df2789a4a54c2374"
+  integrity sha512-UXavyuxzXKMqJPEpFPri6Ku5F9af6ZJXUneHhvQJxavrEjuHkFp2YnDWHcxJiG7hk8ZkWqjcyNeW1s/smZv5cw==
+
+"@types/lodash@^4.14.175":
+  version "4.14.182"
+  resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.182.tgz#05301a4d5e62963227eaafe0ce04dd77c54ea5c2"
+  integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q==
 
 "@types/mdast@^3.0.0":
   version "3.0.10"
@@ -2584,25 +2996,37 @@
   dependencies:
     "@types/express" "*"
 
-"@types/node-schedule@^1.3.2":
-  version "1.3.2"
-  resolved "https://registry.yarnpkg.com/@types/node-schedule/-/node-schedule-1.3.2.tgz#cc7e32c6795cbadc8de03d0e1f86311727375423"
-  integrity sha512-Y0CqdAr+lCpArT8CJJjJq4U2v8Bb5e7ru2nV/NhDdaptCMCRdOL3Y7tAhen39HluQMaIKWvPbDuiFBUQpg7Srw==
+"@types/node-schedule@2.1.0":
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/@types/node-schedule/-/node-schedule-2.1.0.tgz#60375640c0509bab963573def9d1f417f438c290"
+  integrity sha512-NiTwl8YN3v/1YCKrDFSmCTkVxFDylueEqsOFdgF+vPsm+AlyJKGAo5yzX1FiOxPsZiN6/r8gJitYx2EaSuBmmg==
   dependencies:
     "@types/node" "*"
 
-"@types/node@*", "@types/node@14 || 16 || 17", "@types/node@>=12", "@types/node@^17.0.21":
-  version "17.0.21"
-  resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.21.tgz#864b987c0c68d07b4345845c3e63b75edd143644"
-  integrity sha512-DBZCJbhII3r90XbQxI8Y9IjjiiOGlZ0Hr32omXIZvwwZ7p4DMMXGrKXVyPfuoBOri9XNtL0UK69jYIBIsRX3QQ==
+"@types/node@*", "@types/node@14 || 16 || 17", "@types/node@17.0.36", "@types/node@>=12":
+  version "17.0.36"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.36.tgz#c0d5f2fe76b47b63e0e0efc3d2049a9970d68794"
+  integrity sha512-V3orv+ggDsWVHP99K3JlwtH20R7J4IhI1Kksgc+64q5VxgfRkQG8Ws3MFm/FZOKDYGy9feGFlZ70/HpCNe9QaA==
+
+"@types/node@^14.14.31":
+  version "14.18.23"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.23.tgz#70f5f20b0b1b38f696848c1d3647bb95694e615e"
+  integrity sha512-MhbCWN18R4GhO8ewQWAFK4TGQdBpXWByukz7cWyJmXhvRuCIaM/oWytGPqVmDzgEnnaIc9ss6HbU5mUi+vyZPA==
 
-"@types/nodemailer@*", "@types/nodemailer@^6.4.4":
+"@types/nodemailer@*":
   version "6.4.4"
   resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.4.tgz#c265f7e7a51df587597b3a49a023acaf0c741f4b"
   integrity sha512-Ksw4t7iliXeYGvIQcSIgWQ5BLuC/mljIEbjf615svhZL10PE9t+ei8O9gDaD3FPCasUJn9KTLwz2JFJyiiyuqw==
   dependencies:
     "@types/node" "*"
 
+"@types/nodemailer@6.4.5":
+  version "6.4.5"
+  resolved "https://registry.yarnpkg.com/@types/nodemailer/-/nodemailer-6.4.5.tgz#09011ac73259245475d1688e4ba101860567dc39"
+  integrity sha512-zuP3nBRQHI6M2PkXnGGy1Ww4VB+MyYHGgnfV2T+JR9KLkeWqPJuyVUgLpKXuFnA/b7pZaIDFh2sV4759B7jK1g==
+  dependencies:
+    "@types/node" "*"
+
 "@types/normalize-package-data@^2.4.0":
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz#d3357479a0fdfdd5907fe67e17e0a85c906e1301"
@@ -2613,10 +3037,20 @@
   resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
   integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
 
-"@types/prop-types@*":
-  version "15.7.4"
-  resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11"
-  integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ==
+"@types/picomatch@^2.3.0":
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/@types/picomatch/-/picomatch-2.3.0.tgz#75db5e75a713c5a83d5b76780c3da84a82806003"
+  integrity sha512-O397rnSS9iQI4OirieAtsDqvCj4+3eY1J+EPdNTKuHuRWIfUoGyzX294o8C4KJYaLqgSrd2o60c5EqCU8Zv02g==
+
+"@types/prop-types@*", "@types/prop-types@^15.0.0":
+  version "15.7.5"
+  resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
+  integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
+
+"@types/pulltorefreshjs@0.1.5":
+  version "0.1.5"
+  resolved "https://registry.yarnpkg.com/@types/pulltorefreshjs/-/pulltorefreshjs-0.1.5.tgz#f15c9dbc91b8fdd8135093d81ece9e9d4d2324d7"
+  integrity sha512-/VRTgBettvBg1KI8mGnA9oeWs359tTXQ7qsxLuXnksL88jvK6ZNMStG5T9x9vUO9O7jLsgREB0cElz/BWFfdew==
 
 "@types/qs@*":
   version "6.9.7"
@@ -2628,33 +3062,40 @@
   resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
   integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
 
-"@types/react-dom@^17.0.13":
-  version "17.0.13"
-  resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-17.0.13.tgz#a3323b974ee4280070982b3112351bb1952a7809"
-  integrity sha512-wEP+B8hzvy6ORDv1QBhcQia4j6ea4SFIBttHYpXKPFZRviBvknq0FRh3VrIxeXUmsPkwuXVZrVGG7KUVONmXCQ==
+"@types/react-dom@18.0.6":
+  version "18.0.6"
+  resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.6.tgz#36652900024842b74607a17786b6662dd1e103a1"
+  integrity sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==
   dependencies:
     "@types/react" "*"
 
-"@types/react-transition-group@^4.4.0", "@types/react-transition-group@^4.4.4":
+"@types/react-transition-group@4.4.5":
+  version "4.4.5"
+  resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.5.tgz#aae20dcf773c5aa275d5b9f7cdbca638abc5e416"
+  integrity sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==
+  dependencies:
+    "@types/react" "*"
+
+"@types/react-transition-group@^4.4.0":
   version "4.4.4"
   resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.4.tgz#acd4cceaa2be6b757db61ed7b432e103242d163e"
   integrity sha512-7gAPz7anVK5xzbeQW9wFBDg7G++aPLAFY0QaSMOou9rJZpbuI58WAuJrgu+qR92l61grlnCUe7AFX8KGahAgug==
   dependencies:
     "@types/react" "*"
 
-"@types/react@*", "@types/react@16 || 17", "@types/react@^17.0.40":
-  version "17.0.40"
-  resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.40.tgz#dc010cee6254d5239a138083f3799a16638e6bad"
-  integrity sha512-UrXhD/JyLH+W70nNSufXqMZNuUD2cXHu6UjCllC6pmOQgBX4SGXOH8fjRka0O0Ee0HrFxapDD8Bwn81Kmiz6jQ==
+"@types/react@*", "@types/react@16 || 17 || 18", "@types/react@18.0.17":
+  version "18.0.17"
+  resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.17.tgz#4583d9c322d67efe4b39a935d223edcc7050ccf4"
+  integrity sha512-38ETy4tL+rn4uQQi7mB81G7V1g0u2ryquNmsVIOKUAEIDK+3CUjZ6rSRpdvS99dNBnkLFL83qfmtLacGOTIhwQ==
   dependencies:
     "@types/prop-types" "*"
     "@types/scheduler" "*"
     csstype "^3.0.2"
 
-"@types/retry@^0.12.0":
-  version "0.12.1"
-  resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065"
-  integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g==
+"@types/retry@0.12.0":
+  version "0.12.0"
+  resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
+  integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==
 
 "@types/scheduler@*":
   version "0.16.2"
@@ -2668,15 +3109,15 @@
   dependencies:
     schema-utils "*"
 
-"@types/secure-random-password@^0.2.1":
+"@types/secure-random-password@0.2.1":
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/@types/secure-random-password/-/secure-random-password-0.2.1.tgz#c01a96d5c2667c3fa896533207bceb157e3b87bc"
   integrity sha512-tpG5oVF+NpIS9UJ9ttXAokafyhE/MCZBg65D345qu3gOM4YoJ/mFNVzUDUNBfb1hIi598bNOzvY04BbfS7VKwA==
 
-"@types/semver@^7.3.9":
-  version "7.3.9"
-  resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.9.tgz#152c6c20a7688c30b967ec1841d31ace569863fc"
-  integrity sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ==
+"@types/semver@7.3.12":
+  version "7.3.12"
+  resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.12.tgz#920447fdd78d76b19de0438b7f60df3c4a80bf1c"
+  integrity sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A==
 
 "@types/serve-static@*":
   version "1.13.10"
@@ -2686,7 +3127,17 @@
     "@types/mime" "^1"
     "@types/node" "*"
 
-"@types/swagger-ui-express@^4.1.3":
+"@types/sinonjs__fake-timers@8.1.1":
+  version "8.1.1"
+  resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz#b49c2c70150141a15e0fa7e79cf1f92a72934ce3"
+  integrity sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==
+
+"@types/sizzle@^2.3.2":
+  version "2.3.3"
+  resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.3.tgz#ff5e2f1902969d305225a047c8a0fd5c915cebef"
+  integrity sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==
+
+"@types/swagger-ui-express@4.1.3":
   version "4.1.3"
   resolved "https://registry.yarnpkg.com/@types/swagger-ui-express/-/swagger-ui-express-4.1.3.tgz#7adbbbf5343b45869debef1e9ff39c9ba73e380f"
   integrity sha512-jqCjGU/tGEaqIplPy3WyQg+Nrp6y80DCFnDEAvVKWkJyv0VivSSDCChkppHRHAablvInZe6pijDFMnavtN0vqA==
@@ -2699,114 +3150,160 @@
   resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d"
   integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==
 
-"@types/web-push@^3.3.2":
+"@types/web-push@3.3.2":
   version "3.3.2"
   resolved "https://registry.yarnpkg.com/@types/web-push/-/web-push-3.3.2.tgz#8c32434147c0396415862e86405c9edc9c50fc15"
   integrity sha512-JxWGVL/m7mWTIg4mRYO+A6s0jPmBkr4iJr39DqJpRJAc+jrPiEe1/asmkwerzRon8ZZDxaZJpsxpv0Z18Wo9gw==
   dependencies:
     "@types/node" "*"
 
-"@types/xml2js@^0.4.9":
-  version "0.4.9"
-  resolved "https://registry.yarnpkg.com/@types/xml2js/-/xml2js-0.4.9.tgz#a38267d8c2fe121c96922b12ee3bd89a58a6e20e"
-  integrity sha512-CHiCKIihl1pychwR2RNX5mAYmJDACgFVCMT5OArMaO3erzwXVcBqPcusr+Vl8yeeXukxZqtF8mZioqX+mpjjdw==
+"@types/xml2js@0.4.11":
+  version "0.4.11"
+  resolved "https://registry.yarnpkg.com/@types/xml2js/-/xml2js-0.4.11.tgz#bf46a84ecc12c41159a7bd9cf51ae84129af0e79"
+  integrity sha512-JdigeAKmCyoJUiQljjr7tQG3if9NkqGUgwEUqBvV0N7LM4HyQk7UXCnusRa1lnvXAEYJ8mw8GtZWioagNztOwA==
   dependencies:
     "@types/node" "*"
 
-"@types/yamljs@^0.2.31":
+"@types/yamljs@0.2.31":
   version "0.2.31"
   resolved "https://registry.yarnpkg.com/@types/yamljs/-/yamljs-0.2.31.tgz#b1a620b115c96db7b3bfdf0cf54aee0c57139245"
   integrity sha512-QcJ5ZczaXAqbVD3o8mw/mEBhRvO5UAdTtbvgwL/OgoWubvNBh6/MxLBAigtcgIFaq3shon9m3POIxQaLQt4fxQ==
 
-"@types/yup@^0.29.13":
-  version "0.29.13"
-  resolved "https://registry.yarnpkg.com/@types/yup/-/yup-0.29.13.tgz#21b137ba60841307a3c8a1050d3bf4e63ad561e9"
-  integrity sha512-qRyuv+P/1t1JK1rA+elmK1MmCL1BapEzKKfbEhDBV/LMMse4lmhZ/XbgETI39JveDJRpLjmToOI6uFtMW/WR2g==
-
-"@types/zen-observable@0.8.3":
-  version "0.8.3"
-  resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.3.tgz#781d360c282436494b32fe7d9f7f8e64b3118aa3"
-  integrity sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==
-
-"@typescript-eslint/eslint-plugin@^5.14.0":
-  version "5.14.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.14.0.tgz#5119b67152356231a0e24b998035288a9cd21335"
-  integrity sha512-ir0wYI4FfFUDfLcuwKzIH7sMVA+db7WYen47iRSaCGl+HMAZI9fpBwfDo45ZALD3A45ZGyHWDNLhbg8tZrMX4w==
-  dependencies:
-    "@typescript-eslint/scope-manager" "5.14.0"
-    "@typescript-eslint/type-utils" "5.14.0"
-    "@typescript-eslint/utils" "5.14.0"
-    debug "^4.3.2"
-    functional-red-black-tree "^1.0.1"
-    ignore "^5.1.8"
-    regexpp "^3.2.0"
-    semver "^7.3.5"
-    tsutils "^3.21.0"
-
-"@typescript-eslint/parser@^5.0.0", "@typescript-eslint/parser@^5.14.0":
-  version "5.14.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.14.0.tgz#7c79f898aa3cff0ceee6f1d34eeed0f034fb9ef3"
-  integrity sha512-aHJN8/FuIy1Zvqk4U/gcO/fxeMKyoSv/rS46UXMXOJKVsLQ+iYPuXNbpbH7cBLcpSbmyyFbwrniLx5+kutu1pw==
+"@types/yauzl@^2.9.1":
+  version "2.10.0"
+  resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.0.tgz#b3248295276cf8c6f153ebe6a9aba0c988cb2599"
+  integrity sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==
   dependencies:
-    "@typescript-eslint/scope-manager" "5.14.0"
-    "@typescript-eslint/types" "5.14.0"
-    "@typescript-eslint/typescript-estree" "5.14.0"
-    debug "^4.3.2"
+    "@types/node" "*"
 
-"@typescript-eslint/scope-manager@5.14.0":
-  version "5.14.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.14.0.tgz#ea518962b42db8ed0a55152ea959c218cb53ca7b"
-  integrity sha512-LazdcMlGnv+xUc5R4qIlqH0OWARyl2kaP8pVCS39qSL3Pd1F7mI10DbdXeARcE62sVQE4fHNvEqMWsypWO+yEw==
-  dependencies:
-    "@typescript-eslint/types" "5.14.0"
-    "@typescript-eslint/visitor-keys" "5.14.0"
+"@types/yup@0.29.14":
+  version "0.29.14"
+  resolved "https://registry.yarnpkg.com/@types/yup/-/yup-0.29.14.tgz#754f1dccedcc66fc2bbe290c27f5323b407ceb00"
+  integrity sha512-Ynb/CjHhE/Xp/4bhHmQC4U1Ox+I2OpfRYF3dnNgQqn1cHa6LK3H1wJMNPT02tSVZA6FYuXE2ITORfbnb6zBCSA==
 
-"@typescript-eslint/type-utils@5.14.0":
-  version "5.14.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.14.0.tgz#711f08105860b12988454e91df433567205a8f0b"
-  integrity sha512-d4PTJxsqaUpv8iERTDSQBKUCV7Q5yyXjqXUl3XF7Sd9ogNLuKLkxz82qxokqQ4jXdTPZudWpmNtr/JjbbvUixw==
+"@typescript-eslint/eslint-plugin@5.33.1":
+  version "5.33.1"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.33.1.tgz#c0a480d05211660221eda963cc844732fe9b1714"
+  integrity sha512-S1iZIxrTvKkU3+m63YUOxYPKaP+yWDQrdhxTglVDVEVBf+aCSw85+BmJnyUaQQsk5TXFG/LpBu9fa+LrAQ91fQ==
   dependencies:
-    "@typescript-eslint/utils" "5.14.0"
-    debug "^4.3.2"
+    "@typescript-eslint/scope-manager" "5.33.1"
+    "@typescript-eslint/type-utils" "5.33.1"
+    "@typescript-eslint/utils" "5.33.1"
+    debug "^4.3.4"
+    functional-red-black-tree "^1.0.1"
+    ignore "^5.2.0"
+    regexpp "^3.2.0"
+    semver "^7.3.7"
+    tsutils "^3.21.0"
+
+"@typescript-eslint/parser@5.33.1":
+  version "5.33.1"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.33.1.tgz#e4b253105b4d2a4362cfaa4e184e2d226c440ff3"
+  integrity sha512-IgLLtW7FOzoDlmaMoXdxG8HOCByTBXrB1V2ZQYSEV1ggMmJfAkMWTwUjjzagS6OkfpySyhKFkBw7A9jYmcHpZA==
+  dependencies:
+    "@typescript-eslint/scope-manager" "5.33.1"
+    "@typescript-eslint/types" "5.33.1"
+    "@typescript-eslint/typescript-estree" "5.33.1"
+    debug "^4.3.4"
+
+"@typescript-eslint/parser@^5.21.0":
+  version "5.27.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.27.0.tgz#62bb091ed5cf9c7e126e80021bb563dcf36b6b12"
+  integrity sha512-8oGjQF46c52l7fMiPPvX4It3u3V3JipssqDfHQ2hcR0AeR8Zge+OYyKUCm5b70X72N1qXt0qgHenwN6Gc2SXZA==
+  dependencies:
+    "@typescript-eslint/scope-manager" "5.27.0"
+    "@typescript-eslint/types" "5.27.0"
+    "@typescript-eslint/typescript-estree" "5.27.0"
+    debug "^4.3.4"
+
+"@typescript-eslint/scope-manager@5.27.0":
+  version "5.27.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.27.0.tgz#a272178f613050ed62f51f69aae1e19e870a8bbb"
+  integrity sha512-VnykheBQ/sHd1Vt0LJ1JLrMH1GzHO+SzX6VTXuStISIsvRiurue/eRkTqSrG0CexHQgKG8shyJfR4o5VYioB9g==
+  dependencies:
+    "@typescript-eslint/types" "5.27.0"
+    "@typescript-eslint/visitor-keys" "5.27.0"
+
+"@typescript-eslint/scope-manager@5.33.1":
+  version "5.33.1"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.33.1.tgz#8d31553e1b874210018ca069b3d192c6d23bc493"
+  integrity sha512-8ibcZSqy4c5m69QpzJn8XQq9NnqAToC8OdH/W6IXPXv83vRyEDPYLdjAlUx8h/rbusq6MkW4YdQzURGOqsn3CA==
+  dependencies:
+    "@typescript-eslint/types" "5.33.1"
+    "@typescript-eslint/visitor-keys" "5.33.1"
+
+"@typescript-eslint/type-utils@5.33.1":
+  version "5.33.1"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.33.1.tgz#1a14e94650a0ae39f6e3b77478baff002cec4367"
+  integrity sha512-X3pGsJsD8OiqhNa5fim41YtlnyiWMF/eKsEZGsHID2HcDqeSC5yr/uLOeph8rNF2/utwuI0IQoAK3fpoxcLl2g==
+  dependencies:
+    "@typescript-eslint/utils" "5.33.1"
+    debug "^4.3.4"
     tsutils "^3.21.0"
 
-"@typescript-eslint/types@5.14.0":
-  version "5.14.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.14.0.tgz#96317cf116cea4befabc0defef371a1013f8ab11"
-  integrity sha512-BR6Y9eE9360LNnW3eEUqAg6HxS9Q35kSIs4rp4vNHRdfg0s+/PgHgskvu5DFTM7G5VKAVjuyaN476LCPrdA7Mw==
+"@typescript-eslint/types@5.27.0":
+  version "5.27.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.27.0.tgz#c3f44b9dda6177a9554f94a74745ca495ba9c001"
+  integrity sha512-lY6C7oGm9a/GWhmUDOs3xAVRz4ty/XKlQ2fOLr8GAIryGn0+UBOoJDWyHer3UgrHkenorwvBnphhP+zPmzmw0A==
+
+"@typescript-eslint/types@5.33.1":
+  version "5.33.1"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.33.1.tgz#3faef41793d527a519e19ab2747c12d6f3741ff7"
+  integrity sha512-7K6MoQPQh6WVEkMrMW5QOA5FO+BOwzHSNd0j3+BlBwd6vtzfZceJ8xJ7Um2XDi/O3umS8/qDX6jdy2i7CijkwQ==
+
+"@typescript-eslint/typescript-estree@5.27.0", "@typescript-eslint/typescript-estree@^5.9.1":
+  version "5.27.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.27.0.tgz#7965f5b553c634c5354a47dcce0b40b94611e995"
+  integrity sha512-QywPMFvgZ+MHSLRofLI7BDL+UczFFHyj0vF5ibeChDAJgdTV8k4xgEwF0geFhVlPc1p8r70eYewzpo6ps+9LJQ==
+  dependencies:
+    "@typescript-eslint/types" "5.27.0"
+    "@typescript-eslint/visitor-keys" "5.27.0"
+    debug "^4.3.4"
+    globby "^11.1.0"
+    is-glob "^4.0.3"
+    semver "^7.3.7"
+    tsutils "^3.21.0"
 
-"@typescript-eslint/typescript-estree@5.14.0", "@typescript-eslint/typescript-estree@^5.9.1":
-  version "5.14.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.14.0.tgz#78b7f7385d5b6f2748aacea5c9b7f6ae62058314"
-  integrity sha512-QGnxvROrCVtLQ1724GLTHBTR0lZVu13izOp9njRvMkCBgWX26PKvmMP8k82nmXBRD3DQcFFq2oj3cKDwr0FaUA==
+"@typescript-eslint/typescript-estree@5.33.1":
+  version "5.33.1"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.33.1.tgz#a573bd360790afdcba80844e962d8b2031984f34"
+  integrity sha512-JOAzJ4pJ+tHzA2pgsWQi4804XisPHOtbvwUyqsuuq8+y5B5GMZs7lI1xDWs6V2d7gE/Ez5bTGojSK12+IIPtXA==
   dependencies:
-    "@typescript-eslint/types" "5.14.0"
-    "@typescript-eslint/visitor-keys" "5.14.0"
-    debug "^4.3.2"
-    globby "^11.0.4"
+    "@typescript-eslint/types" "5.33.1"
+    "@typescript-eslint/visitor-keys" "5.33.1"
+    debug "^4.3.4"
+    globby "^11.1.0"
     is-glob "^4.0.3"
-    semver "^7.3.5"
+    semver "^7.3.7"
     tsutils "^3.21.0"
 
-"@typescript-eslint/utils@5.14.0":
-  version "5.14.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.14.0.tgz#6c8bc4f384298cbbb32b3629ba7415f9f80dc8c4"
-  integrity sha512-EHwlII5mvUA0UsKYnVzySb/5EE/t03duUTweVy8Zqt3UQXBrpEVY144OTceFKaOe4xQXZJrkptCf7PjEBeGK4w==
+"@typescript-eslint/utils@5.33.1":
+  version "5.33.1"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.33.1.tgz#171725f924fe1fe82bb776522bb85bc034e88575"
+  integrity sha512-uphZjkMaZ4fE8CR4dU7BquOV6u0doeQAr8n6cQenl/poMaIyJtBu8eys5uk6u5HiDH01Mj5lzbJ5SfeDz7oqMQ==
   dependencies:
     "@types/json-schema" "^7.0.9"
-    "@typescript-eslint/scope-manager" "5.14.0"
-    "@typescript-eslint/types" "5.14.0"
-    "@typescript-eslint/typescript-estree" "5.14.0"
+    "@typescript-eslint/scope-manager" "5.33.1"
+    "@typescript-eslint/types" "5.33.1"
+    "@typescript-eslint/typescript-estree" "5.33.1"
     eslint-scope "^5.1.1"
     eslint-utils "^3.0.0"
 
-"@typescript-eslint/visitor-keys@5.14.0":
-  version "5.14.0"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.14.0.tgz#1927005b3434ccd0d3ae1b2ecf60e65943c36986"
-  integrity sha512-yL0XxfzR94UEkjBqyymMLgCBdojzEuy/eim7N9/RIcTNxpJudAcqsU8eRyfzBbcEzGoPWfdM3AGak3cN08WOIw==
+"@typescript-eslint/visitor-keys@5.27.0":
+  version "5.27.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.27.0.tgz#97aa9a5d2f3df8215e6d3b77f9d214a24db269bd"
+  integrity sha512-46cYrteA2MrIAjv9ai44OQDUoCZyHeGIc4lsjCUX2WT6r4C+kidz1bNiR4017wHOPUythYeH+Sc7/cFP97KEAA==
   dependencies:
-    "@typescript-eslint/types" "5.14.0"
-    eslint-visitor-keys "^3.0.0"
+    "@typescript-eslint/types" "5.27.0"
+    eslint-visitor-keys "^3.3.0"
+
+"@typescript-eslint/visitor-keys@5.33.1":
+  version "5.33.1"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.33.1.tgz#0155c7571c8cd08956580b880aea327d5c34a18b"
+  integrity sha512-nwIxOK8Z2MPWltLKMLOEZwmfBZReqUdbEoHQXeCpa+sRVARe5twpJGHCB4dk9903Yaf0nMAlGbQfaAH92F60eg==
+  dependencies:
+    "@typescript-eslint/types" "5.33.1"
+    eslint-visitor-keys "^3.3.0"
 
 JSONStream@^1.0.4:
   version "1.3.5"
@@ -2829,17 +3326,22 @@ accepts@~1.3.8:
     mime-types "~2.1.34"
     negotiator "0.6.3"
 
-ace-builds@^1.4.13, ace-builds@^1.4.14:
-  version "1.4.14"
-  resolved "https://registry.yarnpkg.com/ace-builds/-/ace-builds-1.4.14.tgz#2c41ccbccdd09e665d3489f161a20baeb3a3c852"
-  integrity sha512-NBOQlm9+7RBqRqZwimpgquaLeTJFayqb9UEPtTkpC3TkkwDnlsT/TwsCC0svjt9kEZ6G9mH5AEOHSz6Q/HrzQQ==
+ace-builds@1.9.6:
+  version "1.9.6"
+  resolved "https://registry.yarnpkg.com/ace-builds/-/ace-builds-1.9.6.tgz#2d3721f90f0664b79be9288f6319dd57576ff1e7"
+  integrity sha512-M/Li4hPruMSbkkg35LgdbsIBq0WuwrV4ztP2pKaww47rC/MvDc1bOrYxwJrfgxdlzyLKrja5bn+9KwwuzqB2xQ==
 
-acorn-jsx@^5.3.1:
+ace-builds@^1.4.14:
+  version "1.5.2"
+  resolved "https://registry.yarnpkg.com/ace-builds/-/ace-builds-1.5.2.tgz#411752873a19a4d653a0b156131d56e4192bd9e3"
+  integrity sha512-E/h9JRtcTwzXYKZ4Ucnw9Eit0gEWQSFrjSCQQER/qIavrVbWNM4w21WqyyOqSVs+jtMjpSO11mg2ZZTExXbltQ==
+
+acorn-jsx@^5.3.2:
   version "5.3.2"
   resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
   integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
 
-acorn-node@^1.6.1:
+acorn-node@^1.8.2:
   version "1.8.2"
   resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8"
   integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==
@@ -2863,10 +3365,15 @@ acorn@^7.0.0, acorn@^7.1.1:
   resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
   integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
 
-acorn@^8.4.1, acorn@^8.7.0:
-  version "8.7.0"
-  resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf"
-  integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==
+acorn@^8.4.1, acorn@^8.7.1:
+  version "8.7.1"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30"
+  integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==
+
+acorn@^8.8.0:
+  version "8.8.0"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8"
+  integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==
 
 agent-base@6, agent-base@^6.0.2:
   version "6.0.2"
@@ -2921,34 +3428,27 @@ ajv@^6.10.0, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.12.6:
     json-schema-traverse "^0.4.1"
     uri-js "^4.2.2"
 
-ajv@^8.0.0, ajv@^8.8.0:
-  version "8.10.0"
-  resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d"
-  integrity sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==
+ajv@^8.0.0, ajv@^8.11.0, ajv@^8.8.0:
+  version "8.11.0"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f"
+  integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==
   dependencies:
     fast-deep-equal "^3.1.1"
     json-schema-traverse "^1.0.0"
     require-from-string "^2.0.2"
     uri-js "^4.2.2"
 
-ansi-align@^3.0.0:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59"
-  integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==
-  dependencies:
-    string-width "^4.1.0"
-
 ansi-colors@^4.1.1:
-  version "4.1.1"
-  resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
-  integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
+  version "4.1.3"
+  resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b"
+  integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==
 
 ansi-escapes@^3.2.0:
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
   integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
 
-ansi-escapes@^4.3.0:
+ansi-escapes@^4.2.1, ansi-escapes@^4.3.0:
   version "4.3.2"
   resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
   integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
@@ -2962,15 +3462,10 @@ ansi-escapes@^5.0.0:
   dependencies:
     type-fest "^1.0.2"
 
-ansi-regex@^2.0.0:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
-  integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
-
 ansi-regex@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
-  integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1"
+  integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==
 
 ansi-regex@^4.1.0:
   version "4.1.1"
@@ -3009,17 +3504,12 @@ ansi-styles@^6.0.0:
 ansicolors@~0.3.2:
   version "0.3.2"
   resolved "https://registry.yarnpkg.com/ansicolors/-/ansicolors-0.3.2.tgz#665597de86a9ffe3aa9bfbe6cae5c6ea426b4979"
-  integrity sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=
-
-ansistyles@~0.1.3:
-  version "0.1.3"
-  resolved "https://registry.yarnpkg.com/ansistyles/-/ansistyles-0.1.3.tgz#5de60415bda071bb37127854c864f41b23254539"
-  integrity sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk=
+  integrity sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==
 
 any-promise@^1.0.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
-  integrity sha1-q8av7tzqUugJzcA3au0845Y10X8=
+  integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==
 
 anymatch@~3.1.2:
   version "3.1.2"
@@ -3037,22 +3527,22 @@ app-root-path@^3.0.0:
 append-field@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56"
-  integrity sha1-HjRA6RXwsSA9I3SOeO3XubW0PlY=
-
-aproba@^1.0.3:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
-  integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
+  integrity sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==
 
 "aproba@^1.0.3 || ^2.0.0", aproba@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc"
   integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==
 
+arch@^2.2.0:
+  version "2.2.0"
+  resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11"
+  integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==
+
 archy@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40"
-  integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=
+  integrity sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==
 
 are-we-there-yet@^2.0.0:
   version "2.0.0"
@@ -3070,23 +3560,15 @@ are-we-there-yet@^3.0.0:
     delegates "^1.0.0"
     readable-stream "^3.6.0"
 
-are-we-there-yet@~1.1.2:
-  version "1.1.7"
-  resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz#b15474a932adab4ff8a50d9adfa7e4e926f21146"
-  integrity sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==
-  dependencies:
-    delegates "^1.0.0"
-    readable-stream "^2.0.6"
-
 arg@^4.1.0:
   version "4.1.3"
   resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
   integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
 
-arg@^5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.1.tgz#eb0c9a8f77786cad2af8ff2b862899842d7b6adb"
-  integrity sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==
+arg@^5.0.2:
+  version "5.0.2"
+  resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
+  integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==
 
 argparse@^1.0.7:
   version "1.0.10"
@@ -3103,7 +3585,7 @@ argparse@^2.0.1:
 argv-formatter@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/argv-formatter/-/argv-formatter-1.0.0.tgz#a0ca0cbc29a5b73e836eebe1cbf6c5e0e4eb82f9"
-  integrity sha1-oMoMvCmltz6Dbuvhy/bF4OTrgvk=
+  integrity sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==
 
 aria-query@^4.2.2:
   version "4.2.2"
@@ -3121,21 +3603,21 @@ array-differ@^3.0.0:
 array-flatten@1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
-  integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
+  integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==
 
 array-ify@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece"
-  integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=
+  integrity sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==
 
-array-includes@^3.1.3, array-includes@^3.1.4:
-  version "3.1.4"
-  resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.4.tgz#f5b493162c760f3539631f005ba2bb46acb45ba9"
-  integrity sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==
+array-includes@^3.1.4, array-includes@^3.1.5:
+  version "3.1.5"
+  resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.5.tgz#2c320010db8d31031fd2a5f6b3bbd4b1aad31bdb"
+  integrity sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==
   dependencies:
     call-bind "^1.0.2"
-    define-properties "^1.1.3"
-    es-abstract "^1.19.1"
+    define-properties "^1.1.4"
+    es-abstract "^1.19.5"
     get-intrinsic "^1.1.1"
     is-string "^1.0.7"
 
@@ -3145,27 +3627,29 @@ array-union@^2.1.0:
   integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
 
 array.prototype.flat@^1.2.5:
-  version "1.2.5"
-  resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.5.tgz#07e0975d84bbc7c48cd1879d609e682598d33e13"
-  integrity sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz#0b0c1567bf57b38b56b4c97b8aa72ab45e4adc7b"
+  integrity sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==
   dependencies:
     call-bind "^1.0.2"
     define-properties "^1.1.3"
-    es-abstract "^1.19.0"
+    es-abstract "^1.19.2"
+    es-shim-unscopables "^1.0.0"
 
-array.prototype.flatmap@^1.2.5:
-  version "1.2.5"
-  resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.5.tgz#908dc82d8a406930fdf38598d51e7411d18d4446"
-  integrity sha512-08u6rVyi1Lj7oqWbS9nUxliETrtIROT4XGTA4D/LWGten6E3ocm7cy9SIrmNHOL5XVbVuckUp3X6Xyg8/zpvHA==
+array.prototype.flatmap@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz#a7e8ed4225f4788a70cd910abcf0791e76a5534f"
+  integrity sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==
   dependencies:
-    call-bind "^1.0.0"
+    call-bind "^1.0.2"
     define-properties "^1.1.3"
-    es-abstract "^1.19.0"
+    es-abstract "^1.19.2"
+    es-shim-unscopables "^1.0.0"
 
 arrify@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
-  integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
+  integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==
 
 arrify@^2.0.1:
   version "2.0.1"
@@ -3175,7 +3659,7 @@ arrify@^2.0.1:
 asap@^2.0.0, asap@~2.0.3:
   version "2.0.6"
   resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
-  integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
+  integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==
 
 asn1.js@^5.0.0, asn1.js@^5.3.0:
   version "5.4.1"
@@ -3202,18 +3686,23 @@ assert-never@^1.2.1:
 assert-plus@1.0.0, assert-plus@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
-  integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
+  integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==
 
 ast-types-flow@^0.0.7:
   version "0.0.7"
   resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
-  integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0=
+  integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==
 
 astral-regex@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
   integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
 
+async@^3.2.0:
+  version "3.2.4"
+  resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
+  integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
+
 async@^3.2.3:
   version "3.2.3"
   resolved "https://registry.yarnpkg.com/async/-/async-3.2.3.tgz#ac53dafd3f4720ee9e8a160628f18ea91df196c9"
@@ -3222,21 +3711,21 @@ async@^3.2.3:
 asynckit@^0.4.0:
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
-  integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
+  integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
 
 at-least-node@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
   integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
 
-autoprefixer@^10.4.2:
-  version "10.4.2"
-  resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.2.tgz#25e1df09a31a9fba5c40b578936b90d35c9d4d3b"
-  integrity sha512-9fOPpHKuDW1w/0EKfRmVnxTDt8166MAnLI3mgZ1JCnhNtYWxcJ6Ud5CO/AVOZi/AvFa8DY9RTy3h3+tFBlrrdQ==
+autoprefixer@10.4.8:
+  version "10.4.8"
+  resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.8.tgz#92c7a0199e1cfb2ad5d9427bd585a3d75895b9e5"
+  integrity sha512-75Jr6Q/XpTqEf6D2ltS5uMewJIx5irCU1oBYJrWjFenq/m12WRRrz6g15L1EIoYvPLXTbEry7rDOwrcYNj77xw==
   dependencies:
-    browserslist "^4.19.1"
-    caniuse-lite "^1.0.30001297"
-    fraction.js "^4.1.2"
+    browserslist "^4.21.3"
+    caniuse-lite "^1.0.30001373"
+    fraction.js "^4.2.0"
     normalize-range "^0.1.2"
     picocolors "^1.0.0"
     postcss-value-parser "^4.2.0"
@@ -3244,7 +3733,7 @@ autoprefixer@^10.4.2:
 aws-sign2@~0.7.0:
   version "0.7.0"
   resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
-  integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
+  integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==
 
 aws4@^1.8.0:
   version "1.11.0"
@@ -3252,16 +3741,27 @@ aws4@^1.8.0:
   integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
 
 axe-core@^4.3.5:
-  version "4.4.1"
-  resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.1.tgz#7dbdc25989298f9ad006645cd396782443757413"
-  integrity sha512-gd1kmb21kwNuWr6BQz8fv6GNECPBnUasepcoLbekws23NVBLODdsClRZ+bQ8+9Uomf3Sm3+Vwn0oYG9NvwnJCw==
+  version "4.4.2"
+  resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.2.tgz#dcf7fb6dea866166c3eab33d68208afe4d5f670c"
+  integrity sha512-LVAaGp/wkkgYJcjmHsoKx4juT1aQvJyPcW09MLCjVTh3V2cc6PnyempiLMNH5iMdfIX/zdbjUx2KDjMLCTdPeA==
 
-axios@^0.26.1:
-  version "0.26.1"
-  resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9"
-  integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==
+axe-core@^4.4.3:
+  version "4.4.3"
+  resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.3.tgz#11c74d23d5013c0fa5d183796729bc3482bd2f6f"
+  integrity sha512-32+ub6kkdhhWick/UjvEwRchgoetXqTK14INLqbGm5U2TzBkBNF3nQtLYm8ovxSkQWArjEQvftCKryjZaATu3w==
+
+axios-rate-limit@1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/axios-rate-limit/-/axios-rate-limit-1.3.0.tgz#03241d24c231c47432dab6e8234cfde819253c2e"
+  integrity sha512-cKR5wTbU/CeeyF1xVl5hl6FlYsmzDVqxlN4rGtfO5x7J83UxKDckudsW0yW21/ZJRcO0Qrfm3fUFbhEbWTLayw==
+
+axios@0.27.2:
+  version "0.27.2"
+  resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972"
+  integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==
   dependencies:
-    follow-redirects "^1.14.8"
+    follow-redirects "^1.14.9"
+    form-data "^4.0.0"
 
 axobject-query@^2.2.0:
   version "2.2.0"
@@ -3300,31 +3800,31 @@ babel-plugin-macros@^2.0.0, babel-plugin-macros@^2.6.1:
     cosmiconfig "^6.0.0"
     resolve "^1.12.0"
 
-babel-plugin-polyfill-corejs2@^0.3.0:
-  version "0.3.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz#440f1b70ccfaabc6b676d196239b138f8a2cfba5"
-  integrity sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==
+babel-plugin-polyfill-corejs2@^0.3.2:
+  version "0.3.2"
+  resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.2.tgz#e4c31d4c89b56f3cf85b92558954c66b54bd972d"
+  integrity sha512-LPnodUl3lS0/4wN3Rb+m+UK8s7lj2jcLRrjho4gLw+OJs+I4bvGXshINesY5xx/apM+biTnQ9reDI8yj+0M5+Q==
   dependencies:
-    "@babel/compat-data" "^7.13.11"
-    "@babel/helper-define-polyfill-provider" "^0.3.1"
+    "@babel/compat-data" "^7.17.7"
+    "@babel/helper-define-polyfill-provider" "^0.3.2"
     semver "^6.1.1"
 
-babel-plugin-polyfill-corejs3@^0.5.0:
-  version "0.5.2"
-  resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz#aabe4b2fa04a6e038b688c5e55d44e78cd3a5f72"
-  integrity sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==
+babel-plugin-polyfill-corejs3@^0.5.3:
+  version "0.5.3"
+  resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.3.tgz#d7e09c9a899079d71a8b670c6181af56ec19c5c7"
+  integrity sha512-zKsXDh0XjnrUEW0mxIHLfjBfnXSMr5Q/goMe/fxpQnLm07mcOZiIZHBNWCMx60HmdvjxfXcalac0tfFg0wqxyw==
   dependencies:
-    "@babel/helper-define-polyfill-provider" "^0.3.1"
+    "@babel/helper-define-polyfill-provider" "^0.3.2"
     core-js-compat "^3.21.0"
 
-babel-plugin-polyfill-regenerator@^0.3.0:
-  version "0.3.1"
-  resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz#2c0678ea47c75c8cc2fbb1852278d8fb68233990"
-  integrity sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==
+babel-plugin-polyfill-regenerator@^0.4.0:
+  version "0.4.0"
+  resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.0.tgz#8f51809b6d5883e07e71548d75966ff7635527fe"
+  integrity sha512-RW1cnryiADFeHmfLS+WW/G431p1PsW5qdRdz0SDRi7TKcUgc7Oh/uXkT7MZ/+tGsT1BkczEAmD5XjUyJ5SWDTw==
   dependencies:
-    "@babel/helper-define-polyfill-provider" "^0.3.1"
+    "@babel/helper-define-polyfill-provider" "^0.3.2"
 
-babel-plugin-react-intl-auto@^3.3.0:
+babel-plugin-react-intl-auto@3.3.0:
   version "3.3.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-react-intl-auto/-/babel-plugin-react-intl-auto-3.3.0.tgz#75c6ba8a1eb442f43c2ab85f1a75f4cc1e0d7857"
   integrity sha512-08ZyGWtKrQY/rMNfdvrWPBsjqx+8CirqV4/JUM46FAS2aU98Mi/uWM60K6Wg6Zapdyqs3fCbQ8S4OfqMPsBiqQ==
@@ -3334,6 +3834,21 @@ babel-plugin-react-intl-auto@^3.3.0:
     "@babel/types" "^7.9.0"
     murmurhash3js "^3.0.1"
 
+babel-plugin-react-intl@8.2.25:
+  version "8.2.25"
+  resolved "https://registry.yarnpkg.com/babel-plugin-react-intl/-/babel-plugin-react-intl-8.2.25.tgz#7b6adaa2bc291ac7b9f87bf51f1c2ea8974ffe84"
+  integrity sha512-vqzRwqxMKHBKEpzWIIabxUXSBYd8urOkk49nQdzgEt55tLIuDc1XdHceeMNaeJt9VRLYZUiL5vpYpnvrntUNMQ==
+  dependencies:
+    "@babel/core" "^7.9.0"
+    "@babel/helper-plugin-utils" "^7.8.3"
+    "@babel/types" "^7.9.5"
+    "@formatjs/ts-transformer" "2.13.0"
+    "@types/babel__core" "^7.1.7"
+    "@types/schema-utils" "^2.4.0"
+    intl-messageformat-parser "6.1.2"
+    schema-utils "^3.0.0"
+    tslib "^2.0.1"
+
 babel-plugin-react-intl@^7.0.0:
   version "7.9.4"
   resolved "https://registry.yarnpkg.com/babel-plugin-react-intl/-/babel-plugin-react-intl-7.9.4.tgz#1fc9ab50470d41b934df50d8f436578ee1732cb0"
@@ -3350,25 +3865,10 @@ babel-plugin-react-intl@^7.0.0:
     intl-messageformat-parser "^5.3.7"
     schema-utils "^2.6.6"
 
-babel-plugin-react-intl@^8.2.25:
-  version "8.2.25"
-  resolved "https://registry.yarnpkg.com/babel-plugin-react-intl/-/babel-plugin-react-intl-8.2.25.tgz#7b6adaa2bc291ac7b9f87bf51f1c2ea8974ffe84"
-  integrity sha512-vqzRwqxMKHBKEpzWIIabxUXSBYd8urOkk49nQdzgEt55tLIuDc1XdHceeMNaeJt9VRLYZUiL5vpYpnvrntUNMQ==
-  dependencies:
-    "@babel/core" "^7.9.0"
-    "@babel/helper-plugin-utils" "^7.8.3"
-    "@babel/types" "^7.9.5"
-    "@formatjs/ts-transformer" "2.13.0"
-    "@types/babel__core" "^7.1.7"
-    "@types/schema-utils" "^2.4.0"
-    intl-messageformat-parser "6.1.2"
-    schema-utils "^3.0.0"
-    tslib "^2.0.1"
-
 babel-plugin-syntax-jsx@^6.18.0:
   version "6.18.0"
   resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946"
-  integrity sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=
+  integrity sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==
 
 babel-walk@3.0.0-canary-5:
   version "3.0.0-canary-5"
@@ -3395,11 +3895,11 @@ base64-js@^1.3.1:
 bcrypt-pbkdf@^1.0.0:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
-  integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
+  integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==
   dependencies:
     tweetnacl "^0.14.3"
 
-bcrypt@^5.0.1:
+bcrypt@5.0.1:
   version "5.0.1"
   resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-5.0.1.tgz#f1a2c20f208e2ccdceea4433df0c8b2c54ecdf71"
   integrity sha512-9BTgmrhZM2t1bNuDtrtIMVSmmxZBrJ71n8Wg+YgdjHuIWYF7SjjmCPZFB+/5i/o/PIeRpwVJR3P+NrpIItUjqw==
@@ -3413,14 +3913,14 @@ before-after-hook@^2.2.0:
   integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==
 
 bin-links@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-3.0.0.tgz#8273063638919f6ba4fbe890de9438c1b3adf0b7"
-  integrity sha512-fC7kPWcEkAWBgCKxmAMqZldlIeHsXwQy9JXzrppAVQiukGiDKxmYesJcBKWu6UMwx/5GOfo10wtK/4zy+Xt/mg==
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-3.0.1.tgz#cc70ffb481988b22c527d3e6e454787876987a49"
+  integrity sha512-9vx+ypzVhASvHTS6K+YSGf7nwQdANoz7v6MTC0aCtYnOEZ87YvMf81aY737EZnGZdpbRM3sfWjO9oWkKmuIvyQ==
   dependencies:
-    cmd-shim "^4.0.1"
+    cmd-shim "^5.0.0"
     mkdirp-infer-owner "^2.0.0"
     npm-normalize-package-bin "^1.0.0"
-    read-cmd-shim "^2.0.0"
+    read-cmd-shim "^3.0.0"
     rimraf "^3.0.0"
     write-file-atomic "^4.0.0"
 
@@ -3429,6 +3929,20 @@ binary-extensions@^2.0.0, binary-extensions@^2.2.0:
   resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
   integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
 
+bl@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
+  integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
+  dependencies:
+    buffer "^5.5.0"
+    inherits "^2.0.4"
+    readable-stream "^3.4.0"
+
+blob-util@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb"
+  integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==
+
 bluebird@^3.3.5, bluebird@^3.5.0, bluebird@^3.7.2:
   version "3.7.2"
   resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
@@ -3444,26 +3958,28 @@ bn.js@^4.0.0:
   resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88"
   integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==
 
-body-parser@1.19.2:
-  version "1.19.2"
-  resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.2.tgz#4714ccd9c157d44797b8b5607d72c0b89952f26e"
-  integrity sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==
+body-parser@1.20.0:
+  version "1.20.0"
+  resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5"
+  integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==
   dependencies:
     bytes "3.1.2"
     content-type "~1.0.4"
     debug "2.6.9"
-    depd "~1.1.2"
-    http-errors "1.8.1"
+    depd "2.0.0"
+    destroy "1.2.0"
+    http-errors "2.0.0"
     iconv-lite "0.4.24"
-    on-finished "~2.3.0"
-    qs "6.9.7"
-    raw-body "2.4.3"
+    on-finished "2.4.1"
+    qs "6.10.3"
+    raw-body "2.5.1"
     type-is "~1.6.18"
+    unpipe "1.0.0"
 
 boolbase@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
-  integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24=
+  integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==
 
 boolean@3.2.0, boolean@^3.1.4:
   version "3.2.0"
@@ -3475,25 +3991,11 @@ bottleneck@^2.18.1:
   resolved "https://registry.yarnpkg.com/bottleneck/-/bottleneck-2.19.5.tgz#5df0b90f59fd47656ebe63c78a98419205cadd91"
   integrity sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==
 
-bowser@^2.11.0:
+bowser@2.11.0:
   version "2.11.0"
   resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f"
   integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==
 
-boxen@^5.0.0:
-  version "5.1.2"
-  resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50"
-  integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==
-  dependencies:
-    ansi-align "^3.0.0"
-    camelcase "^6.2.0"
-    chalk "^4.1.0"
-    cli-boxes "^2.2.1"
-    string-width "^4.2.2"
-    type-fest "^0.20.2"
-    widest-line "^3.1.0"
-    wrap-ansi "^7.0.0"
-
 brace-expansion@^1.1.7:
   version "1.1.11"
   resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -3509,34 +4011,57 @@ brace-expansion@^2.0.1:
   dependencies:
     balanced-match "^1.0.0"
 
-braces@^3.0.1, braces@~3.0.2:
+braces@^3.0.2, braces@~3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
   integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
   dependencies:
     fill-range "^7.0.1"
 
-browserslist@^4.17.5, browserslist@^4.19.1:
-  version "4.20.0"
-  resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.0.tgz#35951e3541078c125d36df76056e94738a52ebe9"
-  integrity sha512-bnpOoa+DownbciXj0jVGENf8VYQnE2LNWomhYuCsMmmx9Jd9lwq0WXODuwpSsp8AVdKM2/HorrzxAfbKvWTByQ==
+browserslist@^4.20.2, browserslist@^4.20.3:
+  version "4.20.3"
+  resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.3.tgz#eb7572f49ec430e054f56d52ff0ebe9be915f8bf"
+  integrity sha512-NBhymBQl1zM0Y5dQT/O+xiLP9/rzOIQdKM/eMJBAq7yBgaB6krIYLGejrwVYnSHZdqjscB1SPuAjHwxjvN6Wdg==
   dependencies:
-    caniuse-lite "^1.0.30001313"
-    electron-to-chromium "^1.4.76"
+    caniuse-lite "^1.0.30001332"
+    electron-to-chromium "^1.4.118"
     escalade "^3.1.1"
-    node-releases "^2.0.2"
+    node-releases "^2.0.3"
     picocolors "^1.0.0"
 
+browserslist@^4.21.3:
+  version "4.21.3"
+  resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.3.tgz#5df277694eb3c48bc5c4b05af3e8b7e09c5a6d1a"
+  integrity sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==
+  dependencies:
+    caniuse-lite "^1.0.30001370"
+    electron-to-chromium "^1.4.202"
+    node-releases "^2.0.6"
+    update-browserslist-db "^1.0.5"
+
+buffer-crc32@~0.2.3:
+  version "0.2.13"
+  resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
+  integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==
+
 buffer-equal-constant-time@1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
-  integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=
+  integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==
 
 buffer-from@^1.0.0:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
   integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
 
+buffer@^5.5.0, buffer@^5.6.0:
+  version "5.7.1"
+  resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
+  integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
+  dependencies:
+    base64-js "^1.3.1"
+    ieee754 "^1.1.13"
+
 buffer@^6.0.3:
   version "6.0.3"
   resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
@@ -3545,25 +4070,26 @@ buffer@^6.0.3:
     base64-js "^1.3.1"
     ieee754 "^1.2.1"
 
-builtins@^1.0.3:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88"
-  integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og=
+builtins@^5.0.0:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/builtins/-/builtins-5.0.1.tgz#87f6db9ab0458be728564fa81d876d8d74552fa9"
+  integrity sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==
+  dependencies:
+    semver "^7.0.0"
 
-busboy@^0.2.11:
-  version "0.2.14"
-  resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453"
-  integrity sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=
+busboy@^1.0.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
+  integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
   dependencies:
-    dicer "0.2.5"
-    readable-stream "1.1.x"
+    streamsearch "^1.1.0"
 
 bytes@3.1.2:
   version "3.1.2"
   resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
   integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
 
-cacache@^15.0.3, cacache@^15.2.0, cacache@^15.3.0:
+cacache@^15.2.0:
   version "15.3.0"
   resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb"
   integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==
@@ -3587,24 +4113,40 @@ cacache@^15.0.3, cacache@^15.2.0, cacache@^15.3.0:
     tar "^6.0.2"
     unique-filename "^1.1.1"
 
-cacheable-request@^6.0.0:
-  version "6.1.0"
-  resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912"
-  integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==
+cacache@^16.0.0, cacache@^16.0.6, cacache@^16.1.0:
+  version "16.1.0"
+  resolved "https://registry.yarnpkg.com/cacache/-/cacache-16.1.0.tgz#87a6bae558a511c9cb2a13768073e240ca76153a"
+  integrity sha512-Pk4aQkwCW82A4jGKFvcGkQFqZcMspfP9YWq9Pr87/ldDvlWf718zeI6KWCdKt/jeihu6BytHRUicJPB1K2k8EQ==
   dependencies:
-    clone-response "^1.0.2"
-    get-stream "^5.1.0"
-    http-cache-semantics "^4.0.0"
-    keyv "^3.0.0"
-    lowercase-keys "^2.0.0"
-    normalize-url "^4.1.0"
-    responselike "^1.0.2"
+    "@npmcli/fs" "^2.1.0"
+    "@npmcli/move-file" "^2.0.0"
+    chownr "^2.0.0"
+    fs-minipass "^2.1.0"
+    glob "^8.0.1"
+    infer-owner "^1.0.4"
+    lru-cache "^7.7.1"
+    minipass "^3.1.6"
+    minipass-collect "^1.0.2"
+    minipass-flush "^1.0.5"
+    minipass-pipeline "^1.2.4"
+    mkdirp "^1.0.4"
+    p-map "^4.0.0"
+    promise-inflight "^1.0.1"
+    rimraf "^3.0.2"
+    ssri "^9.0.0"
+    tar "^6.1.11"
+    unique-filename "^1.1.1"
 
 cachedir@2.2.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.2.0.tgz#19afa4305e05d79e417566882e0c8f960f62ff0e"
   integrity sha512-VvxA0xhNqIIfg0V9AmJkDg91DaJwryutH5rVEZAhcNi4iJFj9f+QxmAjgK1LT9I8OgToX27fypX6/MeCXVbBjQ==
 
+cachedir@2.3.0, cachedir@^2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8"
+  integrity sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==
+
 call-bind@^1.0.0, call-bind@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
@@ -3616,7 +4158,7 @@ call-bind@^1.0.0, call-bind@^1.0.2:
 call-me-maybe@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
-  integrity sha1-JtII6onje1y95gJQoV8DHBak1ms=
+  integrity sha512-wCyFsDQkKPwwF8BDwOiWNx/9K45L/hvggQiDbve+viMNMQnWhrlYIuBk09offfwCRtCO9P6XwUttufzU11WCVw==
 
 callsites@^3.0.0:
   version "3.1.0"
@@ -3647,15 +4189,20 @@ camelcase@^6.2.0:
   resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
   integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
 
-caniuse-lite@^1.0.30001283, caniuse-lite@^1.0.30001297, caniuse-lite@^1.0.30001313:
-  version "1.0.30001315"
-  resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001315.tgz#f1b1efd1171ee1170d52709a7252632dacbd7c77"
-  integrity sha512-5v7LFQU4Sb/qvkz7JcZkvtSH1Ko+1x2kgo3ocdBeMGZSOFpuE1kkm0kpTwLtWeFrw5qw08ulLxJjVIXIS8MkiQ==
+caniuse-lite@^1.0.30001332:
+  version "1.0.30001344"
+  resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001344.tgz#8a1e7fdc4db9c2ec79a05e9fd68eb93a761888bb"
+  integrity sha512-0ZFjnlCaXNOAYcV7i+TtdKBp0L/3XEU2MF/x6Du1lrh+SRX4IfzIVL4HNJg5pB2PmFb8rszIGyOvsZnqqRoc2g==
+
+caniuse-lite@^1.0.30001370, caniuse-lite@^1.0.30001373:
+  version "1.0.30001378"
+  resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001378.tgz#3d2159bf5a8f9ca093275b0d3ecc717b00f27b67"
+  integrity sha512-JVQnfoO7FK7WvU4ZkBRbPjaot4+YqxogSDosHv0Hv5mWpUESmN+UubMU6L/hGz8QlQ2aY5U0vR6MOs6j/CXpNA==
 
 cardinal@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/cardinal/-/cardinal-2.1.1.tgz#7cc1055d822d212954d07b085dea251cc7bc5505"
-  integrity sha1-fMEFXYItISlU0HsIXeolHMe8VQU=
+  integrity sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==
   dependencies:
     ansicolors "~0.3.2"
     redeyed "~2.1.0"
@@ -3663,7 +4210,7 @@ cardinal@^2.1.1:
 caseless@~0.12.0:
   version "0.12.0"
   resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
-  integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
+  integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==
 
 chalk@^2.0.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2:
   version "2.4.2"
@@ -3674,7 +4221,7 @@ chalk@^2.0.0, chalk@^2.3.2, chalk@^2.4.1, chalk@^2.4.2:
     escape-string-regexp "^1.0.5"
     supports-color "^5.3.0"
 
-chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2:
+chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
   version "4.1.2"
   resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
   integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@@ -3695,7 +4242,7 @@ character-entities@^2.0.0:
 character-parser@^2.2.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/character-parser/-/character-parser-2.2.0.tgz#c7ce28f36d4bcd9744e5ffc2c5fcde1c73261fc0"
-  integrity sha1-x84o821LzZdE5f/CxfzeHHMmH8A=
+  integrity sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==
   dependencies:
     is-regex "^1.0.3"
 
@@ -3704,29 +4251,36 @@ chardet@^0.7.0:
   resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
   integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
 
-cheerio-select@^1.5.0:
-  version "1.5.0"
-  resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-1.5.0.tgz#faf3daeb31b17c5e1a9dabcee288aaf8aafa5823"
-  integrity sha512-qocaHPv5ypefh6YNxvnbABM07KMxExbtbfuJoIie3iZXX1ERwYmJcIiRrr9H05ucQP1k28dav8rpdDgjQd8drg==
+check-more-types@^2.24.0:
+  version "2.24.0"
+  resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600"
+  integrity sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==
+
+cheerio-select@^2.1.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4"
+  integrity sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==
   dependencies:
-    css-select "^4.1.3"
-    css-what "^5.0.1"
-    domelementtype "^2.2.0"
-    domhandler "^4.2.0"
-    domutils "^2.7.0"
+    boolbase "^1.0.0"
+    css-select "^5.1.0"
+    css-what "^6.1.0"
+    domelementtype "^2.3.0"
+    domhandler "^5.0.3"
+    domutils "^3.0.1"
 
 cheerio@^1.0.0-rc.3:
-  version "1.0.0-rc.10"
-  resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.10.tgz#2ba3dcdfcc26e7956fc1f440e61d51c643379f3e"
-  integrity sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==
-  dependencies:
-    cheerio-select "^1.5.0"
-    dom-serializer "^1.3.2"
-    domhandler "^4.2.0"
-    htmlparser2 "^6.1.0"
-    parse5 "^6.0.1"
-    parse5-htmlparser2-tree-adapter "^6.0.1"
-    tslib "^2.2.0"
+  version "1.0.0-rc.11"
+  resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.11.tgz#1be84be1a126958366bcc57a11648cd9b30a60c2"
+  integrity sha512-bQwNaDIBKID5ts/DsdhxrjqFXYfLw4ste+wMKqWA8DyKcS4qwsPP4Bk8ZNaTJjvpiX/qW3BT4sU7d6Bh5i+dag==
+  dependencies:
+    cheerio-select "^2.1.0"
+    dom-serializer "^2.0.0"
+    domhandler "^5.0.3"
+    domutils "^3.0.1"
+    htmlparser2 "^8.0.1"
+    parse5 "^7.0.0"
+    parse5-htmlparser2-tree-adapter "^7.0.0"
+    tslib "^2.4.0"
 
 chokidar@^3.4.0, chokidar@^3.5.2, chokidar@^3.5.3:
   version "3.5.3"
@@ -3743,20 +4297,15 @@ chokidar@^3.4.0, chokidar@^3.5.2, chokidar@^3.5.3:
   optionalDependencies:
     fsevents "~2.3.2"
 
-chownr@^1.1.4:
-  version "1.1.4"
-  resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
-  integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
-
 chownr@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
   integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
 
-ci-info@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
-  integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
+ci-info@^3.2.0:
+  version "3.3.2"
+  resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.2.tgz#6d2967ffa407466481c6c90b6e16b3098f080128"
+  integrity sha512-xmDt/QIAdeZ9+nfdPsaBCpMvHNLFiLdjj59qjqn+6iPe6YmHGQ35sBnQ8uslRBXFmXkiZQOJRjvQeoGppoTjjg==
 
 cidr-regex@^3.1.1:
   version "3.1.1"
@@ -3775,11 +4324,6 @@ clean-stack@^2.0.0:
   resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
   integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
 
-cli-boxes@^2.2.1:
-  version "2.2.1"
-  resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f"
-  integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==
-
 cli-columns@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/cli-columns/-/cli-columns-4.0.0.tgz#9fe4d65975238d55218c41bd2ed296a7fa555646"
@@ -3791,7 +4335,7 @@ cli-columns@^4.0.0:
 cli-cursor@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5"
-  integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=
+  integrity sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==
   dependencies:
     restore-cursor "^2.0.0"
 
@@ -3814,14 +4358,19 @@ cli-highlight@^2.1.11:
     parse5-htmlparser2-tree-adapter "^6.0.0"
     yargs "^16.0.0"
 
-cli-table3@^0.6.1:
-  version "0.6.1"
-  resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.1.tgz#36ce9b7af4847f288d3cdd081fbd09bf7bd237b8"
-  integrity sha512-w0q/enDHhPLq44ovMGdQeeDLvwxwavsJX7oQGYt/LrBlYsyaxyDnp6z3QzFut/6kLLKnlcUVJLrpB7KBfgG/RA==
+cli-spinners@^2.5.0:
+  version "2.7.0"
+  resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.7.0.tgz#f815fd30b5f9eaac02db604c7a231ed7cb2f797a"
+  integrity sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==
+
+cli-table3@^0.6.1, cli-table3@^0.6.2, cli-table3@~0.6.1:
+  version "0.6.2"
+  resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.2.tgz#aaf5df9d8b5bf12634dc8b3040806a0c07120d2a"
+  integrity sha512-QyavHCaIC80cMivimWu4aWHilIpiDpfm3hGmqAmXVL1UsnbLuBSMd21hTX6VY4ZSDSM73ESLeF8TOYId3rBTbw==
   dependencies:
     string-width "^4.2.0"
   optionalDependencies:
-    colors "1.4.0"
+    "@colors/colors" "1.5.0"
 
 cli-truncate@^2.1.0:
   version "2.1.0"
@@ -3844,6 +4393,11 @@ cli-width@^2.0.0:
   resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48"
   integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==
 
+cli-width@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
+  integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
+
 cliui@^7.0.2:
   version "7.0.4"
   resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
@@ -3853,35 +4407,23 @@ cliui@^7.0.2:
     strip-ansi "^6.0.0"
     wrap-ansi "^7.0.0"
 
-clone-response@^1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b"
-  integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=
-  dependencies:
-    mimic-response "^1.0.0"
-
 clone@2.x:
   version "2.1.2"
   resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
-  integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=
+  integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==
 
 clone@^1.0.2:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
-  integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
+  integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==
 
-cmd-shim@^4.0.1:
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-4.1.0.tgz#b3a904a6743e9fede4148c6f3800bf2a08135bdd"
-  integrity sha512-lb9L7EM4I/ZRVuljLPEtUJOP+xiQVknZ4ZMpMgEp4JzNldPb27HU03hi6K1/6CoIuit/Zm/LQXySErFeXxDprw==
+cmd-shim@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/cmd-shim/-/cmd-shim-5.0.0.tgz#8d0aaa1a6b0708630694c4dbde070ed94c707724"
+  integrity sha512-qkCtZ59BidfEwHltnJwkyVZn+XQojdAySM1D1gSeh11Z4pW1Kpolkyo53L5noc0nrxmIvyFwTmJRo4xs7FFLPw==
   dependencies:
     mkdirp-infer-owner "^2.0.0"
 
-code-point-at@^1.0.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
-  integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
-
 color-convert@^1.9.0, color-convert@^1.9.3:
   version "1.9.3"
   resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
@@ -3899,7 +4441,7 @@ color-convert@^2.0.1:
 color-name@1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
-  integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
+  integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
 
 color-name@^1.0.0, color-name@^1.1.4, color-name@~1.1.4:
   version "1.1.4"
@@ -3907,9 +4449,9 @@ color-name@^1.0.0, color-name@^1.1.4, color-name@~1.1.4:
   integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
 
 color-string@^1.6.0:
-  version "1.9.0"
-  resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.0.tgz#63b6ebd1bec11999d1df3a79a7569451ac2be8aa"
-  integrity sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==
+  version "1.9.1"
+  resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.9.1.tgz#4467f9146f036f855b764dfb5bf8582bf342c7a4"
+  integrity sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==
   dependencies:
     color-name "^1.0.0"
     simple-swizzle "^0.2.2"
@@ -3932,11 +4474,6 @@ colorette@^2.0.16:
   resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da"
   integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g==
 
-colors@1.4.0:
-  version "1.4.0"
-  resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
-  integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==
-
 colorspace@1.1.x:
   version "1.1.4"
   resolved "https://registry.yarnpkg.com/colorspace/-/colorspace-1.1.4.tgz#8d442d1186152f60453bf8070cd66eb364e59243"
@@ -3953,7 +4490,7 @@ columnify@^1.6.0:
     strip-ansi "^6.0.1"
     wcwidth "^1.0.0"
 
-combined-stream@^1.0.6, combined-stream@~1.0.6:
+combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
   version "1.0.8"
   resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
   integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
@@ -3980,17 +4517,47 @@ commander@^5.1.0:
   resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
   integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
 
+commander@^6.1.0:
+  version "6.2.1"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
+  integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
+
 commander@^7.2.0:
   version "7.2.0"
   resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
   integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
 
-commander@^8.3.0:
-  version "8.3.0"
-  resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
-  integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
+commander@^9.0.0:
+  version "9.4.0"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-9.4.0.tgz#bc4a40918fefe52e22450c111ecd6b7acce6f11c"
+  integrity sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==
+
+commander@^9.3.0:
+  version "9.3.0"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-9.3.0.tgz#f619114a5a2d2054e0d9ff1b31d5ccf89255e26b"
+  integrity sha512-hv95iU5uXPbK83mjrJKuZyFM/LBAoCV/XhVGkS5Je6tl7sxr6A0ITMw5WoRV46/UaJ46Nllm3Xt7IaJhXTIkzw==
+
+commitizen@4.2.5:
+  version "4.2.5"
+  resolved "https://registry.yarnpkg.com/commitizen/-/commitizen-4.2.5.tgz#48e5a5c28334c6e8ed845cc24fc9f072efd3961e"
+  integrity sha512-9sXju8Qrz1B4Tw7kC5KhnvwYQN88qs2zbiB8oyMsnXZyJ24PPGiNM3nHr73d32dnE3i8VJEXddBFIbOgYSEXtQ==
+  dependencies:
+    cachedir "2.3.0"
+    cz-conventional-changelog "3.3.0"
+    dedent "0.7.0"
+    detect-indent "6.1.0"
+    find-node-modules "^2.1.2"
+    find-root "1.1.0"
+    fs-extra "9.1.0"
+    glob "7.2.3"
+    inquirer "8.2.4"
+    is-utf8 "^0.2.1"
+    lodash "4.17.21"
+    minimist "1.2.6"
+    strip-bom "4.0.0"
+    strip-json-comments "3.1.1"
 
-commitizen@^4.0.3, commitizen@^4.2.4:
+commitizen@^4.0.3:
   version "4.2.4"
   resolved "https://registry.yarnpkg.com/commitizen/-/commitizen-4.2.4.tgz#a3e5b36bd7575f6bf6e7aa19dbbf06b0d8f37165"
   integrity sha512-LlZChbDzg3Ir3O2S7jSo/cgWp5/QwylQVr59K4xayVq8S4/RdKzSyJkghAiZZHfhh5t4pxunUoyeg0ml1q/7aw==
@@ -4015,6 +4582,11 @@ common-ancestor-path@^1.0.1:
   resolved "https://registry.yarnpkg.com/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz#4f7d2d1394d91b7abdf51871c62f71eadb0182a7"
   integrity sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==
 
+common-tags@^1.8.0:
+  version "1.8.2"
+  resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6"
+  integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==
+
 compare-func@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-2.0.0.tgz#fb65e75edbddfd2e568554e8b5b05fff7a51fcb3"
@@ -4026,12 +4598,12 @@ compare-func@^2.0.0:
 computed-style@~0.1.3:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/computed-style/-/computed-style-0.1.4.tgz#7f344fd8584b2e425bedca4a1afc0e300bb05d74"
-  integrity sha1-fzRP2FhLLkJb7cpKGvwOMAuwXXQ=
+  integrity sha512-WpAmaKbMNmS3OProfHIdJiNleNJdgUrJfbKArXua28QF7+0CoZjlLn0lp6vlc+dl5r2/X9GQiQRQQU4BzSa69w==
 
 concat-map@0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
-  integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
+  integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
 
 concat-stream@^1.5.2:
   version "1.6.2"
@@ -4043,19 +4615,7 @@ concat-stream@^1.5.2:
     readable-stream "^2.2.2"
     typedarray "^0.0.6"
 
-configstore@^5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96"
-  integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==
-  dependencies:
-    dot-prop "^5.2.0"
-    graceful-fs "^4.1.2"
-    make-dir "^3.0.0"
-    unique-string "^2.0.0"
-    write-file-atomic "^3.0.0"
-    xdg-basedir "^4.0.0"
-
-connect-typeorm@^1.1.4:
+connect-typeorm@1.1.4:
   version "1.1.4"
   resolved "https://registry.yarnpkg.com/connect-typeorm/-/connect-typeorm-1.1.4.tgz#80f4e60dc4eeb6c04de334c30bf3e4bb766a34e5"
   integrity sha512-1/0b1aFzip0UBzuaSUkVZE4EW3n4UZzi3x2fmKeCaOb+sB4VZGj79txzLvtWIHLYY6kls/PKNcQHfEurdEjsUw==
@@ -4065,10 +4625,10 @@ connect-typeorm@^1.1.4:
     debug "^4.1.1"
     express-session "^1.15.6"
 
-console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control-strings@~1.1.0:
+console-control-strings@^1.0.0, console-control-strings@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
-  integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
+  integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==
 
 consolidate@^0.16.0:
   version "0.16.0"
@@ -4105,10 +4665,10 @@ conventional-changelog-angular@^5.0.0, conventional-changelog-angular@^5.0.11:
     compare-func "^2.0.0"
     q "^1.5.1"
 
-conventional-changelog-conventionalcommits@^4.3.1:
-  version "4.6.3"
-  resolved "https://registry.yarnpkg.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.3.tgz#0765490f56424b46f6cb4db9135902d6e5a36dc2"
-  integrity sha512-LTTQV4fwOM4oLPad317V/QNQ1FY4Hju5qeBIM1uTHbrnCE+Eg4CdRZ3gO2pUeR+tzWdp80M2j3qFFEDWVqOV4g==
+conventional-changelog-conventionalcommits@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-5.0.0.tgz#41bdce54eb65a848a4a3ffdca93e92fa22b64a86"
+  integrity sha512-lCDbA+ZqVFQGUj7h9QBKoIpLhl8iihkO0nCTyRNzuXtcd7ubODpYB04IFy31JloiJgG0Uovu8ot8oxRzn7Nwtw==
   dependencies:
     compare-func "^2.0.0"
     lodash "^4.17.15"
@@ -4161,7 +4721,7 @@ convert-source-map@^1.1.0, convert-source-map@^1.5.0, convert-source-map@^1.7.0:
   dependencies:
     safe-buffer "~5.1.1"
 
-cookie-parser@^1.4.6:
+cookie-parser@1.4.6:
   version "1.4.6"
   resolved "https://registry.yarnpkg.com/cookie-parser/-/cookie-parser-1.4.6.tgz#3ac3a7d35a7a03bbc7e365073a26074824214594"
   integrity sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==
@@ -4172,7 +4732,7 @@ cookie-parser@^1.4.6:
 cookie-signature@1.0.6:
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
-  integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
+  integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
 
 cookie@0.4.0:
   version "0.4.0"
@@ -4189,6 +4749,18 @@ cookie@0.4.2:
   resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432"
   integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==
 
+cookie@0.5.0:
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
+  integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
+
+copy-to-clipboard@3.3.2:
+  version "3.3.2"
+  resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.2.tgz#5b263ec2366224b100181dded7ce0579b340c107"
+  integrity sha512-Vme1Z6RUDzrb6xAI7EZlVZ5uvOk2F//GaxKUxajDqm9LhOVM1inxNAD2vy+UZDYsd0uyA9s7b3/FVZPSxqrCfg==
+  dependencies:
+    toggle-selection "^1.0.6"
+
 copy-to-clipboard@^3.3.1:
   version "3.3.1"
   resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz#115aa1a9998ffab6196f93076ad6da3b913662ae"
@@ -4196,7 +4768,7 @@ copy-to-clipboard@^3.3.1:
   dependencies:
     toggle-selection "^1.0.6"
 
-copyfiles@^2.4.1:
+copyfiles@2.4.1:
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-2.4.1.tgz#d2dcff60aaad1015f09d0b66e7f0f1c5cd3c5da5"
   integrity sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==
@@ -4209,36 +4781,36 @@ copyfiles@^2.4.1:
     untildify "^4.0.0"
     yargs "^16.1.0"
 
-core-js-compat@^3.20.2, core-js-compat@^3.21.0:
-  version "3.21.1"
-  resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.21.1.tgz#cac369f67c8d134ff8f9bd1623e3bc2c42068c82"
-  integrity sha512-gbgX5AUvMb8gwxC7FLVWYT7Kkgu/y7+h/h1X43yJkNqhlK2fuYyQimqvKGNZFAY6CKii/GFKJ2cp/1/42TN36g==
+core-js-compat@^3.21.0, core-js-compat@^3.22.1:
+  version "3.22.7"
+  resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.22.7.tgz#8359eb66ecbf726dd0cfced8e48d5e73f3224239"
+  integrity sha512-uI9DAQKKiiE/mclIC5g4AjRpio27g+VMRhe6rQoz+q4Wm4L6A/fJhiLtBw+sfOpDG9wZ3O0pxIw7GbfOlBgjOA==
   dependencies:
-    browserslist "^4.19.1"
+    browserslist "^4.20.3"
     semver "7.0.0"
 
 core-js-pure@^3.20.2:
-  version "3.21.1"
-  resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.21.1.tgz#8c4d1e78839f5f46208de7230cebfb72bc3bdb51"
-  integrity sha512-12VZfFIu+wyVbBebyHmRTuEE/tZrB4tJToWcwAMcsp3h4+sHR+fMJWbKpYiCRWlhFBq+KNyO8rIV9rTkeVmznQ==
+  version "3.22.7"
+  resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.22.7.tgz#f58489d9b309fa7b26486a0f70d4ec19a418084e"
+  integrity sha512-wTriFxiZI+C8msGeh7fJcbC/a0V8fdInN1oS2eK79DMBGs8iIJiXhtFJCiT3rBa8w6zroHWW3p8ArlujZ/Mz+w==
 
 core-util-is@1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
-  integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
+  integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==
 
 core-util-is@~1.0.0:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
   integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
 
-cosmiconfig-typescript-loader@^1.0.0:
-  version "1.0.6"
-  resolved "https://registry.yarnpkg.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-1.0.6.tgz#6d879cece8063b15ec8a3258f55a8e94893c7cca"
-  integrity sha512-2nEotziYJWtNtoTjKbchj9QrdTT6DBxCvqjNKoDKARw+e2yZmTQCa07uRrykLIZuvSgp69YXLH89UHc0WhdMfQ==
+cosmiconfig-typescript-loader@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-2.0.1.tgz#5622bb1eb87d293570bcc3a57f406940e0960113"
+  integrity sha512-B9s6sX/omXq7I6gC6+YgLmrBFMJhPWew7ty/X5Tuwtd2zOSgWaUdXjkuVwbe3qqcdETo60+1nSVMekq//LIXVA==
   dependencies:
     cosmiconfig "^7"
-    ts-node "^10.6.0"
+    ts-node "^10.8.0"
 
 cosmiconfig@^6.0.0:
   version "6.0.0"
@@ -4262,10 +4834,10 @@ cosmiconfig@^7, cosmiconfig@^7.0.0, cosmiconfig@^7.0.1:
     path-type "^4.0.0"
     yaml "^1.10.0"
 
-country-flag-icons@^1.4.21:
-  version "1.4.21"
-  resolved "https://registry.yarnpkg.com/country-flag-icons/-/country-flag-icons-1.4.21.tgz#0c00f57894890f5f41c8b632bcf5293cce80af02"
-  integrity sha512-bA9jDr+T5li7EsKdDx0xVnO0bdMdoT8IA3BNbeT2XSWUygR1okhiZ2+eYiC1EKLrFZhI4aEHni2w03lUlOjogg==
+country-flag-icons@1.5.5:
+  version "1.5.5"
+  resolved "https://registry.yarnpkg.com/country-flag-icons/-/country-flag-icons-1.5.5.tgz#04a41c83e2ea38ea28054d4e3eff9d1ce16aec1c"
+  integrity sha512-k4WXZ/WvWOSiYXRG1n8EYHNr1m/IX0GffKqAidaet5DrJsDOmJ8Q/8JvvONhZNnKYg24s4lvsm+9og1HcuIU/g==
 
 create-require@^1.1.0:
   version "1.1.1"
@@ -4280,7 +4852,12 @@ cron-parser@^3.5.0:
     is-nan "^1.3.2"
     luxon "^1.26.0"
 
-cross-spawn@^7.0.2, cross-spawn@^7.0.3:
+cronstrue@2.11.0:
+  version "2.11.0"
+  resolved "https://registry.yarnpkg.com/cronstrue/-/cronstrue-2.11.0.tgz#18ff1b95a836b9b4e06854f796db2dc8fa98ce41"
+  integrity sha512-iIBCSis5yqtFYWtJAmNOiwDveFWWIn+8uV5UYuPHYu/Aeu5CSSJepSbaHMyfc+pPFgnsCcGzfPQEo7LSGmWbTg==
+
+cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
   version "7.0.3"
   resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
   integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
@@ -4304,16 +4881,27 @@ csrf@3.1.0:
     uid-safe "2.1.5"
 
 css-select@^4.1.3:
-  version "4.2.1"
-  resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.2.1.tgz#9e665d6ae4c7f9d65dbe69d0316e3221fb274cdd"
-  integrity sha512-/aUslKhzkTNCQUB2qTX84lVmfia9NyjP3WpDGtj/WxhwBzWBYUV3DgUpurHTme8UTPcPlAD1DJ+b0nN/t50zDQ==
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b"
+  integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==
   dependencies:
     boolbase "^1.0.0"
-    css-what "^5.1.0"
-    domhandler "^4.3.0"
+    css-what "^6.0.1"
+    domhandler "^4.3.1"
     domutils "^2.8.0"
     nth-check "^2.0.1"
 
+css-select@^5.1.0:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6"
+  integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==
+  dependencies:
+    boolbase "^1.0.0"
+    css-what "^6.1.0"
+    domhandler "^5.0.2"
+    domutils "^3.0.1"
+    nth-check "^2.0.1"
+
 css-tree@^1.1.2, css-tree@^1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d"
@@ -4322,10 +4910,10 @@ css-tree@^1.1.2, css-tree@^1.1.3:
     mdn-data "2.0.14"
     source-map "^0.6.1"
 
-css-what@^5.0.1, css-what@^5.1.0:
-  version "5.1.0"
-  resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe"
-  integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==
+css-what@^6.0.1, css-what@^6.1.0:
+  version "6.1.0"
+  resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4"
+  integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==
 
 cssesc@^3.0.0:
   version "3.0.0"
@@ -4345,11 +4933,11 @@ csstype@^2.5.7:
   integrity sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==
 
 csstype@^3.0.2:
-  version "3.0.11"
-  resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.11.tgz#d66700c5eacfac1940deb4e3ee5642792d85cd33"
-  integrity sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2"
+  integrity sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==
 
-csurf@^1.11.0:
+csurf@1.11.0:
   version "1.11.0"
   resolved "https://registry.yarnpkg.com/csurf/-/csurf-1.11.0.tgz#ab0c3c6634634192bd3d6f4b861be20800eeb61a"
   integrity sha512-UCtehyEExKTxgiu8UHdGvHj4tnpE/Qctue03Giq5gPgMQ9cg/ciod5blZQ5a4uCEenNQjxyGuzygLdKUmee/bQ==
@@ -4359,6 +4947,59 @@ csurf@^1.11.0:
     csrf "3.1.0"
     http-errors "~1.7.3"
 
+cy-mobile-commands@0.3.0:
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/cy-mobile-commands/-/cy-mobile-commands-0.3.0.tgz#2bf242093149154d846b755977da197b4730429e"
+  integrity sha512-Bj5P2ylw88hPqolLu68xWB6euVH5uNt8zyh+Ju8sBukGv39mWZxpjp6LtnUX/LK/YMthwvILYHhvr9SG1TP+4w==
+
+cypress@10.6.0:
+  version "10.6.0"
+  resolved "https://registry.yarnpkg.com/cypress/-/cypress-10.6.0.tgz#13f46867febf2c3715874ed5dce9c2e946b175fe"
+  integrity sha512-6sOpHjostp8gcLO34p6r/Ci342lBs8S5z9/eb3ZCQ22w2cIhMWGUoGKkosabPBfKcvRS9BE4UxybBtlIs8gTQA==
+  dependencies:
+    "@cypress/request" "^2.88.10"
+    "@cypress/xvfb" "^1.2.4"
+    "@types/node" "^14.14.31"
+    "@types/sinonjs__fake-timers" "8.1.1"
+    "@types/sizzle" "^2.3.2"
+    arch "^2.2.0"
+    blob-util "^2.0.2"
+    bluebird "^3.7.2"
+    buffer "^5.6.0"
+    cachedir "^2.3.0"
+    chalk "^4.1.0"
+    check-more-types "^2.24.0"
+    cli-cursor "^3.1.0"
+    cli-table3 "~0.6.1"
+    commander "^5.1.0"
+    common-tags "^1.8.0"
+    dayjs "^1.10.4"
+    debug "^4.3.2"
+    enquirer "^2.3.6"
+    eventemitter2 "^6.4.3"
+    execa "4.1.0"
+    executable "^4.1.1"
+    extract-zip "2.0.1"
+    figures "^3.2.0"
+    fs-extra "^9.1.0"
+    getos "^3.2.1"
+    is-ci "^3.0.0"
+    is-installed-globally "~0.4.0"
+    lazy-ass "^1.6.0"
+    listr2 "^3.8.3"
+    lodash "^4.17.21"
+    log-symbols "^4.0.0"
+    minimist "^1.2.6"
+    ospath "^1.2.2"
+    pretty-bytes "^5.6.0"
+    proxy-from-env "1.0.0"
+    request-progress "^3.0.0"
+    semver "^7.3.2"
+    supports-color "^8.1.1"
+    tmp "~0.2.1"
+    untildify "^4.0.0"
+    yauzl "^2.10.0"
+
 cz-conventional-changelog@3.2.0:
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/cz-conventional-changelog/-/cz-conventional-changelog-3.2.0.tgz#6aef1f892d64113343d7e455529089ac9f20e477"
@@ -4373,7 +5014,7 @@ cz-conventional-changelog@3.2.0:
   optionalDependencies:
     "@commitlint/load" ">6.1.1"
 
-cz-conventional-changelog@^3.3.0:
+cz-conventional-changelog@3.3.0:
   version "3.3.0"
   resolved "https://registry.yarnpkg.com/cz-conventional-changelog/-/cz-conventional-changelog-3.3.0.tgz#9246947c90404149b3fe2cf7ee91acad3b7d22d2"
   integrity sha512-U466fIzU5U22eES5lTNiNbZ+d8dfcHcssH4o7QsdWaCcRs/feIPCxKYSWkYBNs5mny7MvEfwpTLWjvbm94hecw==
@@ -4387,7 +5028,7 @@ cz-conventional-changelog@^3.3.0:
   optionalDependencies:
     "@commitlint/load" ">6.1.1"
 
-damerau-levenshtein@^1.0.7:
+damerau-levenshtein@^1.0.7, damerau-levenshtein@^1.0.8:
   version "1.0.8"
   resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
   integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==
@@ -4400,19 +5041,34 @@ dargs@^7.0.0:
 dashdash@^1.12.0:
   version "1.14.1"
   resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
-  integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
+  integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==
   dependencies:
     assert-plus "^1.0.0"
 
+date-fns@2.29.1:
+  version "2.29.1"
+  resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.1.tgz#9667c2615525e552b5135a3116b95b1961456e60"
+  integrity sha512-dlLD5rKaKxpFdnjrs+5azHDFOPEu4ANy/LTh04A1DTzMM7qoajmKCBc8pkKRFT41CNzw+4gQh79X5C+Jq27HAw==
+
+date-fns@^2.28.0:
+  version "2.28.0"
+  resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.28.0.tgz#9570d656f5fc13143e50c975a3b6bbeb46cd08b2"
+  integrity sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==
+
 dateformat@^3.0.0:
   version "3.0.3"
   resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae"
   integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==
 
+dayjs@^1.10.4:
+  version "1.11.5"
+  resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.5.tgz#00e8cc627f231f9499c19b38af49f56dc0ac5e93"
+  integrity sha512-CAdX5Q3YW3Gclyo5Vpqkgpj8fSdLQcRuzfX6mC6Phy0nfJ0eGYOeS7m4mt2plDWLAtA4TqTakvbboHvUxfe4iA==
+
 dayjs@^1.10.6:
-  version "1.10.8"
-  resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.8.tgz#267df4bc6276fcb33c04a6735287e3f429abec41"
-  integrity sha512-wbNwDfBHHur9UOzNUjeKUOJ0fCb0a52Wx0xInmQ7Y8FstyajiV1NmK1e00cxsr9YrE9r7yAChE0VvpuY5Rnlow==
+  version "1.11.2"
+  resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.2.tgz#fa0f5223ef0d6724b3d8327134890cfe3d72fbe5"
+  integrity sha512-F4LXf1OeU9hrSYRPTTj/6FbO4HTjPKXvEIC1P2kcnFurViINCVk3ZV0xAS3XVx9MkMsXbbqlK6hjseaYbgKEHw==
 
 debug@2.6.9, debug@^2.6.9:
   version "2.6.9"
@@ -4421,14 +5077,14 @@ debug@2.6.9, debug@^2.6.9:
   dependencies:
     ms "2.0.0"
 
-debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3:
-  version "4.3.3"
-  resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664"
-  integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==
+debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4:
+  version "4.3.4"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
+  integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
   dependencies:
     ms "2.1.2"
 
-debug@^3.2.6, debug@^3.2.7:
+debug@^3.1.0, debug@^3.2.7:
   version "3.2.7"
   resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
   integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
@@ -4438,12 +5094,12 @@ debug@^3.2.6, debug@^3.2.7:
 debuglog@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
-  integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=
+  integrity sha512-syBZ+rnAK3EgMsH2aYEOLUW7mZSY9Gb+0wUMCFsZvcmiz+HigA0LOcq/HoQqVuGG+EKykunc7QG2bzrponfaSw==
 
 decamelize-keys@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9"
-  integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=
+  integrity sha512-ocLWuYzRPoS9bfiSdDd3cxvrzovVMZnRDVEzAs+hWIVXGDbHxWMECij2OBuyB/An0FFW/nLuq6Kv1i/YC5Qfzg==
   dependencies:
     decamelize "^1.1.0"
     map-obj "^1.0.0"
@@ -4451,7 +5107,7 @@ decamelize-keys@^1.1.0:
 decamelize@^1.1.0, decamelize@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
-  integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
+  integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==
 
 decode-named-character-reference@^1.0.0:
   version "1.0.1"
@@ -4460,17 +5116,10 @@ decode-named-character-reference@^1.0.0:
   dependencies:
     character-entities "^2.0.0"
 
-decompress-response@^3.3.0:
-  version "3.3.0"
-  resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3"
-  integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=
-  dependencies:
-    mimic-response "^1.0.0"
-
 dedent@0.7.0:
   version "0.7.0"
   resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
-  integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=
+  integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==
 
 deep-extend@^0.6.0:
   version "0.6.0"
@@ -4495,31 +5144,27 @@ deepmerge@^4.2.2:
 defaults@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
-  integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=
+  integrity sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==
   dependencies:
     clone "^1.0.2"
 
-defer-to-connect@^1.0.1:
-  version "1.1.3"
-  resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
-  integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==
-
-define-properties@^1.1.3:
-  version "1.1.3"
-  resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
-  integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
+define-properties@^1.1.3, define-properties@^1.1.4:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1"
+  integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==
   dependencies:
-    object-keys "^1.0.12"
+    has-property-descriptors "^1.0.0"
+    object-keys "^1.1.1"
 
 defined@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
-  integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=
+  integrity sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==
 
 del@^6.0.0:
-  version "6.0.0"
-  resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952"
-  integrity sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ==
+  version "6.1.1"
+  resolved "https://registry.yarnpkg.com/del/-/del-6.1.1.tgz#3b70314f1ec0aa325c6b14eb36b95786671edb7a"
+  integrity sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==
   dependencies:
     globby "^11.0.1"
     graceful-fs "^4.2.4"
@@ -4533,23 +5178,23 @@ del@^6.0.0:
 delayed-stream@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
-  integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
+  integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
 
 delegates@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
-  integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
-
-depd@^1.1.2, depd@~1.1.2:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
-  integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
+  integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==
 
-depd@~2.0.0:
+depd@2.0.0, depd@~2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
   integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
 
+depd@^1.1.2, depd@~1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
+  integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==
+
 deprecation@^2.0.0, deprecation@^2.3.1:
   version "2.3.1"
   resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919"
@@ -4560,56 +5205,48 @@ dequal@^2.0.0:
   resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.2.tgz#85ca22025e3a87e65ef75a7a437b35284a7e319d"
   integrity sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug==
 
-destroy@~1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
-  integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
+destroy@1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
+  integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
 
 detect-file@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
-  integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
+  integrity sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==
 
 detect-indent@6.0.0:
   version "6.0.0"
   resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.0.0.tgz#0abd0f549f69fc6659a254fe96786186b6f528fd"
   integrity sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==
 
-detect-indent@^6.0.0:
+detect-indent@6.1.0, detect-indent@^6.0.0:
   version "6.1.0"
   resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6"
   integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==
 
-detect-libc@^1.0.2, detect-libc@^1.0.3:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
-  integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
+detect-libc@^2.0.0:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd"
+  integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==
 
-detective@^5.2.0:
-  version "5.2.0"
-  resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.0.tgz#feb2a77e85b904ecdea459ad897cc90a99bd2a7b"
-  integrity sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==
+detective@^5.2.1:
+  version "5.2.1"
+  resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.1.tgz#6af01eeda11015acb0e73f933242b70f24f91034"
+  integrity sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==
   dependencies:
-    acorn-node "^1.6.1"
+    acorn-node "^1.8.2"
     defined "^1.0.0"
-    minimist "^1.1.1"
+    minimist "^1.2.6"
 
 dezalgo@^1.0.0:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456"
-  integrity sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81"
+  integrity sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==
   dependencies:
     asap "^2.0.0"
     wrappy "1"
 
-dicer@0.2.5:
-  version "0.2.5"
-  resolved "https://registry.yarnpkg.com/dicer/-/dicer-0.2.5.tgz#5996c086bb33218c812c090bddc09cd12facb70f"
-  integrity sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=
-  dependencies:
-    readable-stream "1.1.x"
-    streamsearch "0.1.2"
-
 didyoumean@^1.2.2:
   version "1.2.2"
   resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
@@ -4626,9 +5263,9 @@ diff@^4.0.1:
   integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
 
 diff@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b"
-  integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40"
+  integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==
 
 dir-glob@^3.0.0, dir-glob@^3.0.1:
   version "3.0.1"
@@ -4640,7 +5277,7 @@ dir-glob@^3.0.0, dir-glob@^3.0.1:
 discontinuous-range@1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/discontinuous-range/-/discontinuous-range-1.0.0.tgz#e38331f0844bba49b9a9cb71c771585aab1bc65a"
-  integrity sha1-44Mx8IRLukm5qctxx3FYWqsbxlo=
+  integrity sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==
 
 dlv@^1.1.3:
   version "1.1.3"
@@ -4664,7 +5301,7 @@ doctrine@^3.0.0:
 doctypes@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9"
-  integrity sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=
+  integrity sha512-LLBi6pEqS6Do3EKQ3J0NqHWV5hhb78Pi8vvESYwyOy2c31ZEZVdtitdzsQsKb7878PEERhzUk0ftqGhG6Mz+pQ==
 
 dom-helpers@^5.0.1:
   version "5.2.1"
@@ -4674,19 +5311,28 @@ dom-helpers@^5.0.1:
     "@babel/runtime" "^7.8.7"
     csstype "^3.0.2"
 
-dom-serializer@^1.0.1, dom-serializer@^1.3.2:
-  version "1.3.2"
-  resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91"
-  integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==
+dom-serializer@^1.0.1:
+  version "1.4.1"
+  resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30"
+  integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==
   dependencies:
     domelementtype "^2.0.1"
     domhandler "^4.2.0"
     entities "^2.0.0"
 
-domelementtype@^2.0.1, domelementtype@^2.2.0:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57"
-  integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==
+dom-serializer@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53"
+  integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==
+  dependencies:
+    domelementtype "^2.3.0"
+    domhandler "^5.0.2"
+    entities "^4.2.0"
+
+domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d"
+  integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==
 
 domhandler@^3.0.0:
   version "3.3.0"
@@ -4695,14 +5341,21 @@ domhandler@^3.0.0:
   dependencies:
     domelementtype "^2.0.1"
 
-domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.0:
-  version "4.3.0"
-  resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.0.tgz#16c658c626cf966967e306f966b431f77d4a5626"
-  integrity sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==
+domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1:
+  version "4.3.1"
+  resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c"
+  integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==
   dependencies:
     domelementtype "^2.2.0"
 
-domutils@^2.0.0, domutils@^2.5.2, domutils@^2.7.0, domutils@^2.8.0:
+domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3:
+  version "5.0.3"
+  resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31"
+  integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==
+  dependencies:
+    domelementtype "^2.3.0"
+
+domutils@^2.0.0, domutils@^2.5.2, domutils@^2.8.0:
   version "2.8.0"
   resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135"
   integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==
@@ -4711,30 +5364,34 @@ domutils@^2.0.0, domutils@^2.5.2, domutils@^2.7.0, domutils@^2.8.0:
     domelementtype "^2.2.0"
     domhandler "^4.2.0"
 
-dot-prop@^5.1.0, dot-prop@^5.2.0:
+domutils@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.0.1.tgz#696b3875238338cb186b6c0612bd4901c89a4f1c"
+  integrity sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==
+  dependencies:
+    dom-serializer "^2.0.0"
+    domelementtype "^2.3.0"
+    domhandler "^5.0.1"
+
+dot-prop@^5.1.0:
   version "5.3.0"
   resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88"
   integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==
   dependencies:
     is-obj "^2.0.0"
 
-dotenv@^8.2.0:
-  version "8.6.0"
-  resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.6.0.tgz#061af664d19f7f4d8fc6e4ff9b584ce237adcb8b"
-  integrity sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==
+dotenv@^16.0.0:
+  version "16.0.1"
+  resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.1.tgz#8f8f9d94876c35dac989876a5d3a82a267fdce1d"
+  integrity sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==
 
 duplexer2@~0.1.0:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
-  integrity sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=
+  integrity sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==
   dependencies:
     readable-stream "^2.0.2"
 
-duplexer3@^0.1.4:
-  version "0.1.4"
-  resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
-  integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=
-
 eastasianwidth@^0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
@@ -4743,7 +5400,7 @@ eastasianwidth@^0.2.0:
 ecc-jsbn@~0.1.1:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
-  integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
+  integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==
   dependencies:
     jsbn "~0.1.0"
     safer-buffer "^2.1.0"
@@ -4758,32 +5415,37 @@ ecdsa-sig-formatter@1.0.11:
 ee-first@1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
-  integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=
+  integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
+
+electron-to-chromium@^1.4.118:
+  version "1.4.141"
+  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.141.tgz#4dd9119e8a99f1c83c51dfcf1bed79ea541f08d6"
+  integrity sha512-mfBcbqc0qc6RlxrsIgLG2wCqkiPAjEezHxGTu7p3dHHFOurH4EjS9rFZndX5axC8264rI1Pcbw8uQP39oZckeA==
 
-electron-to-chromium@^1.4.76:
-  version "1.4.82"
-  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.82.tgz#51e123ca434b1eba8c434ece2b54f095b304a651"
-  integrity sha512-Ks+ANzLoIrFDUOJdjxYMH6CMKB8UQo5modAwvSZTxgF+vEs/U7G5IbWFUp6dS4klPkTDVdxbORuk8xAXXhMsWw==
+electron-to-chromium@^1.4.202:
+  version "1.4.224"
+  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.224.tgz#ecf2eed395cfedcbbe634658ccc4b457f7b254c3"
+  integrity sha512-dOujC5Yzj0nOVE23iD5HKqrRSDj2SD7RazpZS/b/WX85MtO6/LzKDF4TlYZTBteB+7fvSg5JpWh0sN7fImNF8w==
 
-email-templates@^8.0.10:
-  version "8.0.10"
-  resolved "https://registry.yarnpkg.com/email-templates/-/email-templates-8.0.10.tgz#eb9321aecca1fa960727888aaced375ceaff9394"
-  integrity sha512-wwV++lBZ6asfMioer48fw85EqfgP2xc+fMtFedCsb70uIQb9nYObWhcZVj3wcaLl03xVliXVJpkIsRXtJ3pa1A==
+email-templates@9.0.0:
+  version "9.0.0"
+  resolved "https://registry.yarnpkg.com/email-templates/-/email-templates-9.0.0.tgz#b23f2b24eb8deb21984c845382934bf387ea1ab5"
+  integrity sha512-ap0p38jAq8FMy86Jp2b3hyCFDUA9utWfOuyKPWhrknmHrrT3n94viGcQIAsaQtUZGaJP/0dJ9w//XqvaZV/yYQ==
   dependencies:
     "@ladjs/i18n" "^7.2.6"
     consolidate "^0.16.0"
-    debug "^4.3.3"
+    debug "^4.3.4"
     get-paths "^0.0.7"
-    html-to-text "^6.0.0"
-    juice "^7.0.0"
+    html-to-text "^8.1.0"
+    juice "^8.0.0"
     lodash "^4.17.21"
     nodemailer "^6.7.2"
     preview-email "^3.0.5"
 
 emoji-regex@^10.0.0:
-  version "10.0.1"
-  resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.0.1.tgz#77180edb279b99510a21b79b19e1dc283d8f3991"
-  integrity sha512-cLuZzriSWVE+rllzeq4zpUEoCPfYEbQ6ZVhIq+ed6ynWST7Bw9XnOr+bKWgCup4paq72DI21gw9M3aaFkm4HAw==
+  version "10.1.0"
+  resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.1.0.tgz#d50e383743c0f7a5945c47087295afc112e3cf66"
+  integrity sha512-xAEnNCT3w2Tg6MA7ly6QqYJvEoY1tm9iIjJ3yMKK9JPlWuRHAMoe5iETwQnx3M9TVbFMfsrBgWKR+IsmswwNjg==
 
 emoji-regex@^8.0.0:
   version "8.0.0"
@@ -4795,6 +5457,11 @@ emoji-regex@^9.2.2:
   resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
   integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
 
+emojis-list@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
+  integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
+
 enabled@2.0.x:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/enabled/-/enabled-2.0.0.tgz#f9dd92ec2d6f4bbc0d5d1e64e21d61cd4665e7c2"
@@ -4803,12 +5470,12 @@ enabled@2.0.x:
 encodeurl@~1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
-  integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
+  integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
 
-encoding-japanese@1.0.30:
-  version "1.0.30"
-  resolved "https://registry.yarnpkg.com/encoding-japanese/-/encoding-japanese-1.0.30.tgz#537c4d62881767925d601acb4c79fb14db81703a"
-  integrity sha512-bd/DFLAoJetvv7ar/KIpE3CNO8wEuyrt9Xuw6nSMiZ+Vrz/Q21BPsMHvARL2Wz6IKHKXgb+DWZqtRg1vql9cBg==
+encoding-japanese@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/encoding-japanese/-/encoding-japanese-2.0.0.tgz#fa0226e5469e7b5b69a04fea7d5481bd1fa56936"
+  integrity sha512-++P0RhebUC8MJAwJOsT93dT+5oc5oPImp1HubZpAuCZ5kTLnhuuBhKHj2jJeO/Gj93idPBWmIuQ9QWMe5rX3pQ==
 
 encoding@^0.1.12, encoding@^0.1.13:
   version "0.1.13"
@@ -4824,15 +5491,22 @@ end-of-stream@^1.1.0:
   dependencies:
     once "^1.4.0"
 
+enquirer@^2.3.6:
+  version "2.3.6"
+  resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
+  integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==
+  dependencies:
+    ansi-colors "^4.1.1"
+
 entities@^2.0.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
   integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
 
-entities@^3.0.1:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/entities/-/entities-3.0.1.tgz#2b887ca62585e96db3903482d336c1006c3001d4"
-  integrity sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==
+entities@^4.2.0, entities@^4.3.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/entities/-/entities-4.3.0.tgz#62915f08d67353bb4eb67e3d62641a4059aec656"
+  integrity sha512-/iP1rZrSEJ0DTlPiX+jbzlA3eVkY/e8L8SozroF395fIqE3TYF/Nz7YOMAawta+vLmyJ/hkGNNPcSbMADCCXbg==
 
 env-ci@^5.0.0:
   version "5.5.0"
@@ -4860,31 +5534,41 @@ error-ex@^1.3.1:
   dependencies:
     is-arrayish "^0.2.1"
 
-es-abstract@^1.19.0, es-abstract@^1.19.1:
-  version "1.19.1"
-  resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3"
-  integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==
+es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5:
+  version "1.20.1"
+  resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814"
+  integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==
   dependencies:
     call-bind "^1.0.2"
     es-to-primitive "^1.2.1"
     function-bind "^1.1.1"
+    function.prototype.name "^1.1.5"
     get-intrinsic "^1.1.1"
     get-symbol-description "^1.0.0"
     has "^1.0.3"
-    has-symbols "^1.0.2"
+    has-property-descriptors "^1.0.0"
+    has-symbols "^1.0.3"
     internal-slot "^1.0.3"
     is-callable "^1.2.4"
-    is-negative-zero "^2.0.1"
+    is-negative-zero "^2.0.2"
     is-regex "^1.1.4"
-    is-shared-array-buffer "^1.0.1"
+    is-shared-array-buffer "^1.0.2"
     is-string "^1.0.7"
-    is-weakref "^1.0.1"
-    object-inspect "^1.11.0"
+    is-weakref "^1.0.2"
+    object-inspect "^1.12.0"
     object-keys "^1.1.1"
     object.assign "^4.1.2"
-    string.prototype.trimend "^1.0.4"
-    string.prototype.trimstart "^1.0.4"
-    unbox-primitive "^1.0.1"
+    regexp.prototype.flags "^1.4.3"
+    string.prototype.trimend "^1.0.5"
+    string.prototype.trimstart "^1.0.5"
+    unbox-primitive "^1.0.2"
+
+es-shim-unscopables@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241"
+  integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==
+  dependencies:
+    has "^1.0.3"
 
 es-to-primitive@^1.2.1:
   version "1.2.1"
@@ -4900,11 +5584,6 @@ escalade@^3.1.1:
   resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
   integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
 
-escape-goat@^2.0.0:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675"
-  integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==
-
 escape-goat@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-3.0.0.tgz#e8b5fb658553fe8a3c4959c316c6ebb8c842b19c"
@@ -4913,39 +5592,39 @@ escape-goat@^3.0.0:
 escape-html@~1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
-  integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
+  integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
 
 escape-string-regexp@^1.0.5:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
-  integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
+  integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
 
 escape-string-regexp@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
   integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
 
-eslint-config-next@^12.1.0:
-  version "12.1.0"
-  resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.1.0.tgz#8ace680dc5207e6ab6c915f3989adec122f582e7"
-  integrity sha512-tBhuUgoDITcdcM7xFvensi9I5WTI4dnvH4ETGRg1U8ZKpXrZsWQFdOKIDzR3RLP5HR3xXrLviaMM4c3zVoE/pA==
-  dependencies:
-    "@next/eslint-plugin-next" "12.1.0"
-    "@rushstack/eslint-patch" "^1.0.8"
-    "@typescript-eslint/parser" "^5.0.0"
-    eslint-import-resolver-node "^0.3.4"
-    eslint-import-resolver-typescript "^2.4.0"
-    eslint-plugin-import "^2.25.2"
+eslint-config-next@12.2.5:
+  version "12.2.5"
+  resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-12.2.5.tgz#76ce83f18cc02f6f42ed407a127f83db54fabd3c"
+  integrity sha512-SOowilkqPzW6DxKp3a3SYlrfPi5Ajs9MIzp9gVfUDxxH9QFM5ElkR1hX5m/iICJuvCbWgQqFBiA3mCMozluniw==
+  dependencies:
+    "@next/eslint-plugin-next" "12.2.5"
+    "@rushstack/eslint-patch" "^1.1.3"
+    "@typescript-eslint/parser" "^5.21.0"
+    eslint-import-resolver-node "^0.3.6"
+    eslint-import-resolver-typescript "^2.7.1"
+    eslint-plugin-import "^2.26.0"
     eslint-plugin-jsx-a11y "^6.5.1"
-    eslint-plugin-react "^7.27.0"
-    eslint-plugin-react-hooks "^4.3.0"
+    eslint-plugin-react "^7.29.4"
+    eslint-plugin-react-hooks "^4.5.0"
 
-eslint-config-prettier@^8.5.0:
+eslint-config-prettier@8.5.0:
   version "8.5.0"
   resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1"
   integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==
 
-eslint-import-resolver-node@^0.3.4, eslint-import-resolver-node@^0.3.6:
+eslint-import-resolver-node@^0.3.6:
   version "0.3.6"
   resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd"
   integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==
@@ -4953,18 +5632,18 @@ eslint-import-resolver-node@^0.3.4, eslint-import-resolver-node@^0.3.6:
     debug "^3.2.7"
     resolve "^1.20.0"
 
-eslint-import-resolver-typescript@^2.4.0:
-  version "2.5.0"
-  resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.5.0.tgz#07661966b272d14ba97f597b51e1a588f9722f0a"
-  integrity sha512-qZ6e5CFr+I7K4VVhQu3M/9xGv9/YmwsEXrsm3nimw8vWaVHRDrQRp26BgCypTxBp3vUp4o5aVEJRiy0F2DFddQ==
+eslint-import-resolver-typescript@^2.7.1:
+  version "2.7.1"
+  resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.7.1.tgz#a90a4a1c80da8d632df25994c4c5fdcdd02b8751"
+  integrity sha512-00UbgGwV8bSgUv34igBDbTOtKhqoRMy9bFjNehT40bXg6585PNIct8HhXZ0SybqB9rWtXj9crcku8ndDn/gIqQ==
   dependencies:
-    debug "^4.3.1"
-    glob "^7.1.7"
-    is-glob "^4.0.1"
-    resolve "^1.20.0"
-    tsconfig-paths "^3.9.0"
+    debug "^4.3.4"
+    glob "^7.2.0"
+    is-glob "^4.0.3"
+    resolve "^1.22.0"
+    tsconfig-paths "^3.14.1"
 
-eslint-module-utils@^2.7.2:
+eslint-module-utils@^2.7.3:
   version "2.7.3"
   resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz#ad7e3a10552fdd0642e1e55292781bd6e34876ee"
   integrity sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==
@@ -4972,37 +5651,58 @@ eslint-module-utils@^2.7.2:
     debug "^3.2.7"
     find-up "^2.1.0"
 
-eslint-plugin-formatjs@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-formatjs/-/eslint-plugin-formatjs-3.0.0.tgz#1864f82a90fa17b4c0e4f901f56bd81e35bdfa78"
-  integrity sha512-htZef5UkVG1I4MkleWXGYsQRrUo+2+iruxPRlqEMN4skrDNOZmp78/KPcaFGhQ1oaaI673y89gEgDZdq+chHsQ==
+eslint-plugin-formatjs@4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-formatjs/-/eslint-plugin-formatjs-4.1.0.tgz#3dfcd6c44037414229d1e071817fc0496f36e213"
+  integrity sha512-r8qCy5SDwsCcUUdP6ua1gYFd6I+tj/5GORj7jTOGGvmOfzkDQk+6ieaUqZ8ZF7xFUubDvLJwaZLHVdHI4Cq6Yw==
   dependencies:
-    "@formatjs/icu-messageformat-parser" "2.0.18"
-    "@formatjs/ts-transformer" "3.9.2"
-    "@types/eslint" "8"
+    "@formatjs/icu-messageformat-parser" "2.1.4"
+    "@formatjs/ts-transformer" "3.9.9"
+    "@types/eslint" "7 || 8"
+    "@types/picomatch" "^2.3.0"
     "@typescript-eslint/typescript-estree" "^5.9.1"
     emoji-regex "^10.0.0"
-    tslib "^2.1.0"
+    picomatch "^2.3.1"
+    tslib "2.4.0"
     typescript "^4.5"
 
-eslint-plugin-import@^2.25.2:
-  version "2.25.4"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.25.4.tgz#322f3f916a4e9e991ac7af32032c25ce313209f1"
-  integrity sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==
+eslint-plugin-import@^2.26.0:
+  version "2.26.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b"
+  integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==
   dependencies:
     array-includes "^3.1.4"
     array.prototype.flat "^1.2.5"
     debug "^2.6.9"
     doctrine "^2.1.0"
     eslint-import-resolver-node "^0.3.6"
-    eslint-module-utils "^2.7.2"
+    eslint-module-utils "^2.7.3"
     has "^1.0.3"
-    is-core-module "^2.8.0"
+    is-core-module "^2.8.1"
     is-glob "^4.0.3"
-    minimatch "^3.0.4"
+    minimatch "^3.1.2"
     object.values "^1.1.5"
-    resolve "^1.20.0"
-    tsconfig-paths "^3.12.0"
+    resolve "^1.22.0"
+    tsconfig-paths "^3.14.1"
+
+eslint-plugin-jsx-a11y@6.6.1:
+  version "6.6.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.6.1.tgz#93736fc91b83fdc38cc8d115deedfc3091aef1ff"
+  integrity sha512-sXgFVNHiWffBq23uiS/JaP6eVR622DqwB4yTzKvGZGcPq6/yZ3WmOZfuBks/vHWo9GaFOqC2ZK4i6+C35knx7Q==
+  dependencies:
+    "@babel/runtime" "^7.18.9"
+    aria-query "^4.2.2"
+    array-includes "^3.1.5"
+    ast-types-flow "^0.0.7"
+    axe-core "^4.4.3"
+    axobject-query "^2.2.0"
+    damerau-levenshtein "^1.0.8"
+    emoji-regex "^9.2.2"
+    has "^1.0.3"
+    jsx-ast-utils "^3.3.2"
+    language-tags "^1.0.5"
+    minimatch "^3.1.2"
+    semver "^6.3.0"
 
 eslint-plugin-jsx-a11y@^6.5.1:
   version "6.5.1"
@@ -5022,37 +5722,67 @@ eslint-plugin-jsx-a11y@^6.5.1:
     language-tags "^1.0.5"
     minimatch "^3.0.4"
 
-eslint-plugin-prettier@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz#8b99d1e4b8b24a762472b4567992023619cb98e0"
-  integrity sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==
+eslint-plugin-no-relative-import-paths@1.4.0:
+  version "1.4.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-no-relative-import-paths/-/eslint-plugin-no-relative-import-paths-1.4.0.tgz#59489ebc19688d1398bfe53d3ad320b3ed42ca17"
+  integrity sha512-J/ok26KqJM+20VsxNEcHc9kyW0dcFHBlihOO5FFv/GQqwcW+G1UngbHLpnPAdOQ1dJg5Ljk/40csqfZ3mnneUw==
+
+eslint-plugin-prettier@4.2.1:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b"
+  integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==
   dependencies:
     prettier-linter-helpers "^1.0.0"
 
-eslint-plugin-react-hooks@^4.3.0:
-  version "4.3.0"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.3.0.tgz#318dbf312e06fab1c835a4abef00121751ac1172"
-  integrity sha512-XslZy0LnMn+84NEG9jSGR6eGqaZB3133L8xewQo3fQagbQuGt7a63gf+P1NGKZavEYEC3UXaWEAA/AqDkuN6xA==
+eslint-plugin-react-hooks@4.6.0:
+  version "4.6.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3"
+  integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
 
-eslint-plugin-react@^7.27.0, eslint-plugin-react@^7.29.3:
-  version "7.29.3"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.29.3.tgz#f4eab757f2756d25d6d4c2a58a9e20b004791f05"
-  integrity sha512-MzW6TuCnDOcta67CkpDyRfRsEVx9FNMDV8wZsDqe1luHPdGTrQIUaUXD27Ja3gHsdOIs/cXzNchWGlqm+qRVRg==
+eslint-plugin-react-hooks@^4.5.0:
+  version "4.5.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.5.0.tgz#5f762dfedf8b2cf431c689f533c9d3fa5dcf25ad"
+  integrity sha512-8k1gRt7D7h03kd+SAAlzXkQwWK22BnK6GKZG+FJA6BAGy22CFvl8kCIXKpVux0cCxMWDQUPqSok0LKaZ0aOcCw==
+
+eslint-plugin-react@7.30.1:
+  version "7.30.1"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.30.1.tgz#2be4ab23ce09b5949c6631413ba64b2810fd3e22"
+  integrity sha512-NbEvI9jtqO46yJA3wcRF9Mo0lF9T/jhdHqhCHXiXtD+Zcb98812wvokjWpU7Q4QH5edo6dmqrukxVvWWXHlsUg==
   dependencies:
-    array-includes "^3.1.4"
-    array.prototype.flatmap "^1.2.5"
+    array-includes "^3.1.5"
+    array.prototype.flatmap "^1.3.0"
+    doctrine "^2.1.0"
+    estraverse "^5.3.0"
+    jsx-ast-utils "^2.4.1 || ^3.0.0"
+    minimatch "^3.1.2"
+    object.entries "^1.1.5"
+    object.fromentries "^2.0.5"
+    object.hasown "^1.1.1"
+    object.values "^1.1.5"
+    prop-types "^15.8.1"
+    resolve "^2.0.0-next.3"
+    semver "^6.3.0"
+    string.prototype.matchall "^4.0.7"
+
+eslint-plugin-react@^7.29.4:
+  version "7.30.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.30.0.tgz#8e7b1b2934b8426ac067a0febade1b13bd7064e3"
+  integrity sha512-RgwH7hjW48BleKsYyHK5vUAvxtE9SMPDKmcPRQgtRCYaZA0XQPt5FSkrU3nhz5ifzMZcA8opwmRJ2cmOO8tr5A==
+  dependencies:
+    array-includes "^3.1.5"
+    array.prototype.flatmap "^1.3.0"
     doctrine "^2.1.0"
     estraverse "^5.3.0"
     jsx-ast-utils "^2.4.1 || ^3.0.0"
     minimatch "^3.1.2"
     object.entries "^1.1.5"
     object.fromentries "^2.0.5"
-    object.hasown "^1.1.0"
+    object.hasown "^1.1.1"
     object.values "^1.1.5"
     prop-types "^15.8.1"
     resolve "^2.0.0-next.3"
     semver "^6.3.0"
-    string.prototype.matchall "^4.0.6"
+    string.prototype.matchall "^4.0.7"
 
 eslint-scope@^5.1.1:
   version "5.1.1"
@@ -5082,18 +5812,19 @@ eslint-visitor-keys@^2.0.0:
   resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
   integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
 
-eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0:
+eslint-visitor-keys@^3.3.0:
   version "3.3.0"
   resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
   integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
 
-eslint@^8.11.0:
-  version "8.11.0"
-  resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.11.0.tgz#88b91cfba1356fc10bb9eb592958457dfe09fb37"
-  integrity sha512-/KRpd9mIRg2raGxHRGwW9ZywYNAClZrHjdueHcrVDuO3a6bj83eoTirCCk0M0yPwOjWYKHwRVRid+xK4F/GHgA==
+eslint@8.22.0:
+  version "8.22.0"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.22.0.tgz#78fcb044196dfa7eef30a9d65944f6f980402c48"
+  integrity sha512-ci4t0sz6vSRKdmkOGmprBo6fmI4PrphDFMy5JEq/fNS0gQkJM3rLmrqcp8ipMcdobH3KtUP40KniAE9W19S4wA==
   dependencies:
-    "@eslint/eslintrc" "^1.2.1"
-    "@humanwhocodes/config-array" "^0.9.2"
+    "@eslint/eslintrc" "^1.3.0"
+    "@humanwhocodes/config-array" "^0.10.4"
+    "@humanwhocodes/gitignore-to-minimatch" "^1.0.2"
     ajv "^6.10.0"
     chalk "^4.0.0"
     cross-spawn "^7.0.2"
@@ -5103,14 +5834,17 @@ eslint@^8.11.0:
     eslint-scope "^7.1.1"
     eslint-utils "^3.0.0"
     eslint-visitor-keys "^3.3.0"
-    espree "^9.3.1"
+    espree "^9.3.3"
     esquery "^1.4.0"
     esutils "^2.0.2"
     fast-deep-equal "^3.1.3"
     file-entry-cache "^6.0.1"
+    find-up "^5.0.0"
     functional-red-black-tree "^1.0.1"
     glob-parent "^6.0.1"
-    globals "^13.6.0"
+    globals "^13.15.0"
+    globby "^11.1.0"
+    grapheme-splitter "^1.0.4"
     ignore "^5.2.0"
     import-fresh "^3.0.0"
     imurmurhash "^0.1.4"
@@ -5119,7 +5853,7 @@ eslint@^8.11.0:
     json-stable-stringify-without-jsonify "^1.0.1"
     levn "^0.4.1"
     lodash.merge "^4.6.2"
-    minimatch "^3.0.4"
+    minimatch "^3.1.2"
     natural-compare "^1.4.0"
     optionator "^0.9.1"
     regexpp "^3.2.0"
@@ -5128,13 +5862,22 @@ eslint@^8.11.0:
     text-table "^0.2.0"
     v8-compile-cache "^2.0.3"
 
-espree@^9.3.1:
-  version "9.3.1"
-  resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.1.tgz#8793b4bc27ea4c778c19908e0719e7b8f4115bcd"
-  integrity sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==
+espree@^9.3.2:
+  version "9.3.2"
+  resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.2.tgz#f58f77bd334731182801ced3380a8cc859091596"
+  integrity sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==
+  dependencies:
+    acorn "^8.7.1"
+    acorn-jsx "^5.3.2"
+    eslint-visitor-keys "^3.3.0"
+
+espree@^9.3.3:
+  version "9.3.3"
+  resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.3.tgz#2dd37c4162bb05f433ad3c1a52ddf8a49dc08e9d"
+  integrity sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==
   dependencies:
-    acorn "^8.7.0"
-    acorn-jsx "^5.3.1"
+    acorn "^8.8.0"
+    acorn-jsx "^5.3.2"
     eslint-visitor-keys "^3.3.0"
 
 esprima@^4.0.0, esprima@~4.0.0:
@@ -5174,7 +5917,27 @@ esutils@^2.0.2:
 etag@~1.8.1:
   version "1.8.1"
   resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
-  integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
+  integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
+
+eventemitter2@^6.4.3:
+  version "6.4.7"
+  resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.7.tgz#a7f6c4d7abf28a14c1ef3442f21cb306a054271d"
+  integrity sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==
+
+execa@4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a"
+  integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==
+  dependencies:
+    cross-spawn "^7.0.0"
+    get-stream "^5.0.0"
+    human-signals "^1.1.1"
+    is-stream "^2.0.0"
+    merge-stream "^2.0.0"
+    npm-run-path "^4.0.0"
+    onetime "^5.1.0"
+    signal-exit "^3.0.2"
+    strip-final-newline "^2.0.0"
 
 execa@^5.0.0, execa@^5.1.1:
   version "5.1.1"
@@ -5191,17 +5954,24 @@ execa@^5.0.0, execa@^5.1.1:
     signal-exit "^3.0.3"
     strip-final-newline "^2.0.0"
 
+executable@^4.1.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c"
+  integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==
+  dependencies:
+    pify "^2.2.0"
+
 expand-tilde@^2.0.0, expand-tilde@^2.0.2:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502"
-  integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=
+  integrity sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==
   dependencies:
     homedir-polyfill "^1.0.1"
 
-express-openapi-validator@^4.13.6:
-  version "4.13.6"
-  resolved "https://registry.yarnpkg.com/express-openapi-validator/-/express-openapi-validator-4.13.6.tgz#a0f5f6de2e0d271e216d66644daa894cdd5ddf09"
-  integrity sha512-KODX+SQgtCuSUOorJ3IpLNLpzoc1SUomYiSAZiWFfSFOaok7ndanUFI0WRS6MGjgEtQt4LC5BFHIeFx+a0CjSw==
+express-openapi-validator@4.13.8:
+  version "4.13.8"
+  resolved "https://registry.yarnpkg.com/express-openapi-validator/-/express-openapi-validator-4.13.8.tgz#805e0106b9f4afbb73ea28f42026e844dfa94dae"
+  integrity sha512-89/sdkq+BKBuIyykaMl/vR9grFc3WFUPTjFo0THHbu+5g+q8rA7fKeoMfz+h84yOQIBcztmJ5ZJdk5uhEls31A==
   dependencies:
     "@types/multer" "^1.4.7"
     ajv "^6.12.6"
@@ -5212,21 +5982,21 @@ express-openapi-validator@^4.13.6:
     lodash.uniq "^4.5.0"
     lodash.zipobject "^4.1.3"
     media-typer "^1.1.0"
-    multer "^1.4.4"
+    multer "^1.4.5-lts.1"
     ono "^7.1.3"
     path-to-regexp "^6.2.0"
 
-express-rate-limit@^6.3.0:
-  version "6.3.0"
-  resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-6.3.0.tgz#253387ce4d36c9c2cc77c7c676068deb36cc0821"
-  integrity sha512-932Io1VGKjM3ppi7xW9sb1J5nVkEJSUiOtHw2oE+JyHks1e+AXuOBSXbJKM0mcXwEnW1TibJibQ455Ow1YFjfg==
+express-rate-limit@6.5.1:
+  version "6.5.1"
+  resolved "https://registry.yarnpkg.com/express-rate-limit/-/express-rate-limit-6.5.1.tgz#2b4c329f03265f94f19613519b169afbd018e783"
+  integrity sha512-pxO6ioBLd3i8IHL+RmJtL4noYzte5fugoMdaDabtU4hcg53+x0QkTwfPtM7vWD0YUaXQgNj9NRdzmps+CHEHlA==
 
-express-session@^1.15.6, express-session@^1.17.2:
-  version "1.17.2"
-  resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.17.2.tgz#397020374f9bf7997f891b85ea338767b30d0efd"
-  integrity sha512-mPcYcLA0lvh7D4Oqr5aNJFMtBMKPLl++OKKxkHzZ0U0oDq1rpKBnkR5f5vCHR26VeArlTOEF9td4x5IjICksRQ==
+express-session@1.17.3, express-session@^1.15.6:
+  version "1.17.3"
+  resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.17.3.tgz#14b997a15ed43e5949cb1d073725675dd2777f36"
+  integrity sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==
   dependencies:
-    cookie "0.4.1"
+    cookie "0.4.2"
     cookie-signature "1.0.6"
     debug "2.6.9"
     depd "~2.0.0"
@@ -5235,38 +6005,39 @@ express-session@^1.15.6, express-session@^1.17.2:
     safe-buffer "5.2.1"
     uid-safe "~2.1.5"
 
-express@^4.17.3:
-  version "4.17.3"
-  resolved "https://registry.yarnpkg.com/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1"
-  integrity sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==
+express@4.18.1:
+  version "4.18.1"
+  resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf"
+  integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==
   dependencies:
     accepts "~1.3.8"
     array-flatten "1.1.1"
-    body-parser "1.19.2"
+    body-parser "1.20.0"
     content-disposition "0.5.4"
     content-type "~1.0.4"
-    cookie "0.4.2"
+    cookie "0.5.0"
     cookie-signature "1.0.6"
     debug "2.6.9"
-    depd "~1.1.2"
+    depd "2.0.0"
     encodeurl "~1.0.2"
     escape-html "~1.0.3"
     etag "~1.8.1"
-    finalhandler "~1.1.2"
+    finalhandler "1.2.0"
     fresh "0.5.2"
+    http-errors "2.0.0"
     merge-descriptors "1.0.1"
     methods "~1.1.2"
-    on-finished "~2.3.0"
+    on-finished "2.4.1"
     parseurl "~1.3.3"
     path-to-regexp "0.1.7"
     proxy-addr "~2.0.7"
-    qs "6.9.7"
+    qs "6.10.3"
     range-parser "~1.2.1"
     safe-buffer "5.2.1"
-    send "0.17.2"
-    serve-static "1.14.2"
+    send "0.18.0"
+    serve-static "1.15.0"
     setprototypeof "1.2.0"
-    statuses "~1.5.0"
+    statuses "2.0.1"
     type-is "~1.6.18"
     utils-merge "1.0.1"
     vary "~1.1.2"
@@ -5285,7 +6056,7 @@ external-editor@^3.0.3:
     iconv-lite "^0.4.24"
     tmp "^0.0.33"
 
-extract-react-intl-messages@^4.1.1:
+extract-react-intl-messages@4.1.1:
   version "4.1.1"
   resolved "https://registry.yarnpkg.com/extract-react-intl-messages/-/extract-react-intl-messages-4.1.1.tgz#cd01d99053bb053ecc8410ccdccb9ac56daae91c"
   integrity sha512-dPogci5X7HVtV7VbUxajH/1YgfNRaW2VtEiVidZ/31Tq8314uzOtzVMNo0IrAPD2E+H1wHoPiu/j565TZsyIZg==
@@ -5306,10 +6077,21 @@ extract-react-intl-messages@^4.1.1:
     sort-keys "^4.0.0"
     write-json-file "^4.3.0"
 
+extract-zip@2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
+  integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==
+  dependencies:
+    debug "^4.1.1"
+    get-stream "^5.1.0"
+    yauzl "^2.10.0"
+  optionalDependencies:
+    "@types/yauzl" "^2.9.1"
+
 extsprintf@1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
-  integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
+  integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==
 
 extsprintf@^1.2.0:
   version "1.4.1"
@@ -5345,7 +6127,7 @@ fast-json-stable-stringify@^2.0.0:
 fast-levenshtein@^2.0.6:
   version "2.0.6"
   resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
-  integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
+  integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
 
 fast-printf@^1.6.9:
   version "1.6.9"
@@ -5366,19 +6148,26 @@ fastq@^1.6.0:
   dependencies:
     reusify "^1.0.4"
 
+fd-slicer@~1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
+  integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==
+  dependencies:
+    pend "~1.2.0"
+
 fecha@^4.2.0:
-  version "4.2.1"
-  resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.1.tgz#0a83ad8f86ef62a091e22bb5a039cd03d23eecce"
-  integrity sha512-MMMQ0ludy/nBs1/o0zVOiKTpG7qMbonKUzjJgQFEuvq6INZ1OraKPRAWkBq5vlKLOUMpmNYG1JoN3oDPUQ9m3Q==
+  version "4.2.3"
+  resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.3.tgz#4d9ccdbc61e8629b259fdca67e65891448d569fd"
+  integrity sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==
 
 figures@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
-  integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=
+  integrity sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==
   dependencies:
     escape-string-regexp "^1.0.5"
 
-figures@^3.0.0:
+figures@^3.0.0, figures@^3.2.0:
   version "3.2.0"
   resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
   integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
@@ -5406,17 +6195,17 @@ fill-range@^7.0.1:
   dependencies:
     to-regex-range "^5.0.1"
 
-finalhandler@~1.1.2:
-  version "1.1.2"
-  resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
-  integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
+finalhandler@1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32"
+  integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==
   dependencies:
     debug "2.6.9"
     encodeurl "~1.0.2"
     escape-html "~1.0.3"
-    on-finished "~2.3.0"
+    on-finished "2.4.1"
     parseurl "~1.3.3"
-    statuses "~1.5.0"
+    statuses "2.0.1"
     unpipe "~1.0.0"
 
 find-node-modules@^2.1.2:
@@ -5435,7 +6224,7 @@ find-root@1.1.0, find-root@^1.1.0:
 find-up@^2.0.0, find-up@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
-  integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c=
+  integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==
   dependencies:
     locate-path "^2.0.0"
 
@@ -5495,15 +6284,24 @@ fn.name@1.x.x:
   resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc"
   integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==
 
-follow-redirects@^1.14.8:
-  version "1.14.9"
-  resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7"
-  integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==
+follow-redirects@^1.14.9:
+  version "1.15.1"
+  resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5"
+  integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==
 
 forever-agent@~0.6.1:
   version "0.6.1"
   resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
-  integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
+  integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==
+
+form-data@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
+  integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
+  dependencies:
+    asynckit "^0.4.0"
+    combined-stream "^1.0.8"
+    mime-types "^2.1.12"
 
 form-data@~2.3.2:
   version "2.3.3"
@@ -5514,7 +6312,7 @@ form-data@~2.3.2:
     combined-stream "^1.0.6"
     mime-types "^2.1.12"
 
-formik@^2.2.9:
+formik@2.2.9:
   version "2.2.9"
   resolved "https://registry.yarnpkg.com/formik/-/formik-2.2.9.tgz#8594ba9c5e2e5cf1f42c5704128e119fc46232d0"
   integrity sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA==
@@ -5532,7 +6330,7 @@ forwarded@0.2.0:
   resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
   integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
 
-fraction.js@^4.1.2:
+fraction.js@^4.2.0:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
   integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==
@@ -5540,12 +6338,12 @@ fraction.js@^4.1.2:
 fresh@0.5.2:
   version "0.5.2"
   resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
-  integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
+  integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==
 
 from2@^2.3.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af"
-  integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=
+  integrity sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==
   dependencies:
     inherits "^2.0.1"
     readable-stream "^2.0.0"
@@ -5564,16 +6362,7 @@ fs-extra@8.1.0:
     jsonfile "^4.0.0"
     universalify "^0.1.0"
 
-fs-extra@^10.0.0:
-  version "10.0.1"
-  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.1.tgz#27de43b4320e833f6867cc044bfce29fdf0ef3b8"
-  integrity sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==
-  dependencies:
-    graceful-fs "^4.2.0"
-    jsonfile "^6.0.1"
-    universalify "^2.0.0"
-
-fs-extra@^9.0.0:
+fs-extra@9.1.0, fs-extra@^9.0.0, fs-extra@^9.1.0:
   version "9.1.0"
   resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d"
   integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==
@@ -5583,12 +6372,14 @@ fs-extra@^9.0.0:
     jsonfile "^6.0.1"
     universalify "^2.0.0"
 
-fs-minipass@^1.2.7:
-  version "1.2.7"
-  resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
-  integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==
+fs-extra@^10.0.0:
+  version "10.1.0"
+  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
+  integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==
   dependencies:
-    minipass "^2.6.0"
+    graceful-fs "^4.2.0"
+    jsonfile "^6.0.1"
+    universalify "^2.0.0"
 
 fs-minipass@^2.0.0, fs-minipass@^2.1.0:
   version "2.1.0"
@@ -5605,7 +6396,7 @@ fs-readdir-recursive@^1.1.0:
 fs.realpath@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
-  integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
+  integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
 
 fsevents@~2.3.2:
   version "2.3.2"
@@ -5617,10 +6408,25 @@ function-bind@^1.1.1:
   resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
   integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
 
+function.prototype.name@^1.1.5:
+  version "1.1.5"
+  resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621"
+  integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==
+  dependencies:
+    call-bind "^1.0.2"
+    define-properties "^1.1.3"
+    es-abstract "^1.19.0"
+    functions-have-names "^1.2.2"
+
 functional-red-black-tree@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
-  integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=
+  integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==
+
+functions-have-names@^1.2.2:
+  version "1.2.3"
+  resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
+  integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
 
 gauge@^3.0.0:
   version "3.0.2"
@@ -5637,10 +6443,10 @@ gauge@^3.0.0:
     strip-ansi "^6.0.1"
     wide-align "^1.1.2"
 
-gauge@^4.0.0:
-  version "4.0.3"
-  resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.3.tgz#286cf105c1962c659f0963058fb05116c1b82d3f"
-  integrity sha512-ICw1DhAwMtb22rYFwEHgJcx1JCwJGv3x6G0OQUq56Nge+H4Q8JEwr8iveS0XFlsUNSI67F5ffMGK25bK4Pmskw==
+gauge@^4.0.3:
+  version "4.0.4"
+  resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce"
+  integrity sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==
   dependencies:
     aproba "^1.0.3 || ^2.0.0"
     color-support "^1.1.3"
@@ -5651,20 +6457,6 @@ gauge@^4.0.0:
     strip-ansi "^6.0.1"
     wide-align "^1.1.5"
 
-gauge@~2.7.3:
-  version "2.7.4"
-  resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
-  integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=
-  dependencies:
-    aproba "^1.0.3"
-    console-control-strings "^1.0.0"
-    has-unicode "^2.0.0"
-    object-assign "^4.1.0"
-    signal-exit "^3.0.0"
-    string-width "^1.0.1"
-    strip-ansi "^3.0.1"
-    wide-align "^1.1.0"
-
 gensync@^1.0.0-beta.2:
   version "1.0.0-beta.2"
   resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
@@ -5691,14 +6483,7 @@ get-paths@^0.0.7:
   dependencies:
     pify "^4.0.1"
 
-get-stream@^4.1.0:
-  version "4.1.0"
-  resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
-  integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
-  dependencies:
-    pump "^3.0.0"
-
-get-stream@^5.1.0:
+get-stream@^5.0.0, get-stream@^5.1.0:
   version "5.2.0"
   resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
   integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
@@ -5718,17 +6503,24 @@ get-symbol-description@^1.0.0:
     call-bind "^1.0.2"
     get-intrinsic "^1.1.1"
 
+getos@^3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/getos/-/getos-3.2.1.tgz#0134d1f4e00eb46144c5a9c0ac4dc087cbb27dc5"
+  integrity sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==
+  dependencies:
+    async "^3.2.0"
+
 getpass@^0.1.1:
   version "0.1.7"
   resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
-  integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
+  integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==
   dependencies:
     assert-plus "^1.0.0"
 
 git-log-parser@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/git-log-parser/-/git-log-parser-1.2.0.tgz#2e6a4c1b13fc00028207ba795a7ac31667b9fd4a"
-  integrity sha1-LmpMGxP8AAKCB7p5WnrDFme5/Uo=
+  integrity sha512-rnCVNfkTL8tdNryFuaY0fYiBWEBcgF748O6ZI61rslBvr2o7U65c2/6npCRqH40vuAhtgtDiqLTJjBVdrejCzA==
   dependencies:
     argv-formatter "~1.0.0"
     spawn-error-forwarder "~1.0.0"
@@ -5786,22 +6578,33 @@ glob@7.1.7:
     once "^1.3.0"
     path-is-absolute "^1.0.0"
 
-glob@^7.0.0, glob@^7.0.5, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.1.7, glob@^7.2.0:
-  version "7.2.0"
-  resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023"
-  integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
+glob@7.2.3, glob@^7.0.5, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0:
+  version "7.2.3"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
+  integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
   dependencies:
     fs.realpath "^1.0.0"
     inflight "^1.0.4"
     inherits "2"
-    minimatch "^3.0.4"
+    minimatch "^3.1.1"
     once "^1.3.0"
     path-is-absolute "^1.0.0"
 
+glob@^8.0.1:
+  version "8.0.3"
+  resolved "https://registry.yarnpkg.com/glob/-/glob-8.0.3.tgz#415c6eb2deed9e502c68fa44a272e6da6eeca42e"
+  integrity sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==
+  dependencies:
+    fs.realpath "^1.0.0"
+    inflight "^1.0.4"
+    inherits "2"
+    minimatch "^5.0.1"
+    once "^1.3.0"
+
 global-dirs@^0.1.1:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445"
-  integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=
+  integrity sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==
   dependencies:
     ini "^1.3.4"
 
@@ -5824,7 +6627,7 @@ global-modules@^1.0.0:
 global-prefix@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe"
-  integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=
+  integrity sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==
   dependencies:
     expand-tilde "^2.0.2"
     homedir-polyfill "^1.0.1"
@@ -5837,14 +6640,14 @@ globals@^11.1.0:
   resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
   integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
 
-globals@^13.6.0, globals@^13.9.0:
-  version "13.12.1"
-  resolved "https://registry.yarnpkg.com/globals/-/globals-13.12.1.tgz#ec206be932e6c77236677127577aa8e50bf1c5cb"
-  integrity sha512-317dFlgY2pdJZ9rspXDks7073GpDmXdfbM3vYYp0HAMKGDh1FfWPleI2ljVNLQX5M5lXcAslTcPTrOrMEFOjyw==
+globals@^13.15.0:
+  version "13.15.0"
+  resolved "https://registry.yarnpkg.com/globals/-/globals-13.15.0.tgz#38113218c907d2f7e98658af246cef8b77e90bac"
+  integrity sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==
   dependencies:
     type-fest "^0.20.2"
 
-globby@^11.0.0, globby@^11.0.1, globby@^11.0.4:
+globby@^11.0.0, globby@^11.0.1, globby@^11.0.4, globby@^11.1.0:
   version "11.1.0"
   resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
   integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
@@ -5856,29 +6659,17 @@ globby@^11.0.0, globby@^11.0.1, globby@^11.0.4:
     merge2 "^1.4.1"
     slash "^3.0.0"
 
-got@^9.6.0:
-  version "9.6.0"
-  resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85"
-  integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==
-  dependencies:
-    "@sindresorhus/is" "^0.14.0"
-    "@szmarczak/http-timer" "^1.1.2"
-    cacheable-request "^6.0.0"
-    decompress-response "^3.3.0"
-    duplexer3 "^0.1.4"
-    get-stream "^4.1.0"
-    lowercase-keys "^1.0.1"
-    mimic-response "^1.0.1"
-    p-cancelable "^1.0.0"
-    to-readable-stream "^1.0.0"
-    url-parse-lax "^3.0.0"
-
-graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9:
-  version "4.2.9"
-  resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96"
-  integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==
-
-gravatar-url@^3.1.0:
+graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.4, graceful-fs@^4.2.6:
+  version "4.2.10"
+  resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
+  integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
+
+grapheme-splitter@^1.0.4:
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
+  integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==
+
+gravatar-url@3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/gravatar-url/-/gravatar-url-3.1.0.tgz#0cbeedab7c00a7bc9b627b3716e331359efcc999"
   integrity sha512-+lOs7Rz1A051OqdqE8Tm4lmeyVgkqH8c6ll5fv///ncdIaL+XnOFmKAB70ix1du/yj8c3EWKbP6OhKjihsBSfA==
@@ -5901,7 +6692,7 @@ handlebars@^4.7.7:
 har-schema@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
-  integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
+  integrity sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==
 
 har-validator@~5.1.3:
   version "5.1.5"
@@ -5916,22 +6707,29 @@ hard-rejection@^2.1.0:
   resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883"
   integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==
 
-has-bigints@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113"
-  integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==
+has-bigints@^1.0.1, has-bigints@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa"
+  integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==
 
 has-flag@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
-  integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0=
+  integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
 
 has-flag@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
   integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
 
-has-symbols@^1.0.1, has-symbols@^1.0.2:
+has-property-descriptors@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861"
+  integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==
+  dependencies:
+    get-intrinsic "^1.1.1"
+
+has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
   integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
@@ -5943,15 +6741,10 @@ has-tostringtag@^1.0.0:
   dependencies:
     has-symbols "^1.0.2"
 
-has-unicode@^2.0.0, has-unicode@^2.0.1:
+has-unicode@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
-  integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=
-
-has-yarn@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77"
-  integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==
+  integrity sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==
 
 has@^1.0.3:
   version "1.0.3"
@@ -5999,37 +6792,33 @@ hosted-git-info@^2.1.4:
   resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
   integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
 
-hosted-git-info@^4.0.0, hosted-git-info@^4.0.1, hosted-git-info@^4.1.0:
+hosted-git-info@^4.0.0, hosted-git-info@^4.0.1:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-4.1.0.tgz#827b82867e9ff1c8d0c4d9d53880397d2c86d224"
   integrity sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==
   dependencies:
     lru-cache "^6.0.0"
 
-html-to-text@8.0.0:
-  version "8.0.0"
-  resolved "https://registry.yarnpkg.com/html-to-text/-/html-to-text-8.0.0.tgz#5848681a5a38d657a7bb58cf5006d1c29fe64ce3"
-  integrity sha512-fEtul1OerF2aMEV+Wpy+Ue20tug134jOY1GIudtdqZi7D0uTudB2tVJBKfVhTL03dtqeJoF8gk8EPX9SyMEvLg==
+hosted-git-info@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-5.0.0.tgz#df7a06678b4ebd722139786303db80fdf302ea56"
+  integrity sha512-rRnjWu0Bxj+nIfUOkz0695C0H6tRrN5iYIzYejb0tDEefe2AekHu/U5Kn9pEie5vsJqpNQU02az7TGSH3qpz4Q==
+  dependencies:
+    lru-cache "^7.5.1"
+
+html-to-text@8.2.0, html-to-text@^8.1.0:
+  version "8.2.0"
+  resolved "https://registry.yarnpkg.com/html-to-text/-/html-to-text-8.2.0.tgz#8b35e280ba7fc27710b7aa76d4500aab30731924"
+  integrity sha512-CLXExYn1b++Lgri+ZyVvbUEFwzkLZppjjZOwB7X1qv2jIi8MrMEvxWX5KQ7zATAzTvcqgmtO00M2kCRMtEdOKQ==
   dependencies:
     "@selderee/plugin-htmlparser2" "^0.6.0"
     deepmerge "^4.2.2"
     he "^1.2.0"
     htmlparser2 "^6.1.0"
-    minimist "^1.2.5"
+    minimist "^1.2.6"
     selderee "^0.6.0"
 
-html-to-text@^6.0.0:
-  version "6.0.0"
-  resolved "https://registry.yarnpkg.com/html-to-text/-/html-to-text-6.0.0.tgz#8b48adb1b781a8378f374c5bb481864a169f59f4"
-  integrity sha512-r0KNC5aqCAItsjlgtirW6RW25c92Ee3ybQj8z//4Sl4suE3HIPqM4deGpYCUJULLjtVPEP1+Ma+1ZeX1iMsCiA==
-  dependencies:
-    deepmerge "^4.2.2"
-    he "^1.2.0"
-    htmlparser2 "^4.1.0"
-    lodash "^4.17.20"
-    minimist "^1.2.5"
-
-htmlparser2@^4.0.0, htmlparser2@^4.1.0:
+htmlparser2@^4.0.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-4.1.0.tgz#9a4ef161f2e4625ebf7dfbe6c0a2f52d18a59e78"
   integrity sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==
@@ -6049,20 +6838,30 @@ htmlparser2@^6.1.0:
     domutils "^2.5.2"
     entities "^2.0.0"
 
-http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0:
+htmlparser2@^8.0.1:
+  version "8.0.1"
+  resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.1.tgz#abaa985474fcefe269bc761a779b544d7196d010"
+  integrity sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==
+  dependencies:
+    domelementtype "^2.3.0"
+    domhandler "^5.0.2"
+    domutils "^3.0.1"
+    entities "^4.3.0"
+
+http-cache-semantics@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390"
   integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==
 
-http-errors@1.8.1:
-  version "1.8.1"
-  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c"
-  integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==
+http-errors@2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
+  integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
   dependencies:
-    depd "~1.1.2"
+    depd "2.0.0"
     inherits "2.0.4"
     setprototypeof "1.2.0"
-    statuses ">= 1.5.0 < 2"
+    statuses "2.0.1"
     toidentifier "1.0.1"
 
 http-errors@~1.7.3:
@@ -6097,12 +6896,21 @@ http-proxy-agent@^5.0.0:
 http-signature@~1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
-  integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
+  integrity sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==
   dependencies:
     assert-plus "^1.0.0"
     jsprim "^1.2.2"
     sshpk "^1.7.0"
 
+http-signature@~1.3.6:
+  version "1.3.6"
+  resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.3.6.tgz#cb6fbfdf86d1c974f343be94e87f7fc128662cf9"
+  integrity sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==
+  dependencies:
+    assert-plus "^1.0.0"
+    jsprim "^2.0.2"
+    sshpk "^1.14.1"
+
 http_ece@1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/http_ece/-/http_ece-1.1.0.tgz#74780c6eb32d8ddfe9e36a83abcd81fe0cd4fb75"
@@ -6111,13 +6919,18 @@ http_ece@1.1.0:
     urlsafe-base64 "~1.0.0"
 
 https-proxy-agent@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2"
-  integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
+  integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
   dependencies:
     agent-base "6"
     debug "4"
 
+human-signals@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
+  integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
+
 human-signals@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
@@ -6126,14 +6939,14 @@ human-signals@^2.1.0:
 humanize-ms@^1.2.1:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed"
-  integrity sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=
+  integrity sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==
   dependencies:
     ms "^2.0.0"
 
-husky@^7.0.4:
-  version "7.0.4"
-  resolved "https://registry.yarnpkg.com/husky/-/husky-7.0.4.tgz#242048245dc49c8fb1bf0cc7cfb98dd722531535"
-  integrity sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==
+husky@8.0.1:
+  version "8.0.1"
+  resolved "https://registry.yarnpkg.com/husky/-/husky-8.0.1.tgz#511cb3e57de3e3190514ae49ed50f6bc3f50b3e9"
+  integrity sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==
 
 i18n-locales@^0.0.5:
   version "0.0.5"
@@ -6154,20 +6967,13 @@ i18n@^0.14.1:
     math-interval-parser "^2.0.1"
     mustache "^4.2.0"
 
-iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
+iconv-lite@0.4.24, iconv-lite@^0.4.24:
   version "0.4.24"
   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
   integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
   dependencies:
     safer-buffer ">= 2.1.2 < 3"
 
-iconv-lite@0.6.2:
-  version "0.6.2"
-  resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.2.tgz#ce13d1875b0c3a674bd6a04b7f76b01b1b6ded01"
-  integrity sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==
-  dependencies:
-    safer-buffer ">= 2.1.2 < 3.0.0"
-
 iconv-lite@0.6.3, iconv-lite@^0.6.2:
   version "0.6.3"
   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
@@ -6175,7 +6981,7 @@ iconv-lite@0.6.3, iconv-lite@^0.6.2:
   dependencies:
     safer-buffer ">= 2.1.2 < 3.0.0"
 
-ieee754@^1.2.1:
+ieee754@^1.1.13, ieee754@^1.2.1:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
   integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
@@ -6183,23 +6989,16 @@ ieee754@^1.2.1:
 ignore-by-default@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
-  integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk=
-
-ignore-walk@^3.0.1:
-  version "3.0.4"
-  resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.4.tgz#c9a09f69b7c7b479a5d74ac1a3c0d4236d2a6335"
-  integrity sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ==
-  dependencies:
-    minimatch "^3.0.4"
+  integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==
 
-ignore-walk@^4.0.1:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-4.0.1.tgz#fc840e8346cf88a3a9380c5b17933cd8f4d39fa3"
-  integrity sha512-rzDQLaW4jQbh2YrOFlJdCtX8qgJTehFRYiUB2r1osqTeDzV/3+Jh8fz1oAPzUThf3iku8Ds4IDqawI5d8mUiQw==
+ignore-walk@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-5.0.1.tgz#5f199e23e1288f518d90358d461387788a154776"
+  integrity sha512-yemi4pMf51WKT7khInJqAvsIGzoqYXblnsz0ql8tM+yi1EKYTY1evX4NAbJrLL/Aanr2HyZeluqU+Oi7MGHokw==
   dependencies:
-    minimatch "^3.0.4"
+    minimatch "^5.0.1"
 
-ignore@^5.1.8, ignore@^5.2.0:
+ignore@^5.2.0:
   version "5.2.0"
   resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
   integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==
@@ -6217,15 +7016,10 @@ import-from@^4.0.0:
   resolved "https://registry.yarnpkg.com/import-from/-/import-from-4.0.0.tgz#2710b8d66817d232e16f4166e319248d3d5492e2"
   integrity sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==
 
-import-lazy@^2.1.0:
-  version "2.1.0"
-  resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
-  integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=
-
 imurmurhash@^0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
-  integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
+  integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
 
 indent-string@^4.0.0:
   version "4.0.0"
@@ -6240,17 +7034,17 @@ infer-owner@^1.0.4:
 inflight@^1.0.4:
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
-  integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
+  integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
   dependencies:
     once "^1.3.0"
     wrappy "1"
 
-inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
+inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
   integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
 
-ini@2.0.0, ini@^2.0.0:
+ini@2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5"
   integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==
@@ -6260,18 +7054,23 @@ ini@^1.3.4, ini@~1.3.0:
   resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
   integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
 
-init-package-json@^3.0.0:
+ini@^3.0.0:
   version "3.0.0"
-  resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-3.0.0.tgz#9ccc1143426a52224cdbfa5485b1cb8a03ac34be"
-  integrity sha512-b0PZaZ3lF0mKsk7QcP03LhxXttVR0kb4XIafD1HXV4JIvLhifdvFgNyXr3qSA/3DZmiskFveLP1eXfXGFybG6g==
+  resolved "https://registry.yarnpkg.com/ini/-/ini-3.0.0.tgz#2f6de95006923aa75feed8894f5686165adc08f1"
+  integrity sha512-TxYQaeNW/N8ymDvwAxPyRbhMBtnEwuvaTYpOQkFx1nSeusgezHniEc/l35Vo4iCq/mMiTJbpD7oYxN98hFlfmw==
+
+init-package-json@^3.0.2:
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-3.0.2.tgz#f5bc9bac93f2bdc005778bc2271be642fecfcd69"
+  integrity sha512-YhlQPEjNFqlGdzrBfDNRLhvoSgX7iQRgSxgsNknRQ9ITXFT7UMfVMWhBTOh2Y+25lRnGrv5Xz8yZwQ3ACR6T3A==
   dependencies:
-    npm-package-arg "^9.0.0"
+    npm-package-arg "^9.0.1"
     promzard "^0.3.0"
     read "^1.0.7"
-    read-package-json "^4.1.1"
+    read-package-json "^5.0.0"
     semver "^7.3.5"
     validate-npm-package-license "^3.0.4"
-    validate-npm-package-name "^3.0.0"
+    validate-npm-package-name "^4.0.0"
 
 inline-style-parser@0.1.1:
   version "0.1.1"
@@ -6297,6 +7096,27 @@ inquirer@6.5.2:
     strip-ansi "^5.1.0"
     through "^2.3.6"
 
+inquirer@8.2.4:
+  version "8.2.4"
+  resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.4.tgz#ddbfe86ca2f67649a67daa6f1051c128f684f0b4"
+  integrity sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==
+  dependencies:
+    ansi-escapes "^4.2.1"
+    chalk "^4.1.1"
+    cli-cursor "^3.1.0"
+    cli-width "^3.0.0"
+    external-editor "^3.0.3"
+    figures "^3.0.0"
+    lodash "^4.17.21"
+    mute-stream "0.0.8"
+    ora "^5.4.1"
+    run-async "^2.4.0"
+    rxjs "^7.5.5"
+    string-width "^4.1.0"
+    strip-ansi "^6.0.0"
+    through "^2.3.6"
+    wrap-ansi "^7.0.0"
+
 internal-slot@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c"
@@ -6321,20 +7141,20 @@ intl-messageformat-parser@^5.3.7:
   dependencies:
     "@formatjs/intl-numberformat" "^5.5.2"
 
-intl-messageformat@9.11.4:
-  version "9.11.4"
-  resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-9.11.4.tgz#0f9030bc6d10e6a48592142f88e646d88f05f1f2"
-  integrity sha512-77TSkNubIy/hsapz6LQpyR6OADcxhWdhSaboPb5flMaALCVkPvAIxr48AlPqaMl4r1anNcvR9rpLWVdwUY1IKg==
+intl-messageformat@10.1.1:
+  version "10.1.1"
+  resolved "https://registry.yarnpkg.com/intl-messageformat/-/intl-messageformat-10.1.1.tgz#226767e7921fa86cef2cbe4a13911050716720bc"
+  integrity sha512-FeJne2oooYW6shLPbrqyjRX6hTELVrQ90Dn88z7NomLk/xZBCLxLPAkgaYaTQJBRBV78nZ933d8APHHkTQrD9Q==
   dependencies:
-    "@formatjs/ecma402-abstract" "1.11.3"
-    "@formatjs/fast-memoize" "1.2.1"
-    "@formatjs/icu-messageformat-parser" "2.0.18"
-    tslib "^2.1.0"
+    "@formatjs/ecma402-abstract" "1.11.8"
+    "@formatjs/fast-memoize" "1.2.4"
+    "@formatjs/icu-messageformat-parser" "2.1.4"
+    tslib "2.4.0"
 
-intl@^1.2.5:
+intl@1.2.5:
   version "1.2.5"
   resolved "https://registry.yarnpkg.com/intl/-/intl-1.2.5.tgz#82244a2190c4e419f8371f5aa34daa3420e2abde"
-  integrity sha1-giRKIZDE5Bn4Nx9ao02qNCDiq94=
+  integrity sha512-rK0KcPHeBFBcqsErKSpvZnrOmWOj+EmDkyJ57e90YWaQNqbcivcqmKDlHEeNprDWOsKzPsh1BfSpPQdDvclHVw==
 
 into-stream@^6.0.0:
   version "6.0.0"
@@ -6350,9 +7170,9 @@ ip-regex@^4.1.0:
   integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==
 
 ip@^1.1.5:
-  version "1.1.5"
-  resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
-  integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=
+  version "1.1.8"
+  resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.8.tgz#ae05948f6b075435ed3307acce04629da8cdbf48"
+  integrity sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==
 
 ipaddr.js@1.9.1:
   version "1.9.1"
@@ -6362,7 +7182,7 @@ ipaddr.js@1.9.1:
 is-arrayish@^0.2.1:
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
-  integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=
+  integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
 
 is-arrayish@^0.3.1:
   version "0.3.2"
@@ -6401,12 +7221,12 @@ is-callable@^1.1.4, is-callable@^1.2.4:
   resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945"
   integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==
 
-is-ci@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c"
-  integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==
+is-ci@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867"
+  integrity sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==
   dependencies:
-    ci-info "^2.0.0"
+    ci-info "^3.2.0"
 
 is-cidr@^4.0.2:
   version "4.0.2"
@@ -6415,10 +7235,10 @@ is-cidr@^4.0.2:
   dependencies:
     cidr-regex "^3.1.1"
 
-is-core-module@^2.2.0, is-core-module@^2.5.0, is-core-module@^2.8.0, is-core-module@^2.8.1:
-  version "2.8.1"
-  resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.1.tgz#f59fdfca701d5879d0a6b100a40aa1560ce27211"
-  integrity sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==
+is-core-module@^2.2.0, is-core-module@^2.5.0, is-core-module@^2.8.1, is-core-module@^2.9.0:
+  version "2.9.0"
+  resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69"
+  integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==
   dependencies:
     has "^1.0.3"
 
@@ -6445,19 +7265,12 @@ is-expression@^4.0.0:
 is-extglob@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
-  integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
-
-is-fullwidth-code-point@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
-  integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
-  dependencies:
-    number-is-nan "^1.0.0"
+  integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
 
 is-fullwidth-code-point@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
-  integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
+  integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==
 
 is-fullwidth-code-point@^3.0.0:
   version "3.0.0"
@@ -6476,7 +7289,7 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
   dependencies:
     is-extglob "^2.1.1"
 
-is-installed-globally@^0.4.0:
+is-installed-globally@~0.4.0:
   version "0.4.0"
   resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520"
   integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==
@@ -6484,10 +7297,15 @@ is-installed-globally@^0.4.0:
     global-dirs "^3.0.0"
     is-path-inside "^3.0.2"
 
+is-interactive@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
+  integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==
+
 is-lambda@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5"
-  integrity sha1-PZh3iZ5qU+/AFgUEzeFfgubwYdU=
+  integrity sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==
 
 is-nan@^1.3.2:
   version "1.3.2"
@@ -6497,20 +7315,15 @@ is-nan@^1.3.2:
     call-bind "^1.0.0"
     define-properties "^1.1.3"
 
-is-negative-zero@^2.0.1:
+is-negative-zero@^2.0.2:
   version "2.0.2"
   resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150"
   integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==
 
-is-npm@^5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-5.0.0.tgz#43e8d65cc56e1b67f8d47262cf667099193f45a8"
-  integrity sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA==
-
 is-number-object@^1.0.4:
-  version "1.0.6"
-  resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0"
-  integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc"
+  integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==
   dependencies:
     has-tostringtag "^1.0.0"
 
@@ -6537,7 +7350,7 @@ is-path-inside@^3.0.2:
 is-plain-obj@^1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
-  integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4=
+  integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==
 
 is-plain-obj@^2.0.0:
   version "2.1.0"
@@ -6567,10 +7380,12 @@ is-regex@^1.0.3, is-regex@^1.1.4:
     call-bind "^1.0.2"
     has-tostringtag "^1.0.0"
 
-is-shared-array-buffer@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6"
-  integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==
+is-shared-array-buffer@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79"
+  integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==
+  dependencies:
+    call-bind "^1.0.2"
 
 is-stream@^2.0.0:
   version "2.0.1"
@@ -6594,21 +7409,26 @@ is-symbol@^1.0.2, is-symbol@^1.0.3:
 is-text-path@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e"
-  integrity sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=
+  integrity sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==
   dependencies:
     text-extensions "^1.0.0"
 
 is-typedarray@^1.0.0, is-typedarray@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
-  integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
+  integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==
+
+is-unicode-supported@^0.1.0:
+  version "0.1.0"
+  resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
+  integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==
 
 is-utf8@^0.2.1:
   version "0.2.1"
   resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
-  integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=
+  integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==
 
-is-weakref@^1.0.1:
+is-weakref@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2"
   integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==
@@ -6627,30 +7447,25 @@ is-wsl@^2.1.1:
   dependencies:
     is-docker "^2.0.0"
 
-is-yarn-global@^0.3.0:
-  version "0.3.0"
-  resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232"
-  integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==
-
 isarray@0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
-  integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
+  integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==
 
 isarray@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
-  integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=
+  integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==
 
 isexe@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
-  integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
+  integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
 
 isstream@~0.1.2:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
-  integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
+  integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==
 
 issue-parser@^6.0.0:
   version "6.0.0"
@@ -6671,7 +7486,7 @@ java-properties@^1.0.0:
 js-stringify@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db"
-  integrity sha1-Fzb939lyTyijaCrcYjCufk6Weds=
+  integrity sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==
 
 "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
   version "4.0.0"
@@ -6686,7 +7501,7 @@ js-yaml@^3.13.1:
     argparse "^1.0.7"
     esprima "^4.0.0"
 
-js-yaml@^4.0.0, js-yaml@^4.1.0:
+js-yaml@^4.1.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
   integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
@@ -6696,7 +7511,7 @@ js-yaml@^4.0.0, js-yaml@^4.1.0:
 jsbn@~0.1.0:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
-  integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
+  integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==
 
 jsesc@^2.5.1:
   version "2.5.2"
@@ -6706,12 +7521,7 @@ jsesc@^2.5.1:
 jsesc@~0.5.0:
   version "0.5.0"
   resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
-  integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=
-
-json-buffer@3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898"
-  integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=
+  integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==
 
 json-parse-better-errors@^1.0.1:
   version "1.0.2"
@@ -6748,7 +7558,14 @@ json-schema@0.4.0:
 json-stable-stringify-without-jsonify@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
-  integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=
+  integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
+
+json-stable-stringify@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af"
+  integrity sha512-i/J297TW6xyj7sDFa7AmBPkQvLIxWr2kKPWI26tXydnZrzVAocNqn5DMNT1Mzk0vit1V5UkRM7C1KdVNp7Lmcg==
+  dependencies:
+    jsonify "~0.0.0"
 
 json-stringify-nice@^1.1.4:
   version "1.1.4"
@@ -6758,7 +7575,7 @@ json-stringify-nice@^1.1.4:
 json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
   version "5.0.1"
   resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
-  integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
+  integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==
 
 json5@^1.0.1:
   version "1.0.1"
@@ -6767,17 +7584,15 @@ json5@^1.0.1:
   dependencies:
     minimist "^1.2.0"
 
-json5@^2.1.2:
-  version "2.2.0"
-  resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3"
-  integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==
-  dependencies:
-    minimist "^1.2.5"
+json5@^2.1.2, json5@^2.2.1:
+  version "2.2.1"
+  resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
+  integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
 
 jsonfile@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb"
-  integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=
+  integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==
   optionalDependencies:
     graceful-fs "^4.1.6"
 
@@ -6790,10 +7605,15 @@ jsonfile@^6.0.1:
   optionalDependencies:
     graceful-fs "^4.1.6"
 
+jsonify@~0.0.0:
+  version "0.0.0"
+  resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
+  integrity sha512-trvBk1ki43VZptdBI5rIlG4YOzyeH/WefQt5rj1grasPn4iiZWKet8nkgc4GlsAylaztn0qZfUYOiTsASJFdNA==
+
 jsonparse@^1.2.0, jsonparse@^1.3.1:
   version "1.3.1"
   resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
-  integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=
+  integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==
 
 jsprim@^1.2.2:
   version "1.4.2"
@@ -6805,20 +7625,38 @@ jsprim@^1.2.2:
     json-schema "0.4.0"
     verror "1.10.0"
 
+jsprim@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-2.0.2.tgz#77ca23dbcd4135cd364800d22ff82c2185803d4d"
+  integrity sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==
+  dependencies:
+    assert-plus "1.0.0"
+    extsprintf "1.3.0"
+    json-schema "0.4.0"
+    verror "1.10.0"
+
 jstransformer@1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/jstransformer/-/jstransformer-1.0.0.tgz#ed8bf0921e2f3f1ed4d5c1a44f68709ed24722c3"
-  integrity sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=
+  integrity sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==
   dependencies:
     is-promise "^2.0.0"
     promise "^7.0.1"
 
 "jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.2.1:
-  version "3.2.1"
-  resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.1.tgz#720b97bfe7d901b927d87c3773637ae8ea48781b"
-  integrity sha512-uP5vu8xfy2F9A6LGC22KO7e2/vGTS1MhP+18f++ZNlf0Ohaxbc9nIEwHAsejlJKyzfZzU5UIhe5ItYkitcZnZA==
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.0.tgz#e624f259143b9062c92b6413ff92a164c80d3ccb"
+  integrity sha512-XzO9luP6L0xkxwhIJMTJQpZo/eeN60K08jHdexfD569AGxeNug6UketeHXEhROoM8aR7EcUoOQmIhcJQjcuq8Q==
   dependencies:
-    array-includes "^3.1.3"
+    array-includes "^3.1.4"
+    object.assign "^4.1.2"
+
+jsx-ast-utils@^3.3.2:
+  version "3.3.2"
+  resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.2.tgz#afe5efe4332cd3515c065072bd4d6b0aa22152bd"
+  integrity sha512-4ZCADZHRkno244xlNnn4AOG6sRQ7iBZ5BbgZ4vW4y5IZw7cVUD1PPeblm1xx/nfmMxPdt/LHsXZW8z/j58+l9Q==
+  dependencies:
+    array-includes "^3.1.5"
     object.assign "^4.1.2"
 
 juice@^7.0.0:
@@ -6832,15 +7670,26 @@ juice@^7.0.0:
     slick "^1.12.2"
     web-resource-inliner "^5.0.0"
 
-just-diff-apply@^4.0.1:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/just-diff-apply/-/just-diff-apply-4.0.1.tgz#da89c5a4ccb14aa8873c70e2c3b6695cef45dab5"
-  integrity sha512-AKOkzB5P6FkfP21UlZVX/OPXx/sC2GagpLX9cBxqHqDuRjwmZ/AJRKSNrB9jHPpRW1W1ONs6gly1gW46t055nQ==
+juice@^8.0.0:
+  version "8.0.0"
+  resolved "https://registry.yarnpkg.com/juice/-/juice-8.0.0.tgz#ac77d3372373409b06a875aee425b9d381f645fe"
+  integrity sha512-LRCfXBOqI1wt+zYR/5xwDnf+ZyiJiDt44DGZaBSAVwZWyWv3BliaiGTLS6KCvadv3uw6XGiPPFcTfY7CdF7Z/Q==
+  dependencies:
+    cheerio "^1.0.0-rc.3"
+    commander "^6.1.0"
+    mensch "^0.3.4"
+    slick "^1.12.2"
+    web-resource-inliner "^5.0.0"
+
+just-diff-apply@^5.2.0:
+  version "5.3.1"
+  resolved "https://registry.yarnpkg.com/just-diff-apply/-/just-diff-apply-5.3.1.tgz#30f40809ffed55ad76dccf73fa9b85a76964c867"
+  integrity sha512-dgFenZnMsc1xGNqgdtgnh7DK+Oy352CE3VZLbzcbQpsBs9iI2K3M0IRrdgREZ72eItTjbl0suRyvKRdVQa9GbA==
 
 just-diff@^5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/just-diff/-/just-diff-5.0.1.tgz#db8fe1cfeea1156f2374bfb289826dca28e7e390"
-  integrity sha512-X00TokkRIDotUIf3EV4xUm6ELc/IkqhS/vPSHdWnsM5y0HoNMfEqrazizI7g78lpHvnRSRt/PFfKtRqJCOGIuQ==
+  version "5.0.2"
+  resolved "https://registry.yarnpkg.com/just-diff/-/just-diff-5.0.2.tgz#68854c94280c37d28cb266d8f29bdd2cd29f003e"
+  integrity sha512-uGd6F+eIZ4T95EinP8ubINGkbEy3jrgBym+6LjW+ja1UG1WQIcEcQ6FLeyXtVJZglk+bj7fvEn+Cu2LBxkgiYQ==
 
 jwa@^2.0.0:
   version "2.0.0"
@@ -6859,13 +7708,6 @@ jws@^4.0.0:
     jwa "^2.0.0"
     safe-buffer "^5.0.1"
 
-keyv@^3.0.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9"
-  integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==
-  dependencies:
-    json-buffer "3.0.0"
-
 kind-of@^6.0.3:
   version "6.0.3"
   resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
@@ -6889,16 +7731,14 @@ language-subtag-registry@~0.3.2:
 language-tags@^1.0.5:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a"
-  integrity sha1-0yHbxNowuovzAk4ED6XBRmH5GTo=
+  integrity sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==
   dependencies:
     language-subtag-registry "~0.3.2"
 
-latest-version@^5.1.0:
-  version "5.1.0"
-  resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face"
-  integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==
-  dependencies:
-    package-json "^6.3.0"
+lazy-ass@^1.6.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513"
+  integrity sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==
 
 levn@^0.4.1:
   version "0.4.1"
@@ -6913,142 +7753,146 @@ libbase64@1.2.1:
   resolved "https://registry.yarnpkg.com/libbase64/-/libbase64-1.2.1.tgz#fb93bf4cb6d730f29b92155b6408d1bd2176a8c8"
   integrity sha512-l+nePcPbIG1fNlqMzrh68MLkX/gTxk/+vdvAb388Ssi7UuUN31MI44w4Yf33mM3Cm4xDfw48mdf3rkdHszLNew==
 
-libmime@5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/libmime/-/libmime-5.0.0.tgz#4759c76eb219985c5d4057b3a9359922194d9ff7"
-  integrity sha512-2Bm96d5ktnE217Ib1FldvUaPAaOst6GtZrsxJCwnJgi9lnsoAKIHyU0sae8rNx6DNYbjdqqh8lv5/b9poD8qOg==
+libmime@5.1.0:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/libmime/-/libmime-5.1.0.tgz#d9a1c4a85c982fa4e64c2c841f95e3827c3f71d2"
+  integrity sha512-xOqorG21Va+3CjpFOfFTU7SWohHH2uIX9ZY4Byz6J+lvpfvc486tOAT/G9GfbrKtJ9O7NCX9o0aC2lxqbnZ9EA==
   dependencies:
-    encoding-japanese "1.0.30"
-    iconv-lite "0.6.2"
+    encoding-japanese "2.0.0"
+    iconv-lite "0.6.3"
     libbase64 "1.2.1"
     libqp "1.1.0"
 
-libnpmaccess@^6.0.1:
-  version "6.0.1"
-  resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-6.0.1.tgz#76a67a84590be2143d8d05ee1ca3d3f332e2a9bb"
-  integrity sha512-IMQEFBpiBOODmON0XXNuDx5aAGw2EE1PuDsWOpZzFrlTCNDkINGDarGGRyunOQFapNjZd18UeApZjEJosLaXyQ==
+libnpmaccess@^6.0.2:
+  version "6.0.3"
+  resolved "https://registry.yarnpkg.com/libnpmaccess/-/libnpmaccess-6.0.3.tgz#473cc3e4aadb2bc713419d92e45d23b070d8cded"
+  integrity sha512-4tkfUZprwvih2VUZYMozL7EMKgQ5q9VW2NtRyxWtQWlkLTAWHRklcAvBN49CVqEkhUw7vTX2fNgB5LzgUucgYg==
   dependencies:
     aproba "^2.0.0"
     minipass "^3.1.1"
-    npm-package-arg "^9.0.0"
+    npm-package-arg "^9.0.1"
     npm-registry-fetch "^13.0.0"
 
-libnpmdiff@^4.0.1:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/libnpmdiff/-/libnpmdiff-4.0.1.tgz#929f1ae42739d4d9722ee6159f54778f4dd17faf"
-  integrity sha512-qZtpjH9R0RgWar3BfwkOWBIRsbtfNqcSAFWED0PzWIKp2d2qAEt4adGDpmnd4CKxujyqPrVHcqER3OqbqjqqFA==
+libnpmdiff@^4.0.2:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/libnpmdiff/-/libnpmdiff-4.0.3.tgz#ad3997330c887c1098ac42682f1e5ad014d49cec"
+  integrity sha512-AiwBtXtH7HjfmT7FbTf9LFzJB347RrIA4I+IewMfhq8vYXaUveHwJMVNgMM2H/o2J+7Hf12JCBoOF5bTwlmGyw==
   dependencies:
-    "@npmcli/disparity-colors" "^1.0.1"
+    "@npmcli/disparity-colors" "^2.0.0"
     "@npmcli/installed-package-contents" "^1.0.7"
     binary-extensions "^2.2.0"
     diff "^5.0.0"
-    minimatch "^3.0.4"
-    npm-package-arg "^9.0.0"
-    pacote "^13.0.2"
+    minimatch "^5.0.1"
+    npm-package-arg "^9.0.1"
+    pacote "^13.0.5"
     tar "^6.1.0"
 
-libnpmexec@^4.0.1:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/libnpmexec/-/libnpmexec-4.0.1.tgz#02755c03fd2566ed9d8857dfebf5183d0967a982"
-  integrity sha512-hax7tnZwx0RVoo4Ds0X9aItzGAibbbiOcxXox1OSCOOFeM56rRsCJh/Izog8/8X8/6kMaybWS5reDIC0oPxX7g==
+libnpmexec@^4.0.2:
+  version "4.0.5"
+  resolved "https://registry.yarnpkg.com/libnpmexec/-/libnpmexec-4.0.5.tgz#e488a1f47805b8d9af3c216ff4a5ea9c51111013"
+  integrity sha512-ykTsaAz0AV5mPr2HqmI6GCtQ5b6/OTJnnuXxZa78fJVMIGqJMfm4lAQZpBNNyH68Fs0oDIGZbnWaB5PfzyzSJg==
   dependencies:
     "@npmcli/arborist" "^5.0.0"
     "@npmcli/ci-detect" "^2.0.0"
     "@npmcli/run-script" "^3.0.0"
     chalk "^4.1.0"
     mkdirp-infer-owner "^2.0.0"
-    npm-package-arg "^9.0.0"
-    npmlog "^6.0.1"
-    pacote "^13.0.2"
+    npm-package-arg "^9.0.1"
+    npmlog "^6.0.2"
+    pacote "^13.0.5"
     proc-log "^2.0.0"
     read "^1.0.7"
     read-package-json-fast "^2.0.2"
     walk-up-path "^1.0.0"
 
 libnpmfund@^3.0.1:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/libnpmfund/-/libnpmfund-3.0.1.tgz#18dcf25c7d4d28dca73fa73ef5bcd3f7e8aaef1a"
-  integrity sha512-VXtKDWCfgyNgY9ioAx0/KmI4dQwCt4kkOEjfMa1ygTXMQisj3HvWa3ppMtrwp/LSE6VIGSaniRI/8YNomcwebA==
+  version "3.0.2"
+  resolved "https://registry.yarnpkg.com/libnpmfund/-/libnpmfund-3.0.2.tgz#7da0827950f0db2cce0acb0dc7652d1834a8b239"
+  integrity sha512-wmFMP/93Wjy+jDg5LaSldDgAhSgCyA64JUUmp806Kae7y3YP9Qv5m1vUhPxT4yebxgB2v/I6G1/RUcNb1y0kVg==
   dependencies:
     "@npmcli/arborist" "^5.0.0"
 
-libnpmhook@^8.0.1:
-  version "8.0.1"
-  resolved "https://registry.yarnpkg.com/libnpmhook/-/libnpmhook-8.0.1.tgz#2f6fab6a5700002fd5681461897cc23ecf835669"
-  integrity sha512-4kdii7Krt8ii9ZLP/xiU1e4Al2NtnOagVQ3/klL3+ZVBU9DVioMsr+7HB3UGdgohjwTrUSN0XhdeQJdoDjvEdg==
+libnpmhook@^8.0.2:
+  version "8.0.3"
+  resolved "https://registry.yarnpkg.com/libnpmhook/-/libnpmhook-8.0.3.tgz#9628518a63455d21dafda312ee46175275707ff5"
+  integrity sha512-TEdNI1mC5zS+w/juCgxrwwQnpbq9lY76NDOS0N37pn6pWIUxB1Yq8mwy6MUEXR1TgH4HurSQyKT6I6Kp9Wjm4A==
   dependencies:
     aproba "^2.0.0"
     npm-registry-fetch "^13.0.0"
 
-libnpmorg@^4.0.1:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/libnpmorg/-/libnpmorg-4.0.1.tgz#54c9c48d9b3b1ccb8def3498ee379ea3e1e9633e"
-  integrity sha512-IVbX21PpGIWK0HEpOGv2KNS89RnwYSAuAtrKX+ka7SC7HZSHfLS7gJ7es+B+YSObV4THmCO8qySbNN8IbOqSSg==
+libnpmorg@^4.0.2:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/libnpmorg/-/libnpmorg-4.0.3.tgz#a85cbdb3665ad4f7c7279d239a4581ec2eeef5a6"
+  integrity sha512-r4CpmCEF+e5PbFMBi64xSXmqn0uGgV4T7NWpGL4/A6KT/DTtIxALILQZq+l0ZdN1xm4RjOvqSDR22oT4il8rAQ==
   dependencies:
     aproba "^2.0.0"
     npm-registry-fetch "^13.0.0"
 
-libnpmpack@^4.0.1:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/libnpmpack/-/libnpmpack-4.0.1.tgz#c98111d92e440cd1fa18a0ab6384087df65947e4"
-  integrity sha512-Ozd/Hz3A+yrE3xhTc/bnoA0lnZb2HfQx0KP0sj6bXHe46hyCsmWCh8xuFXqtnH5FLwAhqI+kvd9HbV6DFACkFw==
+libnpmpack@^4.0.2:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/libnpmpack/-/libnpmpack-4.1.0.tgz#93a170b67bc52e15edc7b1f2e09b2c36e532b897"
+  integrity sha512-BHwojfEbJvVVJXivZjOCe3Y0IzQ47p6c/bfebrpzazuFNRoS9XOsbkncRbl3f23+u9b51eplzwaPh/5xSOAWHg==
   dependencies:
     "@npmcli/run-script" "^3.0.0"
-    npm-package-arg "^9.0.0"
-    pacote "^13.0.2"
+    npm-package-arg "^9.0.1"
+    pacote "^13.5.0"
 
-libnpmpublish@^6.0.1:
-  version "6.0.1"
-  resolved "https://registry.yarnpkg.com/libnpmpublish/-/libnpmpublish-6.0.1.tgz#ceace9648558e85958749071a4df5ff384fec32e"
-  integrity sha512-jcDlQhUBmp1cWStWIOS0Zwd1jm8/XmyBw3zstwNhFFTwrKd2GBcw1/8Vz9OPcLKEUrS6Tzv9b/CV/v5uBnUYlg==
+libnpmpublish@^6.0.2:
+  version "6.0.4"
+  resolved "https://registry.yarnpkg.com/libnpmpublish/-/libnpmpublish-6.0.4.tgz#adb41ec6b0c307d6f603746a4d929dcefb8f1a0b"
+  integrity sha512-lvAEYW8mB8QblL6Q/PI/wMzKNvIrF7Kpujf/4fGS/32a2i3jzUXi04TNyIBcK6dQJ34IgywfaKGh+Jq4HYPFmg==
   dependencies:
-    normalize-package-data "^3.0.2"
-    npm-package-arg "^9.0.0"
+    normalize-package-data "^4.0.0"
+    npm-package-arg "^9.0.1"
     npm-registry-fetch "^13.0.0"
-    semver "^7.1.3"
-    ssri "^8.0.1"
+    semver "^7.3.7"
+    ssri "^9.0.0"
 
-libnpmsearch@^5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/libnpmsearch/-/libnpmsearch-5.0.1.tgz#9b7f0f651e95e1419e40a4bb90e944650549b7de"
-  integrity sha512-O//WlHTQ/croL1oA+4oG1RQvS1O+Vu9oMQbXg78YGq1o5d37Ft11HeGi1hvHVCHTqighqRBIRm+s6RzTDlVAiQ==
+libnpmsearch@^5.0.2:
+  version "5.0.3"
+  resolved "https://registry.yarnpkg.com/libnpmsearch/-/libnpmsearch-5.0.3.tgz#ed502a4c2c70ea36723180455fae1357546b2184"
+  integrity sha512-Ofq76qKAPhxbiyzPf/5LPjJln26VTKwU9hIU0ACxQ6tNtBJ1CHmI7iITrdp7vNezhZc0FlkXwrIpqXjhBJZgLQ==
   dependencies:
     npm-registry-fetch "^13.0.0"
 
-libnpmteam@^4.0.1:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/libnpmteam/-/libnpmteam-4.0.1.tgz#0fb53142ffe4e84bcba94acb4a78867333925592"
-  integrity sha512-zM4dCkfHaLWGv5WL2p4XlzIr0GuwXEnu4DOH1dlvuwyH0J95y0wzjEXrlXrlfKrzNtTmuCCqzOs4SqC/kgA7Qg==
+libnpmteam@^4.0.2:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/libnpmteam/-/libnpmteam-4.0.3.tgz#9335fbbd032b3770f5c9b7ffc6203f47d1ed144a"
+  integrity sha512-LsYYLz4TlTpcqkusInY5MhKjiHFaCx1GV0LmydXJ/QMh+3IWBJpUhes4ynTZuFoJKkDIFjxyMU09ul+RZixgdg==
   dependencies:
     aproba "^2.0.0"
     npm-registry-fetch "^13.0.0"
 
 libnpmversion@^3.0.1:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/libnpmversion/-/libnpmversion-3.0.1.tgz#378ef2b092a4a633772b1e66620ce3c431dc3697"
-  integrity sha512-ZxOVWmMX+RBkOeJSiNPdhMqRaAOJXf3EDfvC6Mr90+NaM+gKptiw/NJBT3jKfZKbLn/wuC0Ey/sc4YNLoBk0Qw==
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/libnpmversion/-/libnpmversion-3.0.4.tgz#a30f563416ea1e2dd69878b4a9edf4eb4a070ef8"
+  integrity sha512-q5hvZlso0SMLgKm4AMtleRWtq4pERprebEGV6OwKi24efgAOgNDP98+jNUX2mIR2wp9eAa6ybkNNWu4yMaCsVw==
   dependencies:
     "@npmcli/git" "^3.0.0"
     "@npmcli/run-script" "^3.0.0"
     json-parse-even-better-errors "^2.3.1"
     proc-log "^2.0.0"
-    semver "^7.3.5"
-    stringify-package "^1.0.1"
+    semver "^7.3.7"
 
 libqp@1.1.0:
   version "1.1.0"
   resolved "https://registry.yarnpkg.com/libqp/-/libqp-1.1.0.tgz#f5e6e06ad74b794fb5b5b66988bf728ef1dedbe8"
-  integrity sha1-9ebgatdLeU+1tbZpiL9yjvHe2+g=
+  integrity sha512-4Rgfa0hZpG++t1Vi2IiqXG9Ad1ig4QTmtuZF946QJP4bPqOYC78ixUXgz5TW/wE7lNaNKlplSYTxQ+fR2KZ0EA==
 
-lilconfig@2.0.4, lilconfig@^2.0.4:
-  version "2.0.4"
-  resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.4.tgz#f4507d043d7058b380b6a8f5cb7bcd4b34cee082"
-  integrity sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==
+lilconfig@2.0.5:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.5.tgz#19e57fd06ccc3848fd1891655b5a447092225b25"
+  integrity sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==
+
+lilconfig@^2.0.5, lilconfig@^2.0.6:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.6.tgz#32a384558bd58af3d4c6e077dd1ad1d397bc69d4"
+  integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==
 
 line-height@0.3.1:
   version "0.3.1"
   resolved "https://registry.yarnpkg.com/line-height/-/line-height-0.3.1.tgz#4b1205edde182872a5efa3c8f620b3187a9c54c9"
-  integrity sha1-SxIF7d4YKHKl76PI9iCzGHqcVMk=
+  integrity sha512-YExecgqPwnp5gplD2+Y8e8A5+jKpr25+DzMbFdI1/1UAr0FJrTFv4VkHLf8/6B590i1wUPJWMKKldkd/bdQ//w==
   dependencies:
     computed-style "~0.1.3"
 
@@ -7057,33 +7901,48 @@ lines-and-columns@^1.1.6:
   resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
   integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
 
-linkify-it@3.0.3:
-  version "3.0.3"
-  resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.3.tgz#a98baf44ce45a550efb4d49c769d07524cc2fa2e"
-  integrity sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==
+linkify-it@4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-4.0.0.tgz#4f2d16879adc637cdfe9056cbc02de30e88ffa32"
+  integrity sha512-QAxkXyzT/TXgwGyY4rTgC95Ex6/lZ5/lYTV9nug6eJt93BCBQGOE47D/g2+/m5J1MrVLr2ot97OXkBZ9bBpR4A==
   dependencies:
     uc.micro "^1.0.1"
 
-lint-staged@^12.3.5:
-  version "12.3.5"
-  resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-12.3.5.tgz#8048ce048c3cac12f57200a06344a54dc91c8fa9"
-  integrity sha512-oOH36RUs1It7b9U/C7Nl/a0sLfoIBcMB8ramiB3nuJ6brBqzsWiUAFSR5DQ3yyP/OR7XKMpijtgKl2DV1lQ3lA==
+lint-staged@12.4.3:
+  version "12.4.3"
+  resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-12.4.3.tgz#914fa468458364e14cc952145db552d87c8847b6"
+  integrity sha512-eH6SKOmdm/ZwCRMTZAmM3q3dPkpq6vco/BfrOw8iGun4Xs/thYegPD/MLIwKO+iPkzibkLJuQcRhRLXKvaKreg==
   dependencies:
     cli-truncate "^3.1.0"
     colorette "^2.0.16"
-    commander "^8.3.0"
-    debug "^4.3.3"
+    commander "^9.3.0"
+    debug "^4.3.4"
     execa "^5.1.1"
-    lilconfig "2.0.4"
-    listr2 "^4.0.1"
-    micromatch "^4.0.4"
+    lilconfig "2.0.5"
+    listr2 "^4.0.5"
+    micromatch "^4.0.5"
     normalize-path "^3.0.0"
-    object-inspect "^1.12.0"
+    object-inspect "^1.12.2"
+    pidtree "^0.5.0"
     string-argv "^0.3.1"
-    supports-color "^9.2.1"
+    supports-color "^9.2.2"
     yaml "^1.10.2"
 
-listr2@^4.0.1:
+listr2@^3.8.3:
+  version "3.14.0"
+  resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.14.0.tgz#23101cc62e1375fd5836b248276d1d2b51fdbe9e"
+  integrity sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==
+  dependencies:
+    cli-truncate "^2.1.0"
+    colorette "^2.0.16"
+    log-update "^4.0.0"
+    p-map "^4.0.0"
+    rfdc "^1.3.0"
+    rxjs "^7.5.1"
+    through "^2.3.8"
+    wrap-ansi "^7.0.0"
+
+listr2@^4.0.5:
   version "4.0.5"
   resolved "https://registry.yarnpkg.com/listr2/-/listr2-4.0.5.tgz#9dcc50221583e8b4c71c43f9c7dfd0ef546b75d5"
   integrity sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==
@@ -7100,7 +7959,7 @@ listr2@^4.0.1:
 load-json-file@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b"
-  integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs=
+  integrity sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==
   dependencies:
     graceful-fs "^4.1.2"
     parse-json "^4.0.0"
@@ -7120,7 +7979,7 @@ load-json-file@^6.2.0:
 locate-path@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
-  integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=
+  integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==
   dependencies:
     p-locate "^2.0.0"
     path-exists "^3.0.0"
@@ -7147,57 +8006,57 @@ lodash-es@^4.17.21:
 lodash.capitalize@^4.2.1:
   version "4.2.1"
   resolved "https://registry.yarnpkg.com/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz#f826c9b4e2a8511d84e3aca29db05e1a4f3b72a9"
-  integrity sha1-+CbJtOKoUR2E46yinbBeGk87cqk=
+  integrity sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==
 
 lodash.castarray@^4.4.0:
   version "4.4.0"
   resolved "https://registry.yarnpkg.com/lodash.castarray/-/lodash.castarray-4.4.0.tgz#c02513515e309daddd4c24c60cfddcf5976d9115"
-  integrity sha1-wCUTUV4wna3dTCTGDP3c9ZdtkRU=
+  integrity sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==
 
 lodash.clonedeep@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
-  integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
+  integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==
 
 lodash.debounce@^4.0.8:
   version "4.0.8"
   resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
-  integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
+  integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
 
 lodash.escaperegexp@^4.1.2:
   version "4.1.2"
   resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347"
-  integrity sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=
+  integrity sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==
 
 lodash.get@^4.4.2:
   version "4.4.2"
   resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
-  integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
+  integrity sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==
 
 lodash.isequal@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
-  integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
+  integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
 
 lodash.ismatch@^4.4.0:
   version "4.4.0"
   resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37"
-  integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=
+  integrity sha512-fPMfXjGQEV9Xsq/8MTSgUf255gawYRbjwMyDbcvDhXgV7enSZA0hynz6vMPnpAb5iONEzBHBPsT+0zes5Z301g==
 
 lodash.isplainobject@^4.0.6:
   version "4.0.6"
   resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
-  integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
+  integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==
 
 lodash.isstring@^4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
-  integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=
+  integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==
 
 lodash.map@^4.5.1:
   version "4.6.0"
   resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3"
-  integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=
+  integrity sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q==
 
 lodash.merge@^4.6.2:
   version "4.6.2"
@@ -7209,31 +8068,44 @@ lodash.mergewith@^4.6.2:
   resolved "https://registry.yarnpkg.com/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz#617121f89ac55f59047c7aec1ccd6654c6590f55"
   integrity sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==
 
+lodash.once@^4.1.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
+  integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==
+
 lodash.pick@^4.4.0:
   version "4.4.0"
   resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3"
-  integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=
+  integrity sha512-hXt6Ul/5yWjfklSGvLQl8vM//l3FtyHZeuelpzK6mm99pNvN9yTDruNZPEJZD1oWrqo+izBmB7oUfWgcCX7s4Q==
 
 lodash.uniq@^4.5.0:
   version "4.5.0"
   resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
-  integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
+  integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==
 
 lodash.uniqby@^4.7.0:
   version "4.7.0"
   resolved "https://registry.yarnpkg.com/lodash.uniqby/-/lodash.uniqby-4.7.0.tgz#d99c07a669e9e6d24e1362dfe266c67616af1302"
-  integrity sha1-2ZwHpmnp5tJOE2Lf4mbGdhavEwI=
+  integrity sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==
 
 lodash.zipobject@^4.1.3:
   version "4.1.3"
   resolved "https://registry.yarnpkg.com/lodash.zipobject/-/lodash.zipobject-4.1.3.tgz#b399f5aba8ff62a746f6979bf20b214f964dbef8"
-  integrity sha1-s5n1q6j/YqdG9peb8gshT5ZNvvg=
+  integrity sha512-A9SzX4hMKWS25MyalwcOnNoplyHbkNVsjidhTp8ru0Sj23wY9GWBKS8gAIGDSAqeWjIjvE4KBEl24XXAs+v4wQ==
 
-lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4:
+lodash@4.17.21, lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4:
   version "4.17.21"
   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
   integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
 
+log-symbols@^4.0.0, log-symbols@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
+  integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==
+  dependencies:
+    chalk "^4.1.0"
+    is-unicode-supported "^0.1.0"
+
 log-update@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1"
@@ -7258,30 +8130,20 @@ logform@^2.3.2, logform@^2.4.0:
 long-timeout@0.1.1:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/long-timeout/-/long-timeout-0.1.1.tgz#9721d788b47e0bcb5a24c2e2bee1a0da55dab514"
-  integrity sha1-lyHXiLR+C8taJMLivuGg2lXatRQ=
+  integrity sha512-BFRuQUqc7x2NWxfJBCyUrN8iYUYznzL9JROmRz1gZ6KlOIgmoD+njPVbb+VNn2nGMKggMsK79iUNErillsrx7w==
 
 longest@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/longest/-/longest-2.0.1.tgz#781e183296aa94f6d4d916dc335d0d17aefa23f8"
-  integrity sha1-eB4YMpaqlPbU2RbcM10NF676I/g=
+  integrity sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==
 
-loose-envify@^1.1.0, loose-envify@^1.4.0:
+loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0:
   version "1.4.0"
   resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
   integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
   dependencies:
     js-tokens "^3.0.0 || ^4.0.0"
 
-lowercase-keys@^1.0.0, lowercase-keys@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
-  integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==
-
-lowercase-keys@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
-  integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
-
 lru-cache@^6.0.0:
   version "6.0.0"
   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
@@ -7289,10 +8151,10 @@ lru-cache@^6.0.0:
   dependencies:
     yallist "^4.0.0"
 
-lru-cache@^7.3.1, lru-cache@^7.4.1:
-  version "7.4.4"
-  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.4.4.tgz#a3dabc394ec07e2285af52fd24d0d74b3ac71c29"
-  integrity sha512-2XbUJmlpIbmc9JvNNmtLzHlF31srxoDxuiQiwBHic7RZyHyltbTdzoO6maRqpdEhOOG5GD80EXvzAU0wR15ccg==
+lru-cache@^7.4.4, lru-cache@^7.5.1, lru-cache@^7.7.1:
+  version "7.10.1"
+  resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.10.1.tgz#db577f42a94c168f676b638d15da8fb073448cab"
+  integrity sha512-BQuhQxPuRl79J5zSXRP+uNzPOyZw2oFI9JLRQ80XswSvg21KMKNtQza9eF42rfI/3Z40RvzBdXgziEkudzjo8A==
 
 luxon@^1.26.0:
   version "1.28.0"
@@ -7300,27 +8162,27 @@ luxon@^1.26.0:
   integrity sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ==
 
 mailparser@^3.3.0:
-  version "3.4.0"
-  resolved "https://registry.yarnpkg.com/mailparser/-/mailparser-3.4.0.tgz#249869bc5a41af9e0eabbf005197789442fbac9e"
-  integrity sha512-u2pfpLg+xr7m2FKDl+ohQhy2gMok1QZ+S9E5umS9ez5DSJWttrqSmBGswyj9F68pZMVTwbhLpBt7Kd04q/W4Vw==
+  version "3.5.0"
+  resolved "https://registry.yarnpkg.com/mailparser/-/mailparser-3.5.0.tgz#5b333b0ef2f063a7db9d24ed95f29efb464cbef3"
+  integrity sha512-mdr2DFgz8LKC0/Q6io6znA0HVnzaPFT0a4TTnLeZ7mWHlkfnm227Wxlq7mHh7AgeP32h7gOUpXvyhSfJJIEeyg==
   dependencies:
-    encoding-japanese "1.0.30"
+    encoding-japanese "2.0.0"
     he "1.2.0"
-    html-to-text "8.0.0"
+    html-to-text "8.2.0"
     iconv-lite "0.6.3"
-    libmime "5.0.0"
-    linkify-it "3.0.3"
-    mailsplit "5.3.1"
-    nodemailer "6.7.0"
-    tlds "1.224.0"
+    libmime "5.1.0"
+    linkify-it "4.0.0"
+    mailsplit "5.3.2"
+    nodemailer "6.7.3"
+    tlds "1.231.0"
 
-mailsplit@5.3.1:
-  version "5.3.1"
-  resolved "https://registry.yarnpkg.com/mailsplit/-/mailsplit-5.3.1.tgz#dd6d5c20a7b8a767fe9c9649dfcb26ee04f84c36"
-  integrity sha512-o6R6HCzqWYmI2/IYlB+v2IMPgYqC2EynmagZQICAhR7zAq0CO6fPcsO6CrYmVuYT+SSwvLAEZR5WniohBELcAA==
+mailsplit@5.3.2:
+  version "5.3.2"
+  resolved "https://registry.yarnpkg.com/mailsplit/-/mailsplit-5.3.2.tgz#c344c019f631be4f54d5213509637127e3e3dd66"
+  integrity sha512-coES12hhKqagkuBTJoqERX+y9bXNpxbxw3Esd07auuwKYmcagouVlgucyIVRp48fnswMKxcUtLoFn/L1a75ynQ==
   dependencies:
     libbase64 "1.2.1"
-    libmime "5.0.0"
+    libmime "5.1.0"
     libqp "1.1.0"
 
 make-dir@^2.1.0:
@@ -7343,27 +8205,27 @@ make-error@^1.1.1:
   resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
   integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
 
-make-fetch-happen@^10.0.3, make-fetch-happen@^10.0.5:
-  version "10.0.5"
-  resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-10.0.5.tgz#006e0c5579224832c732c35b7bcc43c8602da775"
-  integrity sha512-0JQ0daMRDFEv14DelmcFlprdhSDNG7WEgInTjBeWYWZ78W0jfDqygZdPLhcrQ4s/G8skNhBrS4fiF6xA+YlFjQ==
+make-fetch-happen@^10.0.3, make-fetch-happen@^10.0.6, make-fetch-happen@^10.1.5:
+  version "10.1.6"
+  resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-10.1.6.tgz#22b3ac3b077a7cfa80525af12e637e349f21d26e"
+  integrity sha512-/iKDlRQF0fkxyB/w/duW2yRYrGwBcbJjC37ijgi0CmOZ32bzMc86BCSSAHWvuyRFCB408iBPziTSzazBSrKo3w==
   dependencies:
     agentkeepalive "^4.2.1"
-    cacache "^15.3.0"
+    cacache "^16.1.0"
     http-cache-semantics "^4.1.0"
     http-proxy-agent "^5.0.0"
     https-proxy-agent "^5.0.0"
     is-lambda "^1.0.1"
-    lru-cache "^7.4.1"
+    lru-cache "^7.7.1"
     minipass "^3.1.6"
     minipass-collect "^1.0.2"
-    minipass-fetch "^2.0.2"
+    minipass-fetch "^2.0.3"
     minipass-flush "^1.0.5"
     minipass-pipeline "^1.2.4"
     negotiator "^0.6.3"
     promise-retry "^2.0.1"
     socks-proxy-agent "^6.1.1"
-    ssri "^8.0.1"
+    ssri "^9.0.0"
 
 make-fetch-happen@^9.1.0:
   version "9.1.0"
@@ -7395,7 +8257,7 @@ make-plural@^7.0.0:
 map-obj@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d"
-  integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=
+  integrity sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==
 
 map-obj@^4.0.0:
   version "4.3.0"
@@ -7415,9 +8277,9 @@ marked-terminal@^5.0.0:
     supports-hyperlinks "^2.2.0"
 
 marked@^4.0.10:
-  version "4.0.12"
-  resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.12.tgz#2262a4e6fd1afd2f13557726238b69a48b982f7d"
-  integrity sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==
+  version "4.0.16"
+  resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.16.tgz#9ec18fc1a723032eb28666100344d9428cf7a264"
+  integrity sha512-wahonIQ5Jnyatt2fn8KqF/nIqZM8mh3oRu2+l5EANGMhu6RFjiSG52QNE2eWzFMI94HqYSgN184NurgNG6CztA==
 
 math-interval-parser@^2.0.1:
   version "2.0.1"
@@ -7693,9 +8555,9 @@ micromark-util-encode@^1.0.0:
   integrity sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA==
 
 micromark-util-html-tag-name@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.0.0.tgz#75737e92fef50af0c6212bd309bc5cb8dbd489ed"
-  integrity sha512-NenEKIshW2ZI/ERv9HtFNsrn3llSPZtY337LID/24WeLqMzeZhBEE6BQ0vS2ZBjshm5n40chKtJ3qjAbVV8S0g==
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.1.0.tgz#eb227118befd51f48858e879b7a419fc0df20497"
+  integrity sha512-BKlClMmYROy9UiV03SwNmckkjn8QHVaWkqoAqzivabvdGcwNGMMMH/5szAnywmsTBUzDsU57/mFi0sp4BQO6dA==
 
 micromark-util-normalize-identifier@^1.0.0:
   version "1.0.0"
@@ -7763,13 +8625,13 @@ micromark@^3.0.0:
     micromark-util-types "^1.0.1"
     uvu "^0.5.0"
 
-micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4:
-  version "4.0.4"
-  resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9"
-  integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==
+micromatch@^4.0.0, micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5:
+  version "4.0.5"
+  resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
+  integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
   dependencies:
-    braces "^3.0.1"
-    picomatch "^2.2.3"
+    braces "^3.0.2"
+    picomatch "^2.3.1"
 
 mime-db@1.52.0:
   version "1.52.0"
@@ -7808,11 +8670,6 @@ mimic-fn@^2.1.0:
   resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
   integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
 
-mimic-response@^1.0.0, mimic-response@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
-  integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
-
 min-indent@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
@@ -7828,7 +8685,7 @@ minimalistic-assert@^1.0.0:
   resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
   integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
 
-minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.1.2:
+minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
   version "3.1.2"
   resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
   integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
@@ -7836,9 +8693,9 @@ minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.1.2:
     brace-expansion "^1.1.7"
 
 minimatch@^5.0.1:
-  version "5.0.1"
-  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b"
-  integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.0.tgz#1717b464f4971b144f6aabe8f2d0b8e4511e09c7"
+  integrity sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==
   dependencies:
     brace-expansion "^2.0.1"
 
@@ -7851,11 +8708,16 @@ minimist-options@4.1.0, minimist-options@^4.0.2:
     is-plain-obj "^1.1.0"
     kind-of "^6.0.3"
 
-minimist@1.2.5, minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5:
+minimist@1.2.5:
   version "1.2.5"
   resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
   integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
 
+minimist@1.2.6, minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6:
+  version "1.2.6"
+  resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
+  integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
+
 minipass-collect@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617"
@@ -7874,10 +8736,10 @@ minipass-fetch@^1.3.2:
   optionalDependencies:
     encoding "^0.1.12"
 
-minipass-fetch@^2.0.1, minipass-fetch@^2.0.2:
-  version "2.0.3"
-  resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-2.0.3.tgz#688bbd0c2b019642778dc808b6950dd908d192b3"
-  integrity sha512-VA+eiiUtaIvpQJXISwE3OiMvQwAWrgKb97F0aXlCS1Ahikr8fEQq8m3Hf7Kv9KT3nokuHigJKsDMB6atU04olQ==
+minipass-fetch@^2.0.3:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/minipass-fetch/-/minipass-fetch-2.1.0.tgz#ca1754a5f857a3be99a9271277246ac0b44c3ff8"
+  integrity sha512-H9U4UVBGXEyyWJnqYDCLp1PwD8XIkJ4akNHp1aGVI+2Ym7wQMlxDKi4IB4JbmyU+pl9pEs/cVrK6cOuvmbK4Sg==
   dependencies:
     minipass "^3.1.6"
     minipass-sized "^1.0.3"
@@ -7914,14 +8776,6 @@ minipass-sized@^1.0.3:
   dependencies:
     minipass "^3.0.0"
 
-minipass@^2.6.0, minipass@^2.9.0:
-  version "2.9.0"
-  resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
-  integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==
-  dependencies:
-    safe-buffer "^5.1.2"
-    yallist "^3.0.0"
-
 minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3, minipass@^3.1.6:
   version "3.1.6"
   resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee"
@@ -7929,13 +8783,6 @@ minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3, minipass@^3.
   dependencies:
     yallist "^4.0.0"
 
-minizlib@^1.3.3:
-  version "1.3.3"
-  resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
-  integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==
-  dependencies:
-    minipass "^2.9.0"
-
 minizlib@^2.0.0, minizlib@^2.1.1, minizlib@^2.1.2:
   version "2.1.2"
   resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
@@ -7953,12 +8800,12 @@ mkdirp-infer-owner@^2.0.0:
     infer-owner "^1.0.4"
     mkdirp "^1.0.3"
 
-mkdirp@^0.5.1, mkdirp@^0.5.4, mkdirp@^0.5.5:
-  version "0.5.5"
-  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
-  integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
+mkdirp@^0.5.4:
+  version "0.5.6"
+  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
+  integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
   dependencies:
-    minimist "^1.2.5"
+    minimist "^1.2.6"
 
 mkdirp@^1.0.3, mkdirp@^1.0.4:
   version "1.0.4"
@@ -7971,9 +8818,9 @@ modify-values@^1.0.0:
   integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
 
 moment@^2.29.1:
-  version "2.29.1"
-  resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
-  integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
+  version "2.29.3"
+  resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.3.tgz#edd47411c322413999f7a5940d526de183c031f3"
+  integrity sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==
 
 moo@^0.5.0, moo@^0.5.1:
   version "0.5.1"
@@ -8000,17 +8847,16 @@ ms@2.1.3, ms@^2.0.0, ms@^2.1.1, ms@^2.1.2:
   resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
   integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
 
-multer@^1.4.4:
-  version "1.4.4"
-  resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.4.tgz#e2bc6cac0df57a8832b858d7418ccaa8ebaf7d8c"
-  integrity sha512-2wY2+xD4udX612aMqMcB8Ws2Voq6NIUPEtD1be6m411T4uDH/VtL9i//xvcyFlTVfRdaBsk7hV5tgrGQqhuBiw==
+multer@^1.4.5-lts.1:
+  version "1.4.5-lts.1"
+  resolved "https://registry.yarnpkg.com/multer/-/multer-1.4.5-lts.1.tgz#803e24ad1984f58edffbc79f56e305aec5cfd1ac"
+  integrity sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==
   dependencies:
     append-field "^1.0.0"
-    busboy "^0.2.11"
+    busboy "^1.0.0"
     concat-stream "^1.5.2"
     mkdirp "^0.5.4"
     object-assign "^4.1.1"
-    on-finished "^2.3.0"
     type-is "^1.6.4"
     xtend "^4.0.0"
 
@@ -8040,11 +8886,16 @@ mute-stream@0.0.7:
   resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
   integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
 
-mute-stream@~0.0.4:
+mute-stream@0.0.8, mute-stream@~0.0.4:
   version "0.0.8"
   resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
   integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
 
+mylas@^2.1.9:
+  version "2.1.11"
+  resolved "https://registry.yarnpkg.com/mylas/-/mylas-2.1.11.tgz#1827462533977bed1c4251317aa84254e3ca94c7"
+  integrity sha512-krnPUl3n9/k52FGCltWMYcqp9SttxjRJEy0sWLk+g7mIa7wnZrmNSZ40Acx7ghzRSOsxt2rEqMbaq4jWlnTDKg==
+
 mz@^2.4.0:
   version "2.7.0"
   resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
@@ -8059,10 +8910,10 @@ nanoclone@^0.2.1:
   resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4"
   integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==
 
-nanoid@^3.1.30, nanoid@^3.3.1:
-  version "3.3.1"
-  resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35"
-  integrity sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==
+nanoid@^3.3.4:
+  version "3.3.4"
+  resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
+  integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
 
 natural-compare@^1.4.0:
   version "1.4.0"
@@ -8079,15 +8930,6 @@ nearley@^2.20.1:
     railroad-diagrams "^1.0.0"
     randexp "0.4.6"
 
-needle@^2.2.1:
-  version "2.9.1"
-  resolved "https://registry.yarnpkg.com/needle/-/needle-2.9.1.tgz#22d1dffbe3490c2b83e301f7709b6736cd8f2684"
-  integrity sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==
-  dependencies:
-    debug "^3.2.6"
-    iconv-lite "^0.4.4"
-    sax "^1.2.4"
-
 negotiator@0.6.3, negotiator@^0.6.2, negotiator@^0.6.3:
   version "0.6.3"
   resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
@@ -8103,35 +8945,43 @@ nerf-dart@^1.0.0:
   resolved "https://registry.yarnpkg.com/nerf-dart/-/nerf-dart-1.0.0.tgz#e6dab7febf5ad816ea81cf5c629c5a0ebde72c1a"
   integrity sha1-5tq3/r9a2Bbqgc9cYpxaDr3nLBo=
 
-next@12.1.0:
-  version "12.1.0"
-  resolved "https://registry.yarnpkg.com/next/-/next-12.1.0.tgz#c33d753b644be92fc58e06e5a214f143da61dd5d"
-  integrity sha512-s885kWvnIlxsUFHq9UGyIyLiuD0G3BUC/xrH0CEnH5lHEWkwQcHOORgbDF0hbrW9vr/7am4ETfX4A7M6DjrE7Q==
-  dependencies:
-    "@next/env" "12.1.0"
-    caniuse-lite "^1.0.30001283"
-    postcss "8.4.5"
-    styled-jsx "5.0.0"
-    use-subscription "1.5.1"
+next@12.2.5:
+  version "12.2.5"
+  resolved "https://registry.yarnpkg.com/next/-/next-12.2.5.tgz#14fb5975e8841fad09553b8ef41fe1393602b717"
+  integrity sha512-tBdjqX5XC/oFs/6gxrZhjmiq90YWizUYU6qOWAfat7zJwrwapJ+BYgX2PmiacunXMaRpeVT4vz5MSPSLgNkrpA==
+  dependencies:
+    "@next/env" "12.2.5"
+    "@swc/helpers" "0.4.3"
+    caniuse-lite "^1.0.30001332"
+    postcss "8.4.14"
+    styled-jsx "5.0.4"
+    use-sync-external-store "1.2.0"
   optionalDependencies:
-    "@next/swc-android-arm64" "12.1.0"
-    "@next/swc-darwin-arm64" "12.1.0"
-    "@next/swc-darwin-x64" "12.1.0"
-    "@next/swc-linux-arm-gnueabihf" "12.1.0"
-    "@next/swc-linux-arm64-gnu" "12.1.0"
-    "@next/swc-linux-arm64-musl" "12.1.0"
-    "@next/swc-linux-x64-gnu" "12.1.0"
-    "@next/swc-linux-x64-musl" "12.1.0"
-    "@next/swc-win32-arm64-msvc" "12.1.0"
-    "@next/swc-win32-ia32-msvc" "12.1.0"
-    "@next/swc-win32-x64-msvc" "12.1.0"
-
-node-addon-api@^3.0.0, node-addon-api@^3.1.0:
+    "@next/swc-android-arm-eabi" "12.2.5"
+    "@next/swc-android-arm64" "12.2.5"
+    "@next/swc-darwin-arm64" "12.2.5"
+    "@next/swc-darwin-x64" "12.2.5"
+    "@next/swc-freebsd-x64" "12.2.5"
+    "@next/swc-linux-arm-gnueabihf" "12.2.5"
+    "@next/swc-linux-arm64-gnu" "12.2.5"
+    "@next/swc-linux-arm64-musl" "12.2.5"
+    "@next/swc-linux-x64-gnu" "12.2.5"
+    "@next/swc-linux-x64-musl" "12.2.5"
+    "@next/swc-win32-arm64-msvc" "12.2.5"
+    "@next/swc-win32-ia32-msvc" "12.2.5"
+    "@next/swc-win32-x64-msvc" "12.2.5"
+
+node-addon-api@^3.1.0:
   version "3.2.1"
   resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161"
   integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==
 
-node-cache@^5.1.2:
+node-addon-api@^4.2.0:
+  version "4.3.0"
+  resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f"
+  integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==
+
+node-cache@5.1.2:
   version "5.1.2"
   resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-5.1.2.tgz#f264dc2ccad0a780e76253a694e9fd0ed19c398d"
   integrity sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==
@@ -8145,14 +8995,14 @@ node-emoji@^1.11.0:
   dependencies:
     lodash "^4.17.21"
 
-node-fetch@^2.6.0, node-fetch@^2.6.5, node-fetch@^2.6.7:
+node-fetch@^2.6.0, node-fetch@^2.6.7:
   version "2.6.7"
   resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
   integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
   dependencies:
     whatwg-url "^5.0.0"
 
-node-gyp@3.x, node-gyp@^8.4.1:
+node-gyp@8.4.1, node-gyp@8.x, node-gyp@^8.4.1:
   version "8.4.1"
   resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937"
   integrity sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==
@@ -8168,6 +9018,22 @@ node-gyp@3.x, node-gyp@^8.4.1:
     tar "^6.1.2"
     which "^2.0.2"
 
+node-gyp@9.1.0:
+  version "9.1.0"
+  resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-9.1.0.tgz#c8d8e590678ea1f7b8097511dedf41fc126648f8"
+  integrity sha512-HkmN0ZpQJU7FLbJauJTHkHlSVAXlNGDAzH/VYFZGDOnFyn/Na3GlNJfkudmufOdS6/jNFhy88ObzL7ERz9es1g==
+  dependencies:
+    env-paths "^2.2.0"
+    glob "^7.1.4"
+    graceful-fs "^4.2.6"
+    make-fetch-happen "^10.0.3"
+    nopt "^5.0.0"
+    npmlog "^6.0.0"
+    rimraf "^3.0.2"
+    semver "^7.3.5"
+    tar "^6.1.2"
+    which "^2.0.2"
+
 node-gyp@^9.0.0:
   version "9.0.0"
   resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-9.0.0.tgz#e1da2067427f3eb5bb56820cb62bc6b1e4bd2089"
@@ -8184,28 +9050,17 @@ node-gyp@^9.0.0:
     tar "^6.1.2"
     which "^2.0.2"
 
-node-pre-gyp@^0.11.0:
-  version "0.11.0"
-  resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz#db1f33215272f692cd38f03238e3e9b47c5dd054"
-  integrity sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==
-  dependencies:
-    detect-libc "^1.0.2"
-    mkdirp "^0.5.1"
-    needle "^2.2.1"
-    nopt "^4.0.1"
-    npm-packlist "^1.1.6"
-    npmlog "^4.0.2"
-    rc "^1.2.7"
-    rimraf "^2.6.1"
-    semver "^5.3.0"
-    tar "^4"
-
-node-releases@^2.0.2:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01"
-  integrity sha512-XxYDdcQ6eKqp/YjI+tb2C5WM2LgjnZrfYg4vgQt49EK268b6gYCHsBLrK2qvJo4FmCtqmKezb0WZFK4fkrZNsg==
+node-releases@^2.0.3:
+  version "2.0.5"
+  resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666"
+  integrity sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==
+
+node-releases@^2.0.6:
+  version "2.0.6"
+  resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503"
+  integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==
 
-node-schedule@^2.1.0:
+node-schedule@2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/node-schedule/-/node-schedule-2.1.0.tgz#068ae38d7351c330616f7fe7cdb05036f977cbaf"
   integrity sha512-nl4JTiZ7ZQDc97MmpTq9BQjYhq7gOtoh7SiPH069gBFBj0PzD8HI7zyFs6rzqL8Y5tTiEEYLxgtbx034YPrbyQ==
@@ -8214,20 +9069,25 @@ node-schedule@^2.1.0:
     long-timeout "0.1.1"
     sorted-array-functions "^1.3.0"
 
-nodemailer@6.7.0:
-  version "6.7.0"
-  resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.7.0.tgz#86614722c4e0c33d1b5b02aecb90d6d629932b0d"
-  integrity sha512-AtiTVUFHLiiDnMQ43zi0YgkzHOEWUkhDgPlBXrsDzJiJvB29Alo4OKxHQ0ugF3gRqRQIneCLtZU3yiUo7pItZw==
+nodemailer@6.7.3:
+  version "6.7.3"
+  resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.7.3.tgz#b73f9a81b9c8fa8acb4ea14b608f5e725ea8e018"
+  integrity sha512-KUdDsspqx89sD4UUyUKzdlUOper3hRkDVkrKh/89G+d9WKsU5ox51NWS4tB1XR5dPUdR4SP0E3molyEfOvSa3g==
+
+nodemailer@6.7.8:
+  version "6.7.8"
+  resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.7.8.tgz#9f1af9911314960c0b889079e1754e8d9e3f740a"
+  integrity sha512-2zaTFGqZixVmTxpJRCFC+Vk5eGRd/fYtvIR+dl5u9QXLTQWGIf48x/JXvo58g9sa0bU6To04XUv554Paykum3g==
 
 nodemailer@^6.6.3, nodemailer@^6.7.2:
-  version "6.7.2"
-  resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.7.2.tgz#44b2ad5f7ed71b7067f7a21c4fedabaec62b85e0"
-  integrity sha512-Dz7zVwlef4k5R71fdmxwR8Q39fiboGbu3xgswkzGwczUfjp873rVxt1O46+Fh0j1ORnAC6L9+heI8uUpO6DT7Q==
+  version "6.7.5"
+  resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.7.5.tgz#b30b1566f5fa2249f7bd49ced4c58bec6b25915e"
+  integrity sha512-6VtMpwhsrixq1HDYSBBHvW0GwiWawE75dS3oal48VqRhUvKJNnKnJo2RI/bCVQubj1vgrgscMNW4DHaD6xtMCg==
 
-nodemon@^2.0.15:
-  version "2.0.15"
-  resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.15.tgz#504516ce3b43d9dc9a955ccd9ec57550a31a8d4e"
-  integrity sha512-gdHMNx47Gw7b3kWxJV64NI+Q5nfl0y5DgDbiVtShiwa7Z0IZ07Ll4RLFo6AjrhzMtoEZn5PDE3/c2AbVsiCkpA==
+nodemon@2.0.19:
+  version "2.0.19"
+  resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.19.tgz#cac175f74b9cb8b57e770d47841995eebe4488bd"
+  integrity sha512-4pv1f2bMDj0Eeg/MhGqxrtveeQ5/G/UVe9iO6uTZzjnRluSA4PVWf8CW99LUPwGB3eNIA7zUFoP77YuI7hOc0A==
   dependencies:
     chokidar "^3.5.2"
     debug "^3.2.7"
@@ -8235,10 +9095,10 @@ nodemon@^2.0.15:
     minimatch "^3.0.4"
     pstree.remy "^1.1.8"
     semver "^5.7.1"
+    simple-update-notifier "^1.0.7"
     supports-color "^5.5.0"
     touch "^3.1.0"
     undefsafe "^2.0.5"
-    update-notifier "^5.1.0"
 
 noms@0.0.0:
   version "0.0.0"
@@ -8248,14 +9108,6 @@ noms@0.0.0:
     inherits "^2.0.1"
     readable-stream "~1.0.31"
 
-nopt@^4.0.1:
-  version "4.0.3"
-  resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
-  integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==
-  dependencies:
-    abbrev "1"
-    osenv "^0.1.4"
-
 nopt@^5.0.0:
   version "5.0.0"
   resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"
@@ -8280,7 +9132,7 @@ normalize-package-data@^2.5.0:
     semver "2 || 3 || 4 || 5"
     validate-npm-package-license "^3.0.1"
 
-normalize-package-data@^3.0.0, normalize-package-data@^3.0.2:
+normalize-package-data@^3.0.0:
   version "3.0.3"
   resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-3.0.3.tgz#dbcc3e2da59509a0983422884cd172eefdfa525e"
   integrity sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==
@@ -8290,6 +9142,16 @@ normalize-package-data@^3.0.0, normalize-package-data@^3.0.2:
     semver "^7.3.4"
     validate-npm-package-license "^3.0.1"
 
+normalize-package-data@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-4.0.0.tgz#1122d5359af21d4cd08718b92b058a658594177c"
+  integrity sha512-m+GL22VXJKkKbw62ZaBBjv8u6IE3UI4Mh5QakIqs3fWiKe0Xyi6L97hakwZK41/LD4R/2ly71Bayx0NLMwLA/g==
+  dependencies:
+    hosted-git-info "^5.0.0"
+    is-core-module "^2.8.1"
+    semver "^7.3.5"
+    validate-npm-package-license "^3.0.4"
+
 normalize-path@^3.0.0, normalize-path@~3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
@@ -8300,34 +9162,29 @@ normalize-range@^0.1.2:
   resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
   integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=
 
-normalize-url@^4.1.0:
-  version "4.5.1"
-  resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a"
-  integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==
-
 normalize-url@^6.0.0:
   version "6.1.0"
   resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a"
   integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==
 
-npm-audit-report@^2.1.5:
-  version "2.1.5"
-  resolved "https://registry.yarnpkg.com/npm-audit-report/-/npm-audit-report-2.1.5.tgz#a5b8850abe2e8452fce976c8960dd432981737b5"
-  integrity sha512-YB8qOoEmBhUH1UJgh1xFAv7Jg1d+xoNhsDYiFQlEFThEBui0W1vIz2ZK6FVg4WZjwEdl7uBQlm1jy3MUfyHeEw==
+npm-audit-report@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/npm-audit-report/-/npm-audit-report-3.0.0.tgz#1bf3e531208b5f77347c8d00c3d9badf5be30cd6"
+  integrity sha512-tWQzfbwz1sc4244Bx2BVELw0EmZlCsCF0X93RDcmmwhonCsPMoEviYsi+32R+mdRvOWXolPce9zo64n2xgPESw==
   dependencies:
     chalk "^4.0.0"
 
-npm-bundled@^1.0.1, npm-bundled@^1.1.1:
+npm-bundled@^1.1.1, npm-bundled@^1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1"
   integrity sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ==
   dependencies:
     npm-normalize-package-bin "^1.0.1"
 
-npm-install-checks@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-4.0.0.tgz#a37facc763a2fde0497ef2c6d0ac7c3fbe00d7b4"
-  integrity sha512-09OmyDkNLYwqKPOnbI8exiOZU2GVVmQp7tgez2BPi5OZC8M82elDAps7sxC4l//uSUtotWqoEIDwjRvWH4qz8w==
+npm-install-checks@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/npm-install-checks/-/npm-install-checks-5.0.0.tgz#5ff27d209a4e3542b8ac6b0c1db6063506248234"
+  integrity sha512-65lUsMI8ztHCxFz5ckCEC44DRvEGdZX5usQFriauxHEwt7upv1FKaQEmAtU0YnOAdwuNWCmk64xYiQABNrEyLA==
   dependencies:
     semver "^7.1.1"
 
@@ -8336,66 +9193,57 @@ npm-normalize-package-bin@^1.0.0, npm-normalize-package-bin@^1.0.1:
   resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2"
   integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==
 
-npm-package-arg@^9.0.0:
-  version "9.0.0"
-  resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-9.0.0.tgz#955a5e4735298fc23f71cb72da3574daa134340c"
-  integrity sha512-yhzXxeor+Zfhe5MGwPdDumz6HtNlj2pMekWB95IX3CC6uDNgde0oPKHDCLDPoJqQfd0HqAWt+y4Hs5m7CK1+9Q==
+npm-package-arg@^9.0.0, npm-package-arg@^9.0.1, npm-package-arg@^9.0.2:
+  version "9.0.2"
+  resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-9.0.2.tgz#f3ef7b1b3b02e82564af2d5228b4c36567dcd389"
+  integrity sha512-v/miORuX8cndiOheW8p2moNuPJ7QhcFh9WGlTorruG8hXSA23vMTEp5hTCmDxic0nD8KHhj/NQgFuySD3GYY3g==
   dependencies:
-    hosted-git-info "^4.1.0"
+    hosted-git-info "^5.0.0"
     semver "^7.3.5"
-    validate-npm-package-name "^3.0.0"
-
-npm-packlist@^1.1.6:
-  version "1.4.8"
-  resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e"
-  integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==
-  dependencies:
-    ignore-walk "^3.0.1"
-    npm-bundled "^1.0.1"
-    npm-normalize-package-bin "^1.0.1"
+    validate-npm-package-name "^4.0.0"
 
-npm-packlist@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-3.0.0.tgz#0370df5cfc2fcc8f79b8f42b37798dd9ee32c2a9"
-  integrity sha512-L/cbzmutAwII5glUcf2DBRNY/d0TFd4e/FnaZigJV6JD85RHZXJFGwCndjMWiiViiWSsWt3tiOLpI3ByTnIdFQ==
+npm-packlist@^5.1.0:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-5.1.0.tgz#f3fd52903a021009913a133732022132eb355ce7"
+  integrity sha512-a04sqF6FbkyOAFA19AA0e94gS7Et5T2/IMj3VOT9nOF2RaRdVPQ1Q17Fb/HaDRFs+gbC7HOmhVZ29adpWgmDZg==
   dependencies:
-    glob "^7.1.6"
-    ignore-walk "^4.0.1"
-    npm-bundled "^1.1.1"
+    glob "^8.0.1"
+    ignore-walk "^5.0.1"
+    npm-bundled "^1.1.2"
     npm-normalize-package-bin "^1.0.1"
 
-npm-pick-manifest@^7.0.0:
-  version "7.0.0"
-  resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-7.0.0.tgz#e3b18b09678a47e894f90941bef8204ea5d96c3b"
-  integrity sha512-njM1AcdioFaKd0JSGtLO09YA1WRwctjGQJbnHGmKS+u+uwP8oFvtZtOQWPYdxrnY5eJud3wn8OpH4sEIx6+GEQ==
+npm-pick-manifest@^7.0.0, npm-pick-manifest@^7.0.1:
+  version "7.0.1"
+  resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-7.0.1.tgz#76dda30a7cd6b99be822217a935c2f5eacdaca4c"
+  integrity sha512-IA8+tuv8KujbsbLQvselW2XQgmXWS47t3CB0ZrzsRZ82DbDfkcFunOaPm4X7qNuhMfq+FmV7hQT4iFVpHqV7mg==
   dependencies:
-    npm-install-checks "^4.0.0"
+    npm-install-checks "^5.0.0"
     npm-normalize-package-bin "^1.0.1"
     npm-package-arg "^9.0.0"
     semver "^7.3.5"
 
-npm-profile@^6.0.2:
-  version "6.0.2"
-  resolved "https://registry.yarnpkg.com/npm-profile/-/npm-profile-6.0.2.tgz#b2da9887d16d1f0d1ce8a9c3b37a48454a372919"
-  integrity sha512-0Fq8l+A10YXnnS63E3HThWjOb7+19Wsh1nOVutC2fKuowar8t/5PpINsbcm5xQ2dA28uAu+wjFfUyiEVSMz4Jw==
+npm-profile@^6.0.3:
+  version "6.0.3"
+  resolved "https://registry.yarnpkg.com/npm-profile/-/npm-profile-6.0.3.tgz#f4a11ce09467f00fa0832db7f27992e55fdfc94b"
+  integrity sha512-TVeHhnol2Iemud+Sr70/uqax5LnLJ9y361w+m5+Z7WYV2B1t6FhRDxDu72+yYYTvsgshkhnXEqbPjuD87kYXfA==
   dependencies:
-    npm-registry-fetch "^13.0.0"
+    npm-registry-fetch "^13.0.1"
     proc-log "^2.0.0"
 
-npm-registry-fetch@^13.0.0, npm-registry-fetch@^13.0.1:
-  version "13.0.1"
-  resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-13.0.1.tgz#ceecbaab9f1d0d911e1c01a5be2be96d45e472f5"
-  integrity sha512-Ak+LXVtSrCLOdscFW/apUw67OPNph8waHsPKM9UOJosL7i59EF5XoSWQMEsXEOeifM9Bb4/2+WrQC4t/pd8DGg==
+npm-registry-fetch@^13.0.0, npm-registry-fetch@^13.0.1, npm-registry-fetch@^13.1.1:
+  version "13.1.1"
+  resolved "https://registry.yarnpkg.com/npm-registry-fetch/-/npm-registry-fetch-13.1.1.tgz#26dc4b26d0a545886e807748032ba2aefaaae96b"
+  integrity sha512-5p8rwe6wQPLJ8dMqeTnA57Dp9Ox6GH9H60xkyJup07FmVlu3Mk7pf/kIIpl9gaN5bM8NM+UUx3emUWvDNTt39w==
   dependencies:
-    make-fetch-happen "^10.0.3"
+    make-fetch-happen "^10.0.6"
     minipass "^3.1.6"
-    minipass-fetch "^2.0.1"
+    minipass-fetch "^2.0.3"
     minipass-json-stream "^1.0.1"
     minizlib "^2.1.2"
-    npm-package-arg "^9.0.0"
+    npm-package-arg "^9.0.1"
     proc-log "^2.0.0"
 
-npm-run-path@^4.0.1:
+npm-run-path@^4.0.0, npm-run-path@^4.0.1:
   version "4.0.1"
   resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
   integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
@@ -8408,47 +9256,46 @@ npm-user-validate@^1.0.1:
   integrity sha512-uQwcd/tY+h1jnEaze6cdX/LrhWhoBxfSknxentoqmIuStxUExxjWd3ULMLFPiFUrZKbOVMowH6Jq2FRWfmhcEw==
 
 npm@^8.3.0:
-  version "8.5.4"
-  resolved "https://registry.yarnpkg.com/npm/-/npm-8.5.4.tgz#fd25b83b0a757d5b1c067be125c1a1cfb3c319c9"
-  integrity sha512-VnGLT4t88cUE78lLw5kxBwtLn2/Sx6O7Uw9dYwmq6AnF/taWHyMYQgDzUEsLhaXAVH7prG+sjG+MvxlHdIasgg==
+  version "8.11.0"
+  resolved "https://registry.yarnpkg.com/npm/-/npm-8.11.0.tgz#224fbca389252e43dd2a277249df3320a7f91189"
+  integrity sha512-4qmtwHa28J4SPmwCNoQI07KIF/ljmBhhuqG+xNXsIIRpwdKB5OXkMIGfH6KlThR6kzusxlkgR7t1haFDB88dcQ==
   dependencies:
     "@isaacs/string-locale-compare" "^1.1.0"
-    "@npmcli/arborist" "^5.0.2"
+    "@npmcli/arborist" "^5.0.4"
     "@npmcli/ci-detect" "^2.0.0"
-    "@npmcli/config" "^4.0.1"
-    "@npmcli/map-workspaces" "^2.0.2"
-    "@npmcli/package-json" "^1.0.1"
+    "@npmcli/config" "^4.1.0"
+    "@npmcli/fs" "^2.1.0"
+    "@npmcli/map-workspaces" "^2.0.3"
+    "@npmcli/package-json" "^2.0.0"
     "@npmcli/run-script" "^3.0.1"
     abbrev "~1.1.1"
-    ansicolors "~0.3.2"
-    ansistyles "~0.1.3"
     archy "~1.0.0"
-    cacache "^15.3.0"
+    cacache "^16.1.0"
     chalk "^4.1.2"
     chownr "^2.0.0"
     cli-columns "^4.0.0"
-    cli-table3 "^0.6.1"
+    cli-table3 "^0.6.2"
     columnify "^1.6.0"
     fastest-levenshtein "^1.0.12"
-    glob "^7.2.0"
-    graceful-fs "^4.2.9"
-    hosted-git-info "^4.1.0"
-    ini "^2.0.0"
-    init-package-json "^3.0.0"
+    glob "^8.0.1"
+    graceful-fs "^4.2.10"
+    hosted-git-info "^5.0.0"
+    ini "^3.0.0"
+    init-package-json "^3.0.2"
     is-cidr "^4.0.2"
     json-parse-even-better-errors "^2.3.1"
-    libnpmaccess "^6.0.1"
-    libnpmdiff "^4.0.1"
-    libnpmexec "^4.0.1"
+    libnpmaccess "^6.0.2"
+    libnpmdiff "^4.0.2"
+    libnpmexec "^4.0.2"
     libnpmfund "^3.0.1"
-    libnpmhook "^8.0.1"
-    libnpmorg "^4.0.1"
-    libnpmpack "^4.0.1"
-    libnpmpublish "^6.0.1"
-    libnpmsearch "^5.0.1"
-    libnpmteam "^4.0.1"
+    libnpmhook "^8.0.2"
+    libnpmorg "^4.0.2"
+    libnpmpack "^4.0.2"
+    libnpmpublish "^6.0.2"
+    libnpmsearch "^5.0.2"
+    libnpmteam "^4.0.2"
     libnpmversion "^3.0.1"
-    make-fetch-happen "^10.0.5"
+    make-fetch-happen "^10.1.5"
     minipass "^3.1.6"
     minipass-pipeline "^1.2.4"
     mkdirp "^1.0.4"
@@ -8456,44 +9303,34 @@ npm@^8.3.0:
     ms "^2.1.2"
     node-gyp "^9.0.0"
     nopt "^5.0.0"
-    npm-audit-report "^2.1.5"
-    npm-install-checks "^4.0.0"
-    npm-package-arg "^9.0.0"
-    npm-pick-manifest "^7.0.0"
-    npm-profile "^6.0.2"
-    npm-registry-fetch "^13.0.1"
+    npm-audit-report "^3.0.0"
+    npm-install-checks "^5.0.0"
+    npm-package-arg "^9.0.2"
+    npm-pick-manifest "^7.0.1"
+    npm-profile "^6.0.3"
+    npm-registry-fetch "^13.1.1"
     npm-user-validate "^1.0.1"
-    npmlog "^6.0.1"
+    npmlog "^6.0.2"
     opener "^1.5.2"
-    pacote "^13.0.3"
-    parse-conflict-json "^2.0.1"
-    proc-log "^2.0.0"
+    pacote "^13.4.1"
+    parse-conflict-json "^2.0.2"
+    proc-log "^2.0.1"
     qrcode-terminal "^0.12.0"
     read "~1.0.7"
-    read-package-json "^4.1.2"
+    read-package-json "^5.0.1"
     read-package-json-fast "^2.0.3"
     readdir-scoped-modules "^1.1.0"
     rimraf "^3.0.2"
-    semver "^7.3.5"
-    ssri "^8.0.1"
+    semver "^7.3.7"
+    ssri "^9.0.1"
     tar "^6.1.11"
     text-table "~0.2.0"
     tiny-relative-date "^1.3.0"
-    treeverse "^1.0.4"
-    validate-npm-package-name "~3.0.0"
+    treeverse "^2.0.0"
+    validate-npm-package-name "^4.0.0"
     which "^2.0.2"
     write-file-atomic "^4.0.1"
 
-npmlog@^4.0.2:
-  version "4.1.2"
-  resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
-  integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
-  dependencies:
-    are-we-there-yet "~1.1.2"
-    console-control-strings "~1.1.0"
-    gauge "~2.7.3"
-    set-blocking "~2.0.0"
-
 npmlog@^5.0.1:
   version "5.0.1"
   resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-5.0.1.tgz#f06678e80e29419ad67ab964e0fa69959c1eb8b0"
@@ -8504,49 +9341,49 @@ npmlog@^5.0.1:
     gauge "^3.0.0"
     set-blocking "^2.0.0"
 
-npmlog@^6.0.0, npmlog@^6.0.1:
-  version "6.0.1"
-  resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.1.tgz#06f1344a174c06e8de9c6c70834cfba2964bba17"
-  integrity sha512-BTHDvY6nrRHuRfyjt1MAufLxYdVXZfd099H4+i1f0lPywNQyI4foeNXJRObB/uy+TYqUW0vAD9gbdSOXPst7Eg==
+npmlog@^6.0.0, npmlog@^6.0.2:
+  version "6.0.2"
+  resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-6.0.2.tgz#c8166017a42f2dea92d6453168dd865186a70830"
+  integrity sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==
   dependencies:
     are-we-there-yet "^3.0.0"
     console-control-strings "^1.1.0"
-    gauge "^4.0.0"
+    gauge "^4.0.3"
     set-blocking "^2.0.0"
 
 nth-check@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2"
-  integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
+  integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==
   dependencies:
     boolbase "^1.0.0"
 
-number-is-nan@^1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
-  integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
-
 oauth-sign@~0.9.0:
   version "0.9.0"
   resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
   integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
 
-object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
+object-assign@^4.0.1, object-assign@^4.1.1:
   version "4.1.1"
   resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
   integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
 
-object-hash@^2.0.1, object-hash@^2.2.0:
+object-hash@^2.0.1:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5"
   integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==
 
-object-inspect@^1.11.0, object-inspect@^1.12.0, object-inspect@^1.9.0:
-  version "1.12.0"
-  resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0"
-  integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==
+object-hash@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9"
+  integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==
+
+object-inspect@^1.12.0, object-inspect@^1.12.2, object-inspect@^1.9.0:
+  version "1.12.2"
+  resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
+  integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==
 
-object-keys@^1.0.12, object-keys@^1.1.1:
+object-keys@^1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
   integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
@@ -8579,13 +9416,13 @@ object.fromentries@^2.0.5:
     define-properties "^1.1.3"
     es-abstract "^1.19.1"
 
-object.hasown@^1.1.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.0.tgz#7232ed266f34d197d15cac5880232f7a4790afe5"
-  integrity sha512-MhjYRfj3GBlhSkDHo6QmvgjRLXQ2zndabdf3nX0yTyZK9rPfxb6uRpAac8HXNLy1GpqWtZ81Qh4v3uOls2sRAg==
+object.hasown@^1.1.1:
+  version "1.1.1"
+  resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.1.tgz#ad1eecc60d03f49460600430d97f23882cf592a3"
+  integrity sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==
   dependencies:
-    define-properties "^1.1.3"
-    es-abstract "^1.19.1"
+    define-properties "^1.1.4"
+    es-abstract "^1.19.5"
 
 object.values@^1.1.5:
   version "1.1.5"
@@ -8596,20 +9433,13 @@ object.values@^1.1.5:
     define-properties "^1.1.3"
     es-abstract "^1.19.1"
 
-on-finished@^2.3.0:
+on-finished@2.4.1:
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
   integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
   dependencies:
     ee-first "1.1.1"
 
-on-finished@~2.3.0:
-  version "2.3.0"
-  resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
-  integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
-  dependencies:
-    ee-first "1.1.1"
-
 on-headers@~1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
@@ -8663,10 +9493,10 @@ opener@^1.5.2:
   resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598"
   integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==
 
-openpgp@^5.2.0:
-  version "5.2.0"
-  resolved "https://registry.yarnpkg.com/openpgp/-/openpgp-5.2.0.tgz#1275fea03893c7a0081abd2dccaec8124ee687dc"
-  integrity sha512-ZDrvSMq2KZTTWnFV6bSO70HlyAX9uIu2QO/jX+Pd5lb+fewzwsnWHnzN2ZWp++QyM8ifyBPkrD7ZGFq279mpMA==
+openpgp@5.4.0:
+  version "5.4.0"
+  resolved "https://registry.yarnpkg.com/openpgp/-/openpgp-5.4.0.tgz#679e7ce1c97994d72545bf5be818de15e5707b52"
+  integrity sha512-XgQnK8SYy4Ycg9BDvrXTE4foMwME/+1EfGZWZirUU2VPzU1X3xx094fChjbP10+gUJifAcoWTsT2zAbdhFUxyg==
   dependencies:
     asn1.js "^5.0.0"
 
@@ -8682,28 +9512,30 @@ optionator@^0.9.1:
     type-check "^0.4.0"
     word-wrap "^1.2.3"
 
-os-homedir@^1.0.0:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
-  integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
+ora@^5.4.1:
+  version "5.4.1"
+  resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18"
+  integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==
+  dependencies:
+    bl "^4.1.0"
+    chalk "^4.1.0"
+    cli-cursor "^3.1.0"
+    cli-spinners "^2.5.0"
+    is-interactive "^1.0.0"
+    is-unicode-supported "^0.1.0"
+    log-symbols "^4.1.0"
+    strip-ansi "^6.0.0"
+    wcwidth "^1.0.1"
 
-os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
+os-tmpdir@~1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
   integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
 
-osenv@^0.1.4:
-  version "0.1.5"
-  resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
-  integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
-  dependencies:
-    os-homedir "^1.0.0"
-    os-tmpdir "^1.0.0"
-
-p-cancelable@^1.0.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc"
-  integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==
+ospath@^1.2.2:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b"
+  integrity sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==
 
 p-each-series@^2.1.0:
   version "2.2.0"
@@ -8782,11 +9614,11 @@ p-reduce@^2.0.0:
   integrity sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==
 
 p-retry@^4.0.0:
-  version "4.6.1"
-  resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.1.tgz#8fcddd5cdf7a67a0911a9cf2ef0e5df7f602316c"
-  integrity sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA==
+  version "4.6.2"
+  resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16"
+  integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==
   dependencies:
-    "@types/retry" "^0.12.0"
+    "@types/retry" "0.12.0"
     retry "^0.13.1"
 
 p-try@^1.0.0:
@@ -8799,41 +9631,31 @@ p-try@^2.0.0:
   resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
   integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
 
-package-json@^6.3.0:
-  version "6.5.0"
-  resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0"
-  integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==
-  dependencies:
-    got "^9.6.0"
-    registry-auth-token "^4.0.0"
-    registry-url "^5.0.0"
-    semver "^6.2.0"
-
-pacote@^13.0.1, pacote@^13.0.2, pacote@^13.0.3:
-  version "13.0.3"
-  resolved "https://registry.yarnpkg.com/pacote/-/pacote-13.0.3.tgz#0b9654c1aa5eb2b9af28aa259f15e556e7187422"
-  integrity sha512-8thQ06YoO01O1k5rvSpHS/XPJZucw2DPiiT1jI+ys8QaTN6ifAyxfyoABHBa8nIt/4wPdzly4GEPqshctHFoYA==
+pacote@^13.0.3, pacote@^13.0.5, pacote@^13.4.1, pacote@^13.5.0:
+  version "13.5.0"
+  resolved "https://registry.yarnpkg.com/pacote/-/pacote-13.5.0.tgz#e2c745dc320513a98b9403e92b366a1ba6a4db94"
+  integrity sha512-yekp0ykEsaBH0t0bYA/89R+ywdYV5ZnEdg4YMIfqakSlpIhoF6b8+aEUm8NZpfWRgmy6lxgywcW05URhLRogVQ==
   dependencies:
     "@npmcli/git" "^3.0.0"
     "@npmcli/installed-package-contents" "^1.0.7"
-    "@npmcli/promise-spawn" "^1.2.0"
-    "@npmcli/run-script" "^3.0.0"
-    cacache "^15.3.0"
+    "@npmcli/promise-spawn" "^3.0.0"
+    "@npmcli/run-script" "^3.0.1"
+    cacache "^16.0.0"
     chownr "^2.0.0"
     fs-minipass "^2.1.0"
     infer-owner "^1.0.4"
     minipass "^3.1.6"
     mkdirp "^1.0.4"
     npm-package-arg "^9.0.0"
-    npm-packlist "^3.0.0"
+    npm-packlist "^5.1.0"
     npm-pick-manifest "^7.0.0"
-    npm-registry-fetch "^13.0.0"
+    npm-registry-fetch "^13.0.1"
     proc-log "^2.0.0"
     promise-retry "^2.0.1"
-    read-package-json "^4.1.1"
+    read-package-json "^5.0.0"
     read-package-json-fast "^2.0.3"
     rimraf "^3.0.2"
-    ssri "^8.0.1"
+    ssri "^9.0.0"
     tar "^6.1.11"
 
 parent-module@^1.0.0:
@@ -8843,14 +9665,14 @@ parent-module@^1.0.0:
   dependencies:
     callsites "^3.0.0"
 
-parse-conflict-json@^2.0.1:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/parse-conflict-json/-/parse-conflict-json-2.0.1.tgz#76647dd072e6068bcaff20be6ccea68a18e1fb58"
-  integrity sha512-Y7nYw+QaSGBto1LB9lgwOR05Rtz5SbuTf+Oe7HJ6SYQ/DHsvRjQ8O03oWdJbvkt6GzDWospgyZbGmjDYL0sDgA==
+parse-conflict-json@^2.0.1, parse-conflict-json@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/parse-conflict-json/-/parse-conflict-json-2.0.2.tgz#3d05bc8ffe07d39600dc6436c6aefe382033d323"
+  integrity sha512-jDbRGb00TAPFsKWCpZZOT93SxVP9nONOSgES3AevqRq/CHvavEBvKAjxX9p5Y5F0RZLxH9Ufd9+RwtCsa+lFDA==
   dependencies:
     json-parse-even-better-errors "^2.3.1"
     just-diff "^5.0.1"
-    just-diff-apply "^4.0.1"
+    just-diff-apply "^5.2.0"
 
 parse-json@^4.0.0:
   version "4.0.0"
@@ -8875,12 +9697,20 @@ parse-passwd@^1.0.0:
   resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6"
   integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=
 
-parse5-htmlparser2-tree-adapter@^6.0.0, parse5-htmlparser2-tree-adapter@^6.0.1:
+parse5-htmlparser2-tree-adapter@^6.0.0:
   version "6.0.1"
   resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz#2cdf9ad823321140370d4dbf5d3e92c7c8ddc6e6"
   integrity sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==
   dependencies:
-    parse5 "^6.0.1"
+    parse5 "^6.0.1"
+
+parse5-htmlparser2-tree-adapter@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1"
+  integrity sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==
+  dependencies:
+    domhandler "^5.0.2"
+    parse5 "^7.0.0"
 
 parse5@^5.1.1:
   version "5.1.1"
@@ -8892,6 +9722,13 @@ parse5@^6.0.1:
   resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
   integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==
 
+parse5@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.0.0.tgz#51f74a5257f5fcc536389e8c2d0b3802e1bfa91a"
+  integrity sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==
+  dependencies:
+    entities "^4.3.0"
+
 parseley@^0.7.0:
   version "0.7.0"
   resolved "https://registry.yarnpkg.com/parseley/-/parseley-0.7.0.tgz#9949e3a0ed05c5072adb04f013c2810cf49171a8"
@@ -8936,15 +9773,20 @@ path-to-regexp@0.1.7:
   integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=
 
 path-to-regexp@^6.2.0:
-  version "6.2.0"
-  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.0.tgz#f7b3803336104c346889adece614669230645f38"
-  integrity sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg==
+  version "6.2.1"
+  resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.1.tgz#d54934d6798eb9e5ef14e7af7962c945906918e5"
+  integrity sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==
 
 path-type@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
   integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
 
+pend@~1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
+  integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==
+
 performance-now@^2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
@@ -8955,11 +9797,21 @@ picocolors@^1.0.0:
   resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
   integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
 
-picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3:
+picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
   version "2.3.1"
   resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
   integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
 
+pidtree@^0.5.0:
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.5.0.tgz#ad5fbc1de78b8a5f99d6fbdd4f6e4eee21d1aca1"
+  integrity sha512-9nxspIM7OpZuhBxPg73Zvyq7j1QMPMPsGKTqRc2XOaFQauDvoNz9fM1Wdkjmeo7l9GXOZiRs97sPkuayl39wjA==
+
+pify@^2.2.0, pify@^2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+  integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
+
 pify@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
@@ -8998,7 +9850,7 @@ plex-api-headers@1.1.0:
   resolved "https://registry.yarnpkg.com/plex-api-headers/-/plex-api-headers-1.1.0.tgz#4ce364715d9648cccf2c064583279ef87c12fbf2"
   integrity sha1-TONkcV2WSMzPLAZFgyee+HwS+/I=
 
-plex-api@^5.3.2:
+plex-api@5.3.2:
   version "5.3.2"
   resolved "https://registry.yarnpkg.com/plex-api/-/plex-api-5.3.2.tgz#b95ec60a35b9d3c111ffcf7b0e196372225564e3"
   integrity sha512-RCFMQKu1cx+G4Y/8NfaifWEWEyhFFUV/d1/qAD4O1Si/IeA1S4hueC9py0uzFKR2iz+knuEPtVXtq9Upc9GImg==
@@ -9009,6 +9861,22 @@ plex-api@^5.3.2:
     uuid "^3.0.0"
     xml2js "0.4.16"
 
+plimit-lit@^1.2.6:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/plimit-lit/-/plimit-lit-1.3.0.tgz#46908adbfcfc010e65a5a737652768b0fec21587"
+  integrity sha512-63qOoSzggsjBHPVbaKeEtsO8oWTeyJxUfVRLkoc59pRkDiCCLvqn2tCgAkfbejrx+V5zJtlG2wqkk/Db6cwlVQ==
+  dependencies:
+    queue-lit "^1.3.0"
+
+postcss-import@^14.1.0:
+  version "14.1.0"
+  resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-14.1.0.tgz#a7333ffe32f0b8795303ee9e40215dac922781f0"
+  integrity sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==
+  dependencies:
+    postcss-value-parser "^4.0.0"
+    read-cache "^1.0.0"
+    resolve "^1.1.7"
+
 postcss-js@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.0.tgz#31db79889531b80dc7bc9b0ad283e418dce0ac00"
@@ -9016,12 +9884,12 @@ postcss-js@^4.0.0:
   dependencies:
     camelcase-css "^2.0.1"
 
-postcss-load-config@^3.1.0:
-  version "3.1.3"
-  resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.3.tgz#21935b2c43b9a86e6581a576ca7ee1bde2bd1d23"
-  integrity sha512-5EYgaM9auHGtO//ljHH+v/aC/TQ5LHXtL7bQajNAUBKUVKiYE8rYpFms7+V26D9FncaGe2zwCoPQsFKb5zF/Hw==
+postcss-load-config@^3.1.4:
+  version "3.1.4"
+  resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.4.tgz#1ab2571faf84bb078877e1d07905eabe9ebda855"
+  integrity sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==
   dependencies:
-    lilconfig "^2.0.4"
+    lilconfig "^2.0.5"
     yaml "^1.10.2"
 
 postcss-nested@5.0.6:
@@ -9031,34 +9899,34 @@ postcss-nested@5.0.6:
   dependencies:
     postcss-selector-parser "^6.0.6"
 
-postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.9:
-  version "6.0.9"
-  resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f"
-  integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ==
+postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.6:
+  version "6.0.10"
+  resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d"
+  integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==
   dependencies:
     cssesc "^3.0.0"
     util-deprecate "^1.0.2"
 
-postcss-value-parser@^4.2.0:
+postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
   integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
 
-postcss@8.4.5:
-  version "8.4.5"
-  resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95"
-  integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==
+postcss@8.4.14, postcss@^8.4.14:
+  version "8.4.14"
+  resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf"
+  integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==
   dependencies:
-    nanoid "^3.1.30"
+    nanoid "^3.3.4"
     picocolors "^1.0.0"
-    source-map-js "^1.0.1"
+    source-map-js "^1.0.2"
 
-postcss@^8.4.6, postcss@^8.4.8:
-  version "8.4.8"
-  resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.8.tgz#dad963a76e82c081a0657d3a2f3602ce10c2e032"
-  integrity sha512-2tXEqGxrjvAO6U+CJzDL2Fk2kPHTv1jQsYkSoMeOis2SsYaXRO2COxTdQp99cYvif9JTXaAk9lYGc3VhJt7JPQ==
+postcss@8.4.16:
+  version "8.4.16"
+  resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.16.tgz#33a1d675fac39941f5f445db0de4db2b6e01d43c"
+  integrity sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==
   dependencies:
-    nanoid "^3.3.1"
+    nanoid "^3.3.4"
     picocolors "^1.0.0"
     source-map-js "^1.0.2"
 
@@ -9067,11 +9935,6 @@ prelude-ls@^1.2.1:
   resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
   integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
 
-prepend-http@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
-  integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=
-
 prettier-linter-helpers@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b"
@@ -9079,15 +9942,25 @@ prettier-linter-helpers@^1.0.0:
   dependencies:
     fast-diff "^1.1.2"
 
-prettier-plugin-tailwindcss@^0.1.8:
-  version "0.1.8"
-  resolved "https://registry.yarnpkg.com/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.1.8.tgz#ba0f606ed91959ede670303d905b99106e9e6293"
-  integrity sha512-hwarSBCswAXa+kqYtaAkFr3Vop9o04WOyZs0qo3NyvW8L7f1rif61wRyq0+ArmVThOuRBcJF5hjGXYk86cwemg==
+prettier-plugin-organize-imports@3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-3.1.0.tgz#00420affd69f21926dbf29bf94a152f37e859d5e"
+  integrity sha512-eufD78FKdkDTyyY9oKxuwEMrfz4/AXrGeyeyjqiRtSBr01DAdGFTq4SgIKvLeqlLkq+ZPJ2H0+BK0e6flRUwJQ==
 
-prettier@^2.5.1:
-  version "2.5.1"
-  resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a"
-  integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==
+prettier-plugin-tailwindcss@0.1.13:
+  version "0.1.13"
+  resolved "https://registry.yarnpkg.com/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.1.13.tgz#ca1071361dc7e2ed5d95a2ee36825ce45f814942"
+  integrity sha512-/EKQURUrxLu66CMUg4+1LwGdxnz8of7IDvrSLqEtDqhLH61SAlNNUSr90UTvZaemujgl3OH/VHg+fyGltrNixw==
+
+prettier@2.7.1:
+  version "2.7.1"
+  resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64"
+  integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==
+
+pretty-bytes@^5.6.0:
+  version "5.6.0"
+  resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"
+  integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==
 
 preview-email@^3.0.5:
   version "3.0.5"
@@ -9102,10 +9975,10 @@ preview-email@^3.0.5:
     pug "^3.0.2"
     uuid "^8.3.2"
 
-proc-log@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-2.0.0.tgz#25f8cb346a5d08e27f2422b3ca6ba8379bcbf8ba"
-  integrity sha512-I/35MfCX2H8jBUhKN8JB8nmqvQo/nKdrBodBY7L3RhDSPPyvOHwLYNmPuhwuJq7a7C3vgFKWGQM+ecPStcvOHA==
+proc-log@^2.0.0, proc-log@^2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/proc-log/-/proc-log-2.0.1.tgz#8f3f69a1f608de27878f91f5c688b225391cb685"
+  integrity sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==
 
 process-nextick-args@~2.0.0:
   version "2.0.1"
@@ -9176,6 +10049,11 @@ proxy-addr@~2.0.7:
     forwarded "0.2.0"
     ipaddr.js "1.9.1"
 
+proxy-from-env@1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee"
+  integrity sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==
+
 psl@^1.1.28:
   version "1.8.0"
   resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
@@ -9275,7 +10153,7 @@ pug-walk@^2.0.0:
   resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-2.0.0.tgz#417aabc29232bb4499b5b5069a2b2d2a24d5f5fe"
   integrity sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==
 
-pug@^3.0.2:
+pug@3.0.2, pug@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/pug/-/pug-3.0.2.tgz#f35c7107343454e43bc27ae0ff76c731b78ea535"
   integrity sha512-bp0I/hiK1D1vChHh6EfDxtndHji55XP/ZJKwsRqrz6lRia6ZC2OZbdAymlxdVFwd1L70ebrVJw4/eZ79skrIaw==
@@ -9289,6 +10167,11 @@ pug@^3.0.2:
     pug-runtime "^3.0.1"
     pug-strip-comments "^2.0.0"
 
+pulltorefreshjs@0.1.22:
+  version "0.1.22"
+  resolved "https://registry.yarnpkg.com/pulltorefreshjs/-/pulltorefreshjs-0.1.22.tgz#ddb5e3feee0b2a49fd46e1b18e84fffef2c47ac0"
+  integrity sha512-haxNVEHnS4NCQA7NeG7TSV69z4uqy/N7nfPRuc4dPWe8H6ygUrMjdNeohE+6v0lVVX/ukSjbLYwPUGUYtFKfvQ==
+
 pump@^3.0.0:
   version "3.0.0"
   resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
@@ -9302,13 +10185,6 @@ punycode@^2.1.0, punycode@^2.1.1:
   resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
   integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
 
-pupa@^2.1.1:
-  version "2.1.1"
-  resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.1.1.tgz#f5e8fd4afc2c5d97828faa523549ed8744a20d62"
-  integrity sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==
-  dependencies:
-    escape-goat "^2.0.0"
-
 q@^1.5.1:
   version "1.5.1"
   resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
@@ -9319,12 +10195,7 @@ qrcode-terminal@^0.12.0:
   resolved "https://registry.yarnpkg.com/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz#bb5b699ef7f9f0505092a3748be4464fe71b5819"
   integrity sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==
 
-qs@6.9.7:
-  version "6.9.7"
-  resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe"
-  integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==
-
-qs@^6.10.3:
+qs@6.10.3, qs@^6.10.3:
   version "6.10.3"
   resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e"
   integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==
@@ -9336,6 +10207,11 @@ qs@~6.5.2:
   resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad"
   integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==
 
+queue-lit@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/queue-lit/-/queue-lit-1.3.0.tgz#a29e4cfd0d0e2c6594beb70a4726716a57ffce5b"
+  integrity sha512-3HpQ7bD2ct56qPithPr5IzH2Oij3WVPcgevCJ+mI9HAfVJKCqQ2yiFYgb4AUkLfsCmmbVDy9luvE97Ztzr5eBg==
+
 queue-microtask@^1.2.2:
   version "1.2.3"
   resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
@@ -9374,17 +10250,17 @@ range-parser@~1.2.1:
   resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
   integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
 
-raw-body@2.4.3:
-  version "2.4.3"
-  resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.3.tgz#8f80305d11c2a0a545c2d9d89d7a0286fcead43c"
-  integrity sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==
+raw-body@2.5.1:
+  version "2.5.1"
+  resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857"
+  integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==
   dependencies:
     bytes "3.1.2"
-    http-errors "1.8.1"
+    http-errors "2.0.0"
     iconv-lite "0.4.24"
     unpipe "1.0.0"
 
-rc@^1.2.7, rc@^1.2.8:
+rc@^1.2.8:
   version "1.2.8"
   resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
   integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
@@ -9394,82 +10270,87 @@ rc@^1.2.7, rc@^1.2.8:
     minimist "^1.2.0"
     strip-json-comments "~2.0.1"
 
-react-ace@^9.5.0:
-  version "9.5.0"
-  resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-9.5.0.tgz#b6c32b70d404dd821a7e01accc2d76da667ff1f7"
-  integrity sha512-4l5FgwGh6K7A0yWVMQlPIXDItM4Q9zzXRqOae8KkCl6MkOob7sC1CzHxZdOGvV+QioKWbX2p5HcdOVUv6cAdSg==
+react-ace@10.1.0:
+  version "10.1.0"
+  resolved "https://registry.yarnpkg.com/react-ace/-/react-ace-10.1.0.tgz#d348eac2b16475231779070b6cd16768deed565f"
+  integrity sha512-VkvUjZNhdYTuKOKQpMIZi7uzZZVgzCjM7cLYu6F64V0mejY8a2XTyPUIMszC6A4trbeMIHbK5fYFcT/wkP/8VA==
   dependencies:
-    ace-builds "^1.4.13"
+    ace-builds "^1.4.14"
     diff-match-patch "^1.0.5"
     lodash.get "^4.4.2"
     lodash.isequal "^4.5.0"
     prop-types "^15.7.2"
 
-react-animate-height@^2.0.23:
-  version "2.0.23"
-  resolved "https://registry.yarnpkg.com/react-animate-height/-/react-animate-height-2.0.23.tgz#2e14ac707b20ae67b87766ccfd581e693e0e7ec7"
-  integrity sha512-DucSC/1QuxWEFzR9IsHMzrf2nrcZ6qAmLIFoENa2kLK7h72XybcMA9o073z7aHccFzdMEW0/fhAdnQG7a4rDow==
+react-animate-height@2.1.2:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/react-animate-height/-/react-animate-height-2.1.2.tgz#9b450fc64d46f10f5e07da8d0d5e2c47b9f15030"
+  integrity sha512-A9jfz/4CTdsIsE7WCQtO9UkOpMBcBRh8LxyHl2eoZz1ki02jpyUL5xt58gabd0CyeLQ8fRyQ+s2lyV2Ufu8Owg==
   dependencies:
     classnames "^2.2.5"
     prop-types "^15.6.1"
 
-react-dom@17.0.2:
-  version "17.0.2"
-  resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
-  integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
+react-dom@18.2.0:
+  version "18.2.0"
+  resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
+  integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
   dependencies:
     loose-envify "^1.1.0"
-    object-assign "^4.1.1"
-    scheduler "^0.20.2"
+    scheduler "^0.23.0"
 
 react-fast-compare@^2.0.1:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9"
   integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==
 
-react-intersection-observer@^8.33.1:
-  version "8.33.1"
-  resolved "https://registry.yarnpkg.com/react-intersection-observer/-/react-intersection-observer-8.33.1.tgz#8e6442cac7052ed63056e191b7539e423e7d5c64"
-  integrity sha512-3v+qaJvp3D1MlGHyM+KISVg/CMhPiOlO6FgPHcluqHkx4YFCLuyXNlQ/LE6UkbODXlQcLOppfX6UMxCEkUhDLw==
-
-react-intl@5.24.7:
-  version "5.24.7"
-  resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-5.24.7.tgz#a57084543ff8e58ed2d2bc2f1d3b8add3a2f0e3b"
-  integrity sha512-URPLwISsEmnzft33honGEb87LcK0QtwkZXCNsXcDYTnrYC8ZyeJRTcPYvuXC3mrN6+DxnW52RfHC416zNxfyIg==
-  dependencies:
-    "@formatjs/ecma402-abstract" "1.11.3"
-    "@formatjs/icu-messageformat-parser" "2.0.18"
-    "@formatjs/intl" "2.1.0"
-    "@formatjs/intl-displaynames" "5.4.2"
-    "@formatjs/intl-listformat" "6.5.2"
+react-fast-compare@^3.0.1:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb"
+  integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==
+
+react-intersection-observer@9.4.0:
+  version "9.4.0"
+  resolved "https://registry.yarnpkg.com/react-intersection-observer/-/react-intersection-observer-9.4.0.tgz#f6b6e616e625f9bf255857c5cba9dbf7b1825ec7"
+  integrity sha512-v0403CmomOVlzhqFXlzOxg0ziLcVq8mfbP0AwAcEQWgZmR2OulOT79Ikznw4UlB3N+jlUYqLMe4SDHUOyp0t2A==
+
+react-intl@6.0.5:
+  version "6.0.5"
+  resolved "https://registry.yarnpkg.com/react-intl/-/react-intl-6.0.5.tgz#8adcb9108682c82e625a8ce7826283afd3537f62"
+  integrity sha512-nDZ3BosuE8WdovcGxsrjj1aIgJZklSL5aORs5oah+5tLQTzUdOEstzJEYQPM+sxl1dkDOu7RCuw0z9oI9ENf9g==
+  dependencies:
+    "@formatjs/ecma402-abstract" "1.11.8"
+    "@formatjs/icu-messageformat-parser" "2.1.4"
+    "@formatjs/intl" "2.3.1"
+    "@formatjs/intl-displaynames" "6.0.3"
+    "@formatjs/intl-listformat" "7.0.3"
     "@types/hoist-non-react-statics" "^3.3.1"
-    "@types/react" "16 || 17"
+    "@types/react" "16 || 17 || 18"
     hoist-non-react-statics "^3.3.2"
-    intl-messageformat "9.11.4"
-    tslib "^2.1.0"
+    intl-messageformat "10.1.1"
+    tslib "2.4.0"
 
 react-is@^16.13.1, react-is@^16.7.0:
   version "16.13.1"
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
   integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
 
-react-is@^17.0.0:
-  version "17.0.2"
-  resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
-  integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
+react-is@^18.0.0:
+  version "18.1.0"
+  resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.1.0.tgz#61aaed3096d30eacf2a2127118b5b41387d32a67"
+  integrity sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==
 
-react-markdown@^8.0.0:
-  version "8.0.0"
-  resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-8.0.0.tgz#3243296a59ddb0f451d262cc2e11123674b416c2"
-  integrity sha512-qbrWpLny6Ef2xHqnYqtot948LXP+4FtC+MWIuaN1kvSnowM+r1qEeEHpSaU0TDBOisQuj+Qe6eFY15cNL3gLAw==
+react-markdown@8.0.3:
+  version "8.0.3"
+  resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-8.0.3.tgz#e8aba0d2f5a1b2124d476ee1fff9448a2f57e4b3"
+  integrity sha512-We36SfqaKoVNpN1QqsZwWSv/OZt5J15LNgTLWynwAN5b265hrQrsjMtlRNwUvS+YyR3yDM8HpTNc4pK9H/Gc0A==
   dependencies:
     "@types/hast" "^2.0.0"
+    "@types/prop-types" "^15.0.0"
     "@types/unist" "^2.0.0"
     comma-separated-tokens "^2.0.0"
     hast-util-whitespace "^2.0.0"
     prop-types "^15.0.0"
     property-information "^6.0.0"
-    react-is "^17.0.0"
+    react-is "^18.0.0"
     remark-parse "^10.0.0"
     remark-rehype "^10.0.0"
     space-separated-tokens "^2.0.0"
@@ -9478,32 +10359,49 @@ react-markdown@^8.0.0:
     unist-util-visit "^4.0.0"
     vfile "^5.0.0"
 
-react-select@^5.2.2:
-  version "5.2.2"
-  resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.2.2.tgz#3d5edf0a60f1276fd5f29f9f90a305f0a25a5189"
-  integrity sha512-miGS2rT1XbFNjduMZT+V73xbJEeMzVkJOz727F6MeAr2hKE0uUSA8Ff7vD44H32x2PD3SRB6OXTY/L+fTV3z9w==
+react-popper-tooltip@4.4.2:
+  version "4.4.2"
+  resolved "https://registry.yarnpkg.com/react-popper-tooltip/-/react-popper-tooltip-4.4.2.tgz#0dc4894b8e00ba731f89bd2d30584f6032ec6163"
+  integrity sha512-y48r0mpzysRTZAIh8m2kpZ8S1YPNqGtQPDrlXYSGvDS1c1GpG/NUXbsbIdfbhXfmSaRJuTcaT6N1q3CKuHRVbg==
+  dependencies:
+    "@babel/runtime" "^7.18.3"
+    "@popperjs/core" "^2.11.5"
+    react-popper "^2.3.0"
+
+react-popper@^2.3.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-2.3.0.tgz#17891c620e1320dce318bad9fede46a5f71c70ba"
+  integrity sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==
+  dependencies:
+    react-fast-compare "^3.0.1"
+    warning "^4.0.2"
+
+react-select@5.4.0:
+  version "5.4.0"
+  resolved "https://registry.yarnpkg.com/react-select/-/react-select-5.4.0.tgz#81f6ac73906126706f104751ee14437bd16798f4"
+  integrity sha512-CjE9RFLUvChd5SdlfG4vqxZd55AZJRrLrHzkQyTYeHlpOztqcgnyftYAolJ0SGsBev6zAs6qFrjm6KU3eo2hzg==
   dependencies:
     "@babel/runtime" "^7.12.0"
     "@emotion/cache" "^11.4.0"
-    "@emotion/react" "^11.1.1"
+    "@emotion/react" "^11.8.1"
     "@types/react-transition-group" "^4.4.0"
     memoize-one "^5.0.0"
     prop-types "^15.6.0"
     react-transition-group "^4.3.0"
 
-react-spring@^9.4.4:
-  version "9.4.4"
-  resolved "https://registry.yarnpkg.com/react-spring/-/react-spring-9.4.4.tgz#0a53440013f97c1ebaa739a24a902487f36a5c1e"
-  integrity sha512-VOqilh9DJBsS6Pf550YLhdReS3j9a2AQVh7NcsNtWoxTYIeuErWi6ym0++6bBhQp4yT5xvVvUDaJ8ez8vrFgaw==
+react-spring@9.5.2:
+  version "9.5.2"
+  resolved "https://registry.yarnpkg.com/react-spring/-/react-spring-9.5.2.tgz#b9929ad2806e56e6408b27189ec9cdf1dc003873"
+  integrity sha512-OGWNgKi2TSjpqsK67NCUspaCgEvWcG7HcpO9KAaDLFzFGNxWdGdN3YTXhhWUqCsLAx9I6LxPzmRuUPsMNqTgrw==
   dependencies:
-    "@react-spring/core" "~9.4.4"
-    "@react-spring/konva" "~9.4.4"
-    "@react-spring/native" "~9.4.4"
-    "@react-spring/three" "~9.4.4"
-    "@react-spring/web" "~9.4.4"
-    "@react-spring/zdog" "~9.4.4"
+    "@react-spring/core" "~9.5.2"
+    "@react-spring/konva" "~9.5.2"
+    "@react-spring/native" "~9.5.2"
+    "@react-spring/three" "~9.5.2"
+    "@react-spring/web" "~9.5.2"
+    "@react-spring/zdog" "~9.5.2"
 
-react-toast-notifications@^2.5.1:
+react-toast-notifications@2.5.1:
   version "2.5.1"
   resolved "https://registry.yarnpkg.com/react-toast-notifications/-/react-toast-notifications-2.5.1.tgz#30216eedb5608ec69719a818b9a2e09283e90074"
   integrity sha512-eYuuiSPGLyuMHojRH2U7CbENvFHsvNia39pLM/s10KipIoNs14T7RIJk4aU2N+l++OsSgtJqnFObx9bpwLMU5A==
@@ -9511,7 +10409,7 @@ react-toast-notifications@^2.5.1:
     "@emotion/core" "^10.0.14"
     react-transition-group "^4.4.1"
 
-react-transition-group@^4.3.0, react-transition-group@^4.4.1, react-transition-group@^4.4.2:
+react-transition-group@^4.3.0, react-transition-group@^4.4.1:
   version "4.4.2"
   resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.2.tgz#8b59a56f09ced7b55cbd53c36768b922890d5470"
   integrity sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==
@@ -9521,30 +10419,29 @@ react-transition-group@^4.3.0, react-transition-group@^4.4.1, react-transition-g
     loose-envify "^1.4.0"
     prop-types "^15.6.2"
 
-react-truncate-markup@^5.1.0:
-  version "5.1.0"
-  resolved "https://registry.yarnpkg.com/react-truncate-markup/-/react-truncate-markup-5.1.0.tgz#632f263a7d70925ab6368d5620ef32f066c2857a"
-  integrity sha512-TTp8gj63w/o5jQC7HnLMEeAHp9jjSxFlA5lzklvPzcSubcurkEI4g0YjW67YG1yNAJHqQwCadj4mTUvz58S1wQ==
+react-truncate-markup@5.1.2:
+  version "5.1.2"
+  resolved "https://registry.yarnpkg.com/react-truncate-markup/-/react-truncate-markup-5.1.2.tgz#bf09785854d95e20028b257831ffdf32d08c8fa7"
+  integrity sha512-eEq6T8Rs+wz98cRYzQECGFNBfXwRYraLg/kz52f6DRBKmzxqB+GYLeDkVe/zrC+2vh5AEwM6nSYFvDWEBljd0w==
   dependencies:
     line-height "0.3.1"
     memoize-one "^5.1.1"
     prop-types "^15.6.0"
     resize-observer-polyfill "1.5.x"
 
-react-use-clipboard@1.0.7:
-  version "1.0.7"
-  resolved "https://registry.yarnpkg.com/react-use-clipboard/-/react-use-clipboard-1.0.7.tgz#34cccdfb4f17f5e6522e38f2cee62d05f605597a"
-  integrity sha512-blIprqARyITp0uVw/2Rh87mcujqXdH6vZ5NrcuXEhI5EmjBGxcGnwt/79+vdN7rwM6OliGj481lOj6ZCcsiYEQ==
+react-use-clipboard@1.0.8:
+  version "1.0.8"
+  resolved "https://registry.yarnpkg.com/react-use-clipboard/-/react-use-clipboard-1.0.8.tgz#7c1a5bcb469a0841dd9d1242af78e51d2ab7221f"
+  integrity sha512-QbN2kFl9uWEsELU4ONpAM98WASllAUWPSGBocbEVzRlcl1PbSa9EIdgADm6XlrcjYw9g1YQBfnCUb/5HGTOY+w==
   dependencies:
     copy-to-clipboard "^3.3.1"
 
-react@17.0.2:
-  version "17.0.2"
-  resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
-  integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
+react@18.2.0:
+  version "18.2.0"
+  resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
+  integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
   dependencies:
     loose-envify "^1.1.0"
-    object-assign "^4.1.1"
 
 read-babelrc-up@^1.1.0:
   version "1.1.0"
@@ -9554,10 +10451,17 @@ read-babelrc-up@^1.1.0:
     find-up "^4.1.0"
     json5 "^2.1.2"
 
-read-cmd-shim@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-2.0.0.tgz#4a50a71d6f0965364938e9038476f7eede3928d9"
-  integrity sha512-HJpV9bQpkl6KwjxlJcBoqu9Ba0PQg8TqSNIOrulGt54a0uup0HtevreFHzYzkm0lpnleRdNBzXznKrgxglEHQw==
+read-cache@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774"
+  integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==
+  dependencies:
+    pify "^2.3.0"
+
+read-cmd-shim@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-3.0.0.tgz#62b8c638225c61e6cc607f8f4b779f3b8238f155"
+  integrity sha512-KQDVjGqhZk92PPNRj9ZEXEuqg8bUobSKRw+q0YQ3TKI5xkce7bUJobL4Z/OtiEbAAv70yEpYIXp4iQ9L8oPVog==
 
 read-package-json-fast@^2.0.2, read-package-json-fast@^2.0.3:
   version "2.0.3"
@@ -9567,15 +10471,15 @@ read-package-json-fast@^2.0.2, read-package-json-fast@^2.0.3:
     json-parse-even-better-errors "^2.3.0"
     npm-normalize-package-bin "^1.0.1"
 
-read-package-json@^4.1.1, read-package-json@^4.1.2:
-  version "4.1.2"
-  resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-4.1.2.tgz#b444d047de7c75d4a160cb056d00c0693c1df703"
-  integrity sha512-Dqer4pqzamDE2O4M55xp1qZMuLPqi4ldk2ya648FOMHRjwMzFhuxVrG04wd0c38IsvkVdr3vgHI6z+QTPdAjrQ==
+read-package-json@^5.0.0, read-package-json@^5.0.1:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-5.0.1.tgz#1ed685d95ce258954596b13e2e0e76c7d0ab4c26"
+  integrity sha512-MALHuNgYWdGW3gKzuNMuYtcSSZbGQm94fAp16xt8VsYTLBjUSc55bLMKe6gzpWue0Tfi6CBgwCSdDAqutGDhMg==
   dependencies:
-    glob "^7.1.1"
-    json-parse-even-better-errors "^2.3.0"
-    normalize-package-data "^3.0.0"
-    npm-normalize-package-bin "^1.0.0"
+    glob "^8.0.1"
+    json-parse-even-better-errors "^2.3.1"
+    normalize-package-data "^4.0.0"
+    npm-normalize-package-bin "^1.0.1"
 
 read-pkg-up@^7.0.0, read-pkg-up@^7.0.1:
   version "7.0.1"
@@ -9603,16 +10507,6 @@ read@1, read@^1.0.7, read@~1.0.7:
   dependencies:
     mute-stream "~0.0.4"
 
-readable-stream@1.1.x:
-  version "1.1.14"
-  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
-  integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk=
-  dependencies:
-    core-util-is "~1.0.0"
-    inherits "~2.0.1"
-    isarray "0.0.1"
-    string_decoder "~0.10.x"
-
 readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.4.0, readable-stream@^3.6.0:
   version "3.6.0"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
@@ -9622,7 +10516,7 @@ readable-stream@3, readable-stream@^3.0.0, readable-stream@^3.4.0, readable-stre
     string_decoder "^1.1.1"
     util-deprecate "^1.0.1"
 
-readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@~2.3.6:
+readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.2.2, readable-stream@~2.3.6:
   version "2.3.7"
   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
   integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
@@ -9677,7 +10571,7 @@ redeyed@~2.1.0:
   dependencies:
     esprima "~4.0.0"
 
-reflect-metadata@^0.1.13:
+reflect-metadata@0.1.13, reflect-metadata@^0.1.13:
   version "0.1.13"
   resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08"
   integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==
@@ -9699,20 +10593,21 @@ regenerator-runtime@^0.13.4:
   resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
   integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==
 
-regenerator-transform@^0.14.2:
-  version "0.14.5"
-  resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4"
-  integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==
+regenerator-transform@^0.15.0:
+  version "0.15.0"
+  resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.0.tgz#cbd9ead5d77fae1a48d957cf889ad0586adb6537"
+  integrity sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==
   dependencies:
     "@babel/runtime" "^7.8.4"
 
-regexp.prototype.flags@^1.3.1:
-  version "1.4.1"
-  resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.1.tgz#b3f4c0059af9e47eca9f3f660e51d81307e72307"
-  integrity sha512-pMR7hBVUUGI7PMA37m2ofIdQCsomVnas+Jn5UPGAHQ+/LlwKm/aTLJHdasmHRzlfeZwHiAOaRSo2rbBDm3nNUQ==
+regexp.prototype.flags@^1.4.1, regexp.prototype.flags@^1.4.3:
+  version "1.4.3"
+  resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac"
+  integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==
   dependencies:
     call-bind "^1.0.2"
     define-properties "^1.1.3"
+    functions-have-names "^1.2.2"
 
 regexpp@^3.2.0:
   version "3.2.0"
@@ -9731,6 +10626,18 @@ regexpu-core@^5.0.1:
     unicode-match-property-ecmascript "^2.0.0"
     unicode-match-property-value-ecmascript "^2.0.0"
 
+regexpu-core@^5.1.0:
+  version "5.1.0"
+  resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.1.0.tgz#2f8504c3fd0ebe11215783a41541e21c79942c6d"
+  integrity sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA==
+  dependencies:
+    regenerate "^1.4.2"
+    regenerate-unicode-properties "^10.0.1"
+    regjsgen "^0.6.0"
+    regjsparser "^0.8.2"
+    unicode-match-property-ecmascript "^2.0.0"
+    unicode-match-property-value-ecmascript "^2.0.0"
+
 registry-auth-token@^4.0.0:
   version "4.2.1"
   resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250"
@@ -9738,13 +10645,6 @@ registry-auth-token@^4.0.0:
   dependencies:
     rc "^1.2.8"
 
-registry-url@^5.0.0:
-  version "5.1.0"
-  resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009"
-  integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==
-  dependencies:
-    rc "^1.2.8"
-
 regjsgen@^0.6.0:
   version "0.6.0"
   resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.6.0.tgz#83414c5354afd7d6627b16af5f10f41c4e71808d"
@@ -9776,6 +10676,13 @@ remark-rehype@^10.0.0:
     mdast-util-to-hast "^12.1.0"
     unified "^10.0.0"
 
+request-progress@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-3.0.0.tgz#4ca754081c7fec63f505e4faa825aa06cd669dbe"
+  integrity sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==
+  dependencies:
+    throttleit "^1.0.0"
+
 request-promise-core@1.1.2:
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.2.tgz#339f6aababcafdb31c799ff158700336301d3346"
@@ -9859,6 +10766,15 @@ resolve-global@1.0.0, resolve-global@^1.0.0:
   dependencies:
     global-dirs "^0.1.1"
 
+resolve@^1.1.7, resolve@^1.22.1:
+  version "1.22.1"
+  resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177"
+  integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==
+  dependencies:
+    is-core-module "^2.9.0"
+    path-parse "^1.0.7"
+    supports-preserve-symlinks-flag "^1.0.0"
+
 resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.15.1, resolve@^1.20.0, resolve@^1.22.0:
   version "1.22.0"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198"
@@ -9876,13 +10792,6 @@ resolve@^2.0.0-next.3:
     is-core-module "^2.2.0"
     path-parse "^1.0.6"
 
-responselike@^1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7"
-  integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=
-  dependencies:
-    lowercase-keys "^1.0.0"
-
 restore-cursor@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf"
@@ -9924,13 +10833,6 @@ rfdc@^1.3.0:
   resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b"
   integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==
 
-rimraf@^2.6.1:
-  version "2.7.1"
-  resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
-  integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
-  dependencies:
-    glob "^7.1.3"
-
 rimraf@^3.0.0, rimraf@^3.0.2:
   version "3.0.2"
   resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
@@ -9943,7 +10845,7 @@ rndm@1.2.0:
   resolved "https://registry.yarnpkg.com/rndm/-/rndm-1.2.0.tgz#f33fe9cfb52bbfd520aa18323bc65db110a1b76c"
   integrity sha1-8z/pz7Urv9UgqhgyO8ZdsRCht2w=
 
-run-async@^2.2.0:
+run-async@^2.2.0, run-async@^2.4.0:
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
   integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
@@ -9962,6 +10864,13 @@ rxjs@^6.4.0:
   dependencies:
     tslib "^1.9.0"
 
+rxjs@^7.5.1:
+  version "7.5.6"
+  resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.6.tgz#0446577557862afd6903517ce7cae79ecb9662bc"
+  integrity sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==
+  dependencies:
+    tslib "^2.1.0"
+
 rxjs@^7.5.5:
   version "7.5.5"
   resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.5.tgz#2ebad89af0f560f460ad5cc4213219e1f7dd4e9f"
@@ -9976,7 +10885,7 @@ sade@^1.7.3:
   dependencies:
     mri "^1.1.0"
 
-safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.1, safe-buffer@~5.2.0:
+safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0:
   version "5.2.1"
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
   integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
@@ -10001,18 +10910,17 @@ safe-stable-stringify@^2.3.1:
   resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
   integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
 
-sax@>=0.6.0, sax@^1.2.4:
+sax@>=0.6.0:
   version "1.2.4"
   resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
   integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
 
-scheduler@^0.20.2:
-  version "0.20.2"
-  resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
-  integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
+scheduler@^0.23.0:
+  version "0.23.0"
+  resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
+  integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
   dependencies:
     loose-envify "^1.1.0"
-    object-assign "^4.1.1"
 
 schema-utils@*:
   version "4.0.0"
@@ -10042,7 +10950,7 @@ schema-utils@^3.0.0:
     ajv "^6.12.5"
     ajv-keywords "^3.5.2"
 
-secure-random-password@^0.2.3:
+secure-random-password@0.2.3:
   version "0.2.3"
   resolved "https://registry.yarnpkg.com/secure-random-password/-/secure-random-password-0.2.3.tgz#cc99714a824328f251b11b35b557b685c09717db"
   integrity sha512-2zpmr6pK3CZGIS9fgApFw00/tKEBVbJTqe4AZLrLNgahCK6ueIR5uMzvbERNibr8hkWneMcOqDcm4wpHWUxrYw==
@@ -10061,17 +10969,17 @@ selderee@^0.6.0:
   dependencies:
     parseley "^0.7.0"
 
-semantic-release-docker-buildx@^1.0.1:
+semantic-release-docker-buildx@1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/semantic-release-docker-buildx/-/semantic-release-docker-buildx-1.0.1.tgz#9d63ee60638905bd4caba6e15190f091de4ded67"
   integrity sha512-DU5OCNM2cDpjM1Gr83jJnPgxryQysPno9cvDbs0AY8NwUL/nZc5mZn59UZB9BjHtSKsjKX1pgRb0bFd7LWJOOQ==
   dependencies:
     execa "^5.0.0"
 
-semantic-release@^19.0.2:
-  version "19.0.2"
-  resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-19.0.2.tgz#6011683c06d7b416e5faa5a3f43b22bbf3798aa8"
-  integrity sha512-7tPonjZxukKECmClhsfyMKDt0GR38feIC2HxgyYaBi+9tDySBLjK/zYDLhh+m6yjnHIJa9eBTKYE7k63ZQcYbw==
+semantic-release@19.0.3:
+  version "19.0.3"
+  resolved "https://registry.yarnpkg.com/semantic-release/-/semantic-release-19.0.3.tgz#9291053ad9890052f28e7c5921d4741530d516fd"
+  integrity sha512-HaFbydST1cDKZHuFZxB8DTrBLJVK/AnDExpK0s3EqLIAAUAHUgnd+VSJCUtTYQKkAkauL8G9CucODrVCc7BuAA==
   dependencies:
     "@semantic-release/commit-analyzer" "^9.0.2"
     "@semantic-release/error" "^3.0.0"
@@ -10110,62 +11018,62 @@ semver-diff@^3.1.1:
     semver "^6.3.0"
 
 semver-regex@^3.1.2:
-  version "3.1.3"
-  resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-3.1.3.tgz#b2bcc6f97f63269f286994e297e229b6245d0dc3"
-  integrity sha512-Aqi54Mk9uYTjVexLnR67rTyBusmwd04cLkHy9hNvk3+G3nT2Oyg7E0l4XVbOaNwIvQ3hHeYxGcyEy+mKreyBFQ==
+  version "3.1.4"
+  resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-3.1.4.tgz#13053c0d4aa11d070a2f2872b6b1e3ae1e1971b4"
+  integrity sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==
 
-"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.6.0, semver@^5.7.1:
+"semver@2 || 3 || 4 || 5", semver@^5.6.0, semver@^5.7.1:
   version "5.7.1"
   resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
   integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
 
-semver@7.0.0:
+semver@7.0.0, semver@~7.0.0:
   version "7.0.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
   integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
 
-semver@7.3.5, semver@^7.1.1, semver@^7.1.2, semver@^7.1.3, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5:
-  version "7.3.5"
-  resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
-  integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
+semver@7.3.7, semver@^7.0.0, semver@^7.1.1, semver@^7.1.2, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7:
+  version "7.3.7"
+  resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f"
+  integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==
   dependencies:
     lru-cache "^6.0.0"
 
-semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0:
+semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
   version "6.3.0"
   resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
   integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
 
-send@0.17.2:
-  version "0.17.2"
-  resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820"
-  integrity sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==
+send@0.18.0:
+  version "0.18.0"
+  resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"
+  integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==
   dependencies:
     debug "2.6.9"
-    depd "~1.1.2"
-    destroy "~1.0.4"
+    depd "2.0.0"
+    destroy "1.2.0"
     encodeurl "~1.0.2"
     escape-html "~1.0.3"
     etag "~1.8.1"
     fresh "0.5.2"
-    http-errors "1.8.1"
+    http-errors "2.0.0"
     mime "1.6.0"
     ms "2.1.3"
-    on-finished "~2.3.0"
+    on-finished "2.4.1"
     range-parser "~1.2.1"
-    statuses "~1.5.0"
+    statuses "2.0.1"
 
-serve-static@1.14.2:
-  version "1.14.2"
-  resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa"
-  integrity sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==
+serve-static@1.15.0:
+  version "1.15.0"
+  resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
+  integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==
   dependencies:
     encodeurl "~1.0.2"
     escape-html "~1.0.3"
     parseurl "~1.3.3"
-    send "0.17.2"
+    send "0.18.0"
 
-set-blocking@^2.0.0, set-blocking@~2.0.0:
+set-blocking@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
   integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
@@ -10230,6 +11138,13 @@ simple-swizzle@^0.2.2:
   dependencies:
     is-arrayish "^0.3.1"
 
+simple-update-notifier@^1.0.7:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz#7edf75c5bdd04f88828d632f762b2bc32996a9cc"
+  integrity sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==
+  dependencies:
+    semver "~7.0.0"
+
 slash@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44"
@@ -10277,15 +11192,15 @@ smart-buffer@^4.2.0:
   integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
 
 socks-proxy-agent@^6.0.0, socks-proxy-agent@^6.1.1:
-  version "6.1.1"
-  resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.1.1.tgz#e664e8f1aaf4e1fb3df945f09e3d94f911137f87"
-  integrity sha512-t8J0kG3csjA4g6FTbsMOWws+7R7vuRC8aQ/wy3/1OWmsgwA68zs/+cExQ0koSitUDXqhufF/YJr9wtNMZHw5Ew==
+  version "6.2.0"
+  resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-6.2.0.tgz#f6b5229cc0cbd6f2f202d9695f09d871e951c85e"
+  integrity sha512-wWqJhjb32Q6GsrUqzuFkukxb/zzide5quXYcMVpIjxalDBBYy2nqKCFQ/9+Ie4dvOYSQdOk3hUlZSdzZOd3zMQ==
   dependencies:
     agent-base "^6.0.2"
-    debug "^4.3.1"
-    socks "^2.6.1"
+    debug "^4.3.3"
+    socks "^2.6.2"
 
-socks@^2.6.1:
+socks@^2.6.2:
   version "2.6.2"
   resolved "https://registry.yarnpkg.com/socks/-/socks-2.6.2.tgz#ec042d7960073d40d94268ff3bb727dc685f111a"
   integrity sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==
@@ -10305,12 +11220,12 @@ sorted-array-functions@^1.3.0:
   resolved "https://registry.yarnpkg.com/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz#8605695563294dffb2c9796d602bd8459f7a0dd5"
   integrity sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA==
 
-source-map-js@^1.0.1, source-map-js@^1.0.2:
+source-map-js@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
   integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
 
-source-map@^0.5.0, source-map@^0.5.7:
+source-map@^0.5.7:
   version "0.5.7"
   resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
   integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=
@@ -10382,17 +11297,18 @@ sprintf-js@~1.0.2:
   resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
   integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=
 
-sqlite3@^5.0.2:
-  version "5.0.2"
-  resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-5.0.2.tgz#00924adcc001c17686e0a6643b6cbbc2d3965083"
-  integrity sha512-1SdTNo+BVU211Xj1csWa8lV6KM0CtucDwRyA0VHl91wEH1Mgh7RxUpI4rVvG7OhHrzCSGaVyW5g8vKvlrk9DJA==
+sqlite3@5.0.11:
+  version "5.0.11"
+  resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-5.0.11.tgz#102c835d70be66da9d95a383fd6ea084a082ef7f"
+  integrity sha512-4akFOr7u9lJEeAWLJxmwiV43DJcGV7w3ab7SjQFAFaTVyknY3rZjvXTKIVtWqUoY4xwhjwoHKYs2HDW2SoHVsA==
   dependencies:
-    node-addon-api "^3.0.0"
-    node-pre-gyp "^0.11.0"
+    "@mapbox/node-pre-gyp" "^1.0.0"
+    node-addon-api "^4.2.0"
+    tar "^6.1.11"
   optionalDependencies:
-    node-gyp "3.x"
+    node-gyp "8.x"
 
-sshpk@^1.7.0:
+sshpk@^1.14.1, sshpk@^1.7.0:
   version "1.17.0"
   resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5"
   integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==
@@ -10414,6 +11330,13 @@ ssri@^8.0.0, ssri@^8.0.1:
   dependencies:
     minipass "^3.1.1"
 
+ssri@^9.0.0, ssri@^9.0.1:
+  version "9.0.1"
+  resolved "https://registry.yarnpkg.com/ssri/-/ssri-9.0.1.tgz#544d4c357a8d7b71a19700074b6883fcb4eae057"
+  integrity sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==
+  dependencies:
+    minipass "^3.1.1"
+
 stable@^0.1.8:
   version "0.1.8"
   resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
@@ -10424,7 +11347,12 @@ stack-trace@0.0.x:
   resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0"
   integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=
 
-"statuses@>= 1.5.0 < 2", statuses@~1.5.0:
+statuses@2.0.1:
+  version "2.0.1"
+  resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
+  integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
+
+"statuses@>= 1.5.0 < 2":
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
   integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
@@ -10442,26 +11370,17 @@ stream-combiner2@~1.1.1:
     duplexer2 "~0.1.0"
     readable-stream "^2.0.2"
 
-streamsearch@0.1.2:
-  version "0.1.2"
-  resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
-  integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=
+streamsearch@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
+  integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
 
 string-argv@^0.3.1:
   version "0.3.1"
   resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da"
   integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==
 
-string-width@^1.0.1:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
-  integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
-  dependencies:
-    code-point-at "^1.0.0"
-    is-fullwidth-code-point "^1.0.0"
-    strip-ansi "^3.0.0"
-
-"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3:
+"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
   version "4.2.3"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
   integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -10487,35 +11406,37 @@ string-width@^5.0.0:
     emoji-regex "^9.2.2"
     strip-ansi "^7.0.1"
 
-string.prototype.matchall@^4.0.6:
-  version "4.0.6"
-  resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.6.tgz#5abb5dabc94c7b0ea2380f65ba610b3a544b15fa"
-  integrity sha512-6WgDX8HmQqvEd7J+G6VtAahhsQIssiZ8zl7zKh1VDMFyL3hRTJP4FTNA3RbIp2TOQ9AYNDcc7e3fH0Qbup+DBg==
+string.prototype.matchall@^4.0.7:
+  version "4.0.7"
+  resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz#8e6ecb0d8a1fb1fda470d81acecb2dba057a481d"
+  integrity sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==
   dependencies:
     call-bind "^1.0.2"
     define-properties "^1.1.3"
     es-abstract "^1.19.1"
     get-intrinsic "^1.1.1"
-    has-symbols "^1.0.2"
+    has-symbols "^1.0.3"
     internal-slot "^1.0.3"
-    regexp.prototype.flags "^1.3.1"
+    regexp.prototype.flags "^1.4.1"
     side-channel "^1.0.4"
 
-string.prototype.trimend@^1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80"
-  integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==
+string.prototype.trimend@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0"
+  integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==
   dependencies:
     call-bind "^1.0.2"
-    define-properties "^1.1.3"
+    define-properties "^1.1.4"
+    es-abstract "^1.19.5"
 
-string.prototype.trimstart@^1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed"
-  integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==
+string.prototype.trimstart@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef"
+  integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==
   dependencies:
     call-bind "^1.0.2"
-    define-properties "^1.1.3"
+    define-properties "^1.1.4"
+    es-abstract "^1.19.5"
 
 string_decoder@^1.1.1:
   version "1.3.0"
@@ -10536,18 +11457,6 @@ string_decoder@~1.1.1:
   dependencies:
     safe-buffer "~5.1.0"
 
-stringify-package@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/stringify-package/-/stringify-package-1.0.1.tgz#e5aa3643e7f74d0f28628b72f3dad5cecfc3ba85"
-  integrity sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==
-
-strip-ansi@^3.0.0, strip-ansi@^3.0.1:
-  version "3.0.1"
-  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
-  integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
-  dependencies:
-    ansi-regex "^2.0.0"
-
 strip-ansi@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
@@ -10603,7 +11512,7 @@ strip-json-comments@3.0.1:
   resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7"
   integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==
 
-strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
+strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
   integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
@@ -10620,10 +11529,10 @@ style-to-object@^0.3.0:
   dependencies:
     inline-style-parser "0.1.1"
 
-styled-jsx@5.0.0:
-  version "5.0.0"
-  resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.0.tgz#816b4b92e07b1786c6b7111821750e0ba4d26e77"
-  integrity sha512-qUqsWoBquEdERe10EW8vLp3jT25s/ssG1/qX5gZ4wu15OZpmSMFI2v+fWlRhLfykA5rFtlJ1ME8A8pm/peV4WA==
+styled-jsx@5.0.4:
+  version "5.0.4"
+  resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.4.tgz#5b1bd0b9ab44caae3dd1361295559706e044aa53"
+  integrity sha512-sDFWLbg4zR+UkNzfk5lPilyIgtpddfxXEULxhujorr5jtePTUqiPDc5BC0v1NRqTr/WaFBGQQUoYToGlF4B2KQ==
 
 stylis@4.0.13:
   version "4.0.13"
@@ -10644,10 +11553,17 @@ supports-color@^7.0.0, supports-color@^7.1.0:
   dependencies:
     has-flag "^4.0.0"
 
-supports-color@^9.2.1:
-  version "9.2.1"
-  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.2.1.tgz#599dc9d45acf74c6176e0d880bab1d7d718fe891"
-  integrity sha512-Obv7ycoCTG51N7y175StI9BlAXrmgZrFhZOb0/PyjHBher/NmsdBgbbQ1Inhq+gIhz6+7Gb+jWF2Vqi7Mf1xnQ==
+supports-color@^8.1.1:
+  version "8.1.1"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
+  integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
+  dependencies:
+    has-flag "^4.0.0"
+
+supports-color@^9.2.2:
+  version "9.2.2"
+  resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-9.2.2.tgz#502acaf82f2b7ee78eb7c83dcac0f89694e5a7bb"
+  integrity sha512-XC6g/Kgux+rJXmwokjm9ECpD6k/smUoS5LKlUCcsYr4IY3rW0XyAympon2RmxGrlnZURMpg5T18gWDP9CsHXFA==
 
 supports-hyperlinks@^2.2.0:
   version "2.2.0"
@@ -10662,12 +11578,12 @@ supports-preserve-symlinks-flag@^1.0.0:
   resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
   integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
 
-svg-parser@^2.0.2:
+svg-parser@^2.0.4:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5"
   integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==
 
-svgo@^2.5.0:
+svgo@^2.8.0:
   version "2.8.0"
   resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24"
   integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==
@@ -10680,62 +11596,50 @@ svgo@^2.5.0:
     picocolors "^1.0.0"
     stable "^0.1.8"
 
-swagger-ui-dist@>=4.1.3:
-  version "4.6.2"
-  resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-4.6.2.tgz#3c6ac79108b67d37c76ac8f8bebf4b432ef81585"
-  integrity sha512-BSt+ukOGkGZ2uHV4jyyCAzt60ysyQpGZAAhtIh7AMHT4MH1xXGkoXm2tfr1oRqO1N4IEY6qqNAlmcfMo/dAYuw==
+swagger-ui-dist@>=4.11.0:
+  version "4.11.1"
+  resolved "https://registry.yarnpkg.com/swagger-ui-dist/-/swagger-ui-dist-4.11.1.tgz#1e9c0e62bdac632f7b206c95ef9cbe986097606a"
+  integrity sha512-pf3kfSTYdF9mYFY2VnfJ51wnXlSVhEGdtymhpHzfbFw2jTbiEWgBoVz5EB9aW2EaJvUGTM1YHAXYZX7Jk4RdAQ==
 
-swagger-ui-express@^4.3.0:
-  version "4.3.0"
-  resolved "https://registry.yarnpkg.com/swagger-ui-express/-/swagger-ui-express-4.3.0.tgz#226238ab231f7718f9109d63a66efc3a795618dd"
-  integrity sha512-jN46SEEe9EoXa3ZgZoKgnSF6z0w3tnM1yqhO4Y+Q4iZVc8JOQB960EZpIAz6rNROrDApVDwcMHR0mhlnc/5Omw==
+swagger-ui-express@4.5.0:
+  version "4.5.0"
+  resolved "https://registry.yarnpkg.com/swagger-ui-express/-/swagger-ui-express-4.5.0.tgz#feb1314627092eb9c7e6b65ee018927011445530"
+  integrity sha512-DHk3zFvsxrkcnurGvQlAcLuTDacAVN1JHKDgcba/gr2NFRE4HGwP1YeHIXMiGznkWR4AeS7X5vEblNn4QljuNA==
   dependencies:
-    swagger-ui-dist ">=4.1.3"
+    swagger-ui-dist ">=4.11.0"
 
-swr@^1.2.2:
-  version "1.2.2"
-  resolved "https://registry.yarnpkg.com/swr/-/swr-1.2.2.tgz#6cae09928d30593a7980d80f85823e57468fac5d"
-  integrity sha512-ky0BskS/V47GpW8d6RU7CPsr6J8cr7mQD6+do5eky3bM0IyJaoi3vO8UhvrzJaObuTlGhPl2szodeB2dUd76Xw==
+swr@1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/swr/-/swr-1.3.0.tgz#c6531866a35b4db37b38b72c45a63171faf9f4e8"
+  integrity sha512-dkghQrOl2ORX9HYrMDtPa7LTVHJjCTeZoB1dqTbnnEDlSvN8JEKpYIYurDfvbQFUUS8Cg8PceFVZNkW0KNNYPw==
 
-tailwindcss@^3.0.23:
-  version "3.0.23"
-  resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.0.23.tgz#c620521d53a289650872a66adfcb4129d2200d10"
-  integrity sha512-+OZOV9ubyQ6oI2BXEhzw4HrqvgcARY38xv3zKcjnWtMIZstEsXdI9xftd1iB7+RbOnj2HOEzkA0OyB5BaSxPQA==
+tailwindcss@3.1.8:
+  version "3.1.8"
+  resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.1.8.tgz#4f8520550d67a835d32f2f4021580f9fddb7b741"
+  integrity sha512-YSneUCZSFDYMwk+TGq8qYFdCA3yfBRdBlS7txSq0LUmzyeqRe3a8fBQzbz9M3WS/iFT4BNf/nmw9mEzrnSaC0g==
   dependencies:
-    arg "^5.0.1"
-    chalk "^4.1.2"
+    arg "^5.0.2"
     chokidar "^3.5.3"
     color-name "^1.1.4"
-    cosmiconfig "^7.0.1"
-    detective "^5.2.0"
+    detective "^5.2.1"
     didyoumean "^1.2.2"
     dlv "^1.1.3"
     fast-glob "^3.2.11"
     glob-parent "^6.0.2"
     is-glob "^4.0.3"
+    lilconfig "^2.0.6"
     normalize-path "^3.0.0"
-    object-hash "^2.2.0"
-    postcss "^8.4.6"
+    object-hash "^3.0.0"
+    picocolors "^1.0.0"
+    postcss "^8.4.14"
+    postcss-import "^14.1.0"
     postcss-js "^4.0.0"
-    postcss-load-config "^3.1.0"
+    postcss-load-config "^3.1.4"
     postcss-nested "5.0.6"
-    postcss-selector-parser "^6.0.9"
+    postcss-selector-parser "^6.0.10"
     postcss-value-parser "^4.2.0"
     quick-lru "^5.1.1"
-    resolve "^1.22.0"
-
-tar@^4:
-  version "4.4.19"
-  resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3"
-  integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==
-  dependencies:
-    chownr "^1.1.4"
-    fs-minipass "^1.2.7"
-    minipass "^2.9.0"
-    minizlib "^1.3.3"
-    mkdirp "^0.5.5"
-    safe-buffer "^5.2.1"
-    yallist "^3.1.1"
+    resolve "^1.22.1"
 
 tar@^6.0.2, tar@^6.1.0, tar@^6.1.11, tar@^6.1.2:
   version "6.1.11"
@@ -10794,6 +11698,11 @@ thenify-all@^1.0.0:
   dependencies:
     any-promise "^1.0.0"
 
+throttleit@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c"
+  integrity sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==
+
 through2@^2.0.1, through2@~2.0.0:
   version "2.0.5"
   resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
@@ -10829,15 +11738,10 @@ titleize@2:
   resolved "https://registry.yarnpkg.com/titleize/-/titleize-2.1.0.tgz#5530de07c22147a0488887172b5bd94f5b30a48f"
   integrity sha512-m+apkYlfiQTKLW+sI4vqUkwMEzfgEUEYSqljx1voUE3Wz/z1ZsxyzSxvH2X8uKVrOp7QkByWt0rA6+gvhCKy6g==
 
-tlds@1.224.0:
-  version "1.224.0"
-  resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.224.0.tgz#dc9a5b0bda0708af0302114f6e24458770c5af01"
-  integrity sha512-Jgdc8SEijbDFUsmCn6Wk/f7E6jBLFZOG3U1xK0amGSfEH55Xx97ItUS/d2NngsuApjn11UeWCWj8Um3VRhseZQ==
-
-tlds@^1.230.0:
-  version "1.230.0"
-  resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.230.0.tgz#9c836528c4062e565b3b58bfaef83d99e09c113d"
-  integrity sha512-QFuY6JBWZt2bZXlapjqsojul5dv9xfo7Uc8wTUlctJOuF+BS/ICni2f4x7MFiT7muUVmcKC1LvGnU4GWhYO0PQ==
+tlds@1.231.0, tlds@^1.230.0:
+  version "1.231.0"
+  resolved "https://registry.yarnpkg.com/tlds/-/tlds-1.231.0.tgz#93880175cd0a06fdf7b5b5b9bcadff9d94813e39"
+  integrity sha512-L7UQwueHSkGxZHQBXHVmXW64oi+uqNtzFt2x6Ssk7NVnpIbw16CRs4eb/jmKOZ9t2JnqZ/b3Cfvo97lnXqKrhw==
 
 tmp@^0.0.33:
   version "0.0.33"
@@ -10846,16 +11750,18 @@ tmp@^0.0.33:
   dependencies:
     os-tmpdir "~1.0.2"
 
+tmp@~0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
+  integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==
+  dependencies:
+    rimraf "^3.0.0"
+
 to-fast-properties@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
   integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
 
-to-readable-stream@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771"
-  integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==
-
 to-regex-range@^5.0.1:
   version "5.0.1"
   resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
@@ -10913,10 +11819,10 @@ traverse@~0.6.6:
   resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137"
   integrity sha1-y99WD9e5r2MlAv7UD5GMFX6pcTc=
 
-treeverse@^1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/treeverse/-/treeverse-1.0.4.tgz#a6b0ebf98a1bca6846ddc7ecbc900df08cb9cd5f"
-  integrity sha512-whw60l7r+8ZU8Tu/Uc2yxtc4ZTZbR/PF3u1IPNKGQ6p8EICLb3Z2lAgoqw9bqYd8IkgnsaOcLzYHFckjqNsf0g==
+treeverse@^2.0.0:
+  version "2.0.0"
+  resolved "https://registry.yarnpkg.com/treeverse/-/treeverse-2.0.0.tgz#036dcef04bc3fd79a9b79a68d4da03e882d8a9ca"
+  integrity sha512-N5gJCkLu1aXccpOTtqV6ddSEi6ZmGkh3hjmbu1IjcavJK4qyOVQmi0myQKM7z5jVGmD68SJoliaVrMmVObhj6A==
 
 trim-newlines@^3.0.0:
   version "3.0.1"
@@ -10933,12 +11839,31 @@ trough@^2.0.0:
   resolved "https://registry.yarnpkg.com/trough/-/trough-2.1.0.tgz#0f7b511a4fde65a46f18477ab38849b22c554876"
   integrity sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==
 
-ts-node@^10.6.0, ts-node@^10.7.0:
-  version "10.7.0"
-  resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.7.0.tgz#35d503d0fab3e2baa672a0e94f4b40653c2463f5"
-  integrity sha512-TbIGS4xgJoX2i3do417KSaep1uRAW/Lu+WAL2doDHC0D6ummjirVOXU5/7aiZotbQ5p1Zp9tP7U6cYhA0O7M8A==
+ts-node@10.9.1:
+  version "10.9.1"
+  resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b"
+  integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==
+  dependencies:
+    "@cspotcode/source-map-support" "^0.8.0"
+    "@tsconfig/node10" "^1.0.7"
+    "@tsconfig/node12" "^1.0.7"
+    "@tsconfig/node14" "^1.0.0"
+    "@tsconfig/node16" "^1.0.2"
+    acorn "^8.4.1"
+    acorn-walk "^8.1.1"
+    arg "^4.1.0"
+    create-require "^1.1.0"
+    diff "^4.0.1"
+    make-error "^1.1.1"
+    v8-compile-cache-lib "^3.0.1"
+    yn "3.1.1"
+
+ts-node@^10.8.0:
+  version "10.8.0"
+  resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.8.0.tgz#3ceb5ac3e67ae8025c1950626aafbdecb55d82ce"
+  integrity sha512-/fNd5Qh+zTt8Vt1KbYZjRHCE9sI5i7nqfD/dzBBRDeVXZXS6kToW6R7tTU6Nd4XavFs0mAVCg29Q//ML7WsZYA==
   dependencies:
-    "@cspotcode/source-map-support" "0.7.0"
+    "@cspotcode/source-map-support" "^0.8.0"
     "@tsconfig/node10" "^1.0.7"
     "@tsconfig/node12" "^1.0.7"
     "@tsconfig/node14" "^1.0.0"
@@ -10949,29 +11874,50 @@ ts-node@^10.6.0, ts-node@^10.7.0:
     create-require "^1.1.0"
     diff "^4.0.1"
     make-error "^1.1.1"
-    v8-compile-cache-lib "^3.0.0"
+    v8-compile-cache-lib "^3.0.1"
     yn "3.1.1"
 
-tsconfig-paths@^3.12.0, tsconfig-paths@^3.9.0:
-  version "3.13.0"
-  resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.13.0.tgz#f3e9b8f6876698581d94470c03c95b3a48c0e3d7"
-  integrity sha512-nWuffZppoaYK0vQ1SQmkSsQzJoHA4s6uzdb2waRpD806x9yfq153AdVsWz4je2qZcW+pENrMQXbGQ3sMCkXuhw==
+tsc-alias@1.7.0:
+  version "1.7.0"
+  resolved "https://registry.yarnpkg.com/tsc-alias/-/tsc-alias-1.7.0.tgz#733482751133a25b97608ee424f8a1f085fcaaef"
+  integrity sha512-n/K6g8S7Ec7Y/A2Z77Ikp2Uv1S1ERtT63ni69XV4W1YPT4rnNmz8ItgIiJYvKfFnKfqcZQ81UPjoKpMTxaC/rg==
+  dependencies:
+    chokidar "^3.5.3"
+    commander "^9.0.0"
+    globby "^11.0.4"
+    mylas "^2.1.9"
+    normalize-path "^3.0.0"
+    plimit-lit "^1.2.6"
+
+tsconfig-paths@4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-4.1.0.tgz#f8ef7d467f08ae3a695335bf1ece088c5538d2c1"
+  integrity sha512-AHx4Euop/dXFC+Vx589alFba8QItjF+8hf8LtmuiCwHyI4rHXQtOOENaM8kvYf5fR0dRChy3wzWIZ9WbB7FWow==
+  dependencies:
+    json5 "^2.2.1"
+    minimist "^1.2.6"
+    strip-bom "^3.0.0"
+
+tsconfig-paths@^3.14.1:
+  version "3.14.1"
+  resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a"
+  integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==
   dependencies:
     "@types/json5" "^0.0.29"
     json5 "^1.0.1"
-    minimist "^1.2.0"
+    minimist "^1.2.6"
     strip-bom "^3.0.0"
 
+tslib@2.4.0, tslib@^2.0.1, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.4.0:
+  version "2.4.0"
+  resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
+  integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
+
 tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0:
   version "1.14.1"
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
   integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
 
-tslib@^2.0.1, tslib@^2.1.0, tslib@^2.2.0:
-  version "2.3.1"
-  resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01"
-  integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==
-
 tsscmp@1.0.6:
   version "1.0.6"
   resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb"
@@ -11063,33 +12009,38 @@ typedarray@^0.0.6:
   resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
   integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
 
-typeorm@0.2.45:
-  version "0.2.45"
-  resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.2.45.tgz#e5bbb3af822dc4646bad96cfa48cd22fa4687cea"
-  integrity sha512-c0rCO8VMJ3ER7JQ73xfk0zDnVv0WDjpsP6Q1m6CVKul7DB9iVdWLRjPzc8v2eaeBuomsbZ2+gTaYr8k1gm3bYA==
+typeorm@0.3.7:
+  version "0.3.7"
+  resolved "https://registry.yarnpkg.com/typeorm/-/typeorm-0.3.7.tgz#5776ed5058f0acb75d64723b39ff458d21de64c1"
+  integrity sha512-MsPJeP6Zuwfe64c++l80+VRqpGEGxf0CkztIEnehQ+CMmQPSHjOnFbFxwBuZ2jiLqZTjLk2ZqQdVF0RmvxNF3Q==
   dependencies:
     "@sqltools/formatter" "^1.2.2"
     app-root-path "^3.0.0"
     buffer "^6.0.3"
     chalk "^4.1.0"
     cli-highlight "^2.1.11"
-    debug "^4.3.1"
-    dotenv "^8.2.0"
-    glob "^7.1.6"
-    js-yaml "^4.0.0"
+    date-fns "^2.28.0"
+    debug "^4.3.3"
+    dotenv "^16.0.0"
+    glob "^7.2.0"
+    js-yaml "^4.1.0"
     mkdirp "^1.0.4"
     reflect-metadata "^0.1.13"
     sha.js "^2.4.11"
-    tslib "^2.1.0"
+    tslib "^2.3.1"
     uuid "^8.3.2"
     xml2js "^0.4.23"
-    yargs "^17.0.1"
-    zen-observable-ts "^1.0.0"
+    yargs "^17.3.1"
 
-typescript@^4.0, typescript@^4.4.3, typescript@^4.5, typescript@^4.6.2:
-  version "4.6.2"
-  resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4"
-  integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==
+typescript@4.7.4:
+  version "4.7.4"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235"
+  integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==
+
+typescript@^4.0, typescript@^4.5, typescript@^4.6.4:
+  version "4.7.2"
+  resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.2.tgz#1f9aa2ceb9af87cca227813b4310fff0b51593c4"
+  integrity sha512-Mamb1iX2FDUpcTRzltPxgWMKy3fhg0TN378ylbktPGPK/99KbDtMQ4W1hwgsbPAsG3a0xKa1vmw4VKZQbkvz5A==
 
 uc.micro@^1.0.1:
   version "1.0.6"
@@ -11097,9 +12048,9 @@ uc.micro@^1.0.1:
   integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==
 
 uglify-js@^3.1.4:
-  version "3.15.3"
-  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.15.3.tgz#9aa82ca22419ba4c0137642ba0df800cb06e0471"
-  integrity sha512-6iCVm2omGJbsu3JWac+p6kUiOpg3wFO2f8lIXjfEb8RrmLjzog1wTPMmwKB7swfzzqxj9YM+sGUM++u1qN4qJg==
+  version "3.15.5"
+  resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.15.5.tgz#2b10f9e0bfb3f5c15a8e8404393b6361eaeb33b3"
+  integrity sha512-hNM5q5GbBRB5xB+PMqVRcgYe4c8jbyZ1pzZhS6jbq54/4F2gFK869ZheiE5A8/t+W5jtTNpWef/5Q9zk639FNQ==
 
 uid-safe@2.1.5, uid-safe@~2.1.5:
   version "2.1.5"
@@ -11108,14 +12059,14 @@ uid-safe@2.1.5, uid-safe@~2.1.5:
   dependencies:
     random-bytes "~1.0.0"
 
-unbox-primitive@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471"
-  integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==
+unbox-primitive@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e"
+  integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==
   dependencies:
-    function-bind "^1.1.1"
-    has-bigints "^1.0.1"
-    has-symbols "^1.0.2"
+    call-bind "^1.0.2"
+    has-bigints "^1.0.2"
+    has-symbols "^1.0.3"
     which-boxed-primitive "^1.0.2"
 
 undefsafe@^2.0.5:
@@ -11129,9 +12080,9 @@ underscore.deep@~0.5.1:
   integrity sha1-ByZx9I1oc1w0Ij/P72PmnlJ2zCs=
 
 underscore@~1.13.1:
-  version "1.13.2"
-  resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.2.tgz#276cea1e8b9722a8dbed0100a407dda572125881"
-  integrity sha512-ekY1NhRzq0B08g4bGuX4wd2jZx5GnKz6mKSqFL4nqBlfyMGiG10gDFhDTMEfYmDL6Jy0FUIZp7wiRB+0BP7J2g==
+  version "1.13.3"
+  resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.3.tgz#54bc95f7648c5557897e5e968d0f76bc062c34ee"
+  integrity sha512-QvjkYpiD+dJJraRA8+dGAU4i7aBbb2s0S3jA45TFOvg2VgqvdCDd/3N6CqA8gluk1W91GLoXg5enMUx560QzuA==
 
 unicode-canonical-property-names-ecmascript@^2.0.0:
   version "2.0.0"
@@ -11208,9 +12159,11 @@ unist-util-is@^5.0.0:
   integrity sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ==
 
 unist-util-position@^4.0.0:
-  version "4.0.1"
-  resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-4.0.1.tgz#f8484b2da19a897a0180556d160c28633070dbb9"
-  integrity sha512-mgy/zI9fQ2HlbOtTdr2w9lhVaiFUHWQnZrFF2EUoVOqtAUdzqMtNiD99qA5a1IcjWVR8O6aVYE9u7Z2z1v0SQA==
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-4.0.3.tgz#5290547b014f6222dff95c48d5c3c13a88fadd07"
+  integrity sha512-p/5EMGIa1qwbXjA+QgcBXaPWjSnZfQ2Sc3yBEEfgPwsEmJd8Qh+DSk3LGnmOM4S1bY2C0AjmMnB8RuEYxpPwXQ==
+  dependencies:
+    "@types/unist" "^2.0.0"
 
 unist-util-stringify-position@^3.0.0:
   version "3.0.2"
@@ -11278,25 +12231,13 @@ untildify@^4.0.0:
   resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b"
   integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==
 
-update-notifier@^5.1.0:
-  version "5.1.0"
-  resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-5.1.0.tgz#4ab0d7c7f36a231dd7316cf7729313f0214d9ad9"
-  integrity sha512-ItnICHbeMh9GqUy31hFPrD1kcuZ3rpxDZbf4KUDavXwS0bW5m7SLbDQpGX3UYr072cbrF5hFUs3r5tUsPwjfHw==
+update-browserslist-db@^1.0.5:
+  version "1.0.5"
+  resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz#be06a5eedd62f107b7c19eb5bcefb194411abf38"
+  integrity sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==
   dependencies:
-    boxen "^5.0.0"
-    chalk "^4.1.0"
-    configstore "^5.0.1"
-    has-yarn "^2.1.0"
-    import-lazy "^2.1.0"
-    is-ci "^2.0.0"
-    is-installed-globally "^0.4.0"
-    is-npm "^5.0.0"
-    is-yarn-global "^0.3.0"
-    latest-version "^5.1.0"
-    pupa "^2.1.1"
-    semver "^7.3.4"
-    semver-diff "^3.1.1"
-    xdg-basedir "^4.0.0"
+    escalade "^3.1.1"
+    picocolors "^1.0.0"
 
 uri-js@^4.2.2:
   version "4.4.1"
@@ -11310,24 +12251,15 @@ url-join@^4.0.0:
   resolved "https://registry.yarnpkg.com/url-join/-/url-join-4.0.1.tgz#b642e21a2646808ffa178c4c5fda39844e12cde7"
   integrity sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==
 
-url-parse-lax@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c"
-  integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=
-  dependencies:
-    prepend-http "^2.0.0"
-
 urlsafe-base64@^1.0.0, urlsafe-base64@~1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/urlsafe-base64/-/urlsafe-base64-1.0.0.tgz#23f89069a6c62f46cf3a1d3b00169cefb90be0c6"
   integrity sha1-I/iQaabGL0bPOh07ABac77kL4MY=
 
-use-subscription@1.5.1:
-  version "1.5.1"
-  resolved "https://registry.yarnpkg.com/use-subscription/-/use-subscription-1.5.1.tgz#73501107f02fad84c6dd57965beb0b75c68c42d1"
-  integrity sha512-Xv2a1P/yReAjAbhylMfFplFKj9GssgTwN7RlcTxBujFQcloStWNDQdc4g4NRWH9xS4i/FDk04vQBptAXoF3VcA==
-  dependencies:
-    object-assign "^4.1.1"
+use-sync-external-store@1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
+  integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
 
 util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
   version "1.0.2"
@@ -11359,10 +12291,10 @@ uvu@^0.5.0:
     kleur "^4.0.3"
     sade "^1.7.3"
 
-v8-compile-cache-lib@^3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.0.tgz#0582bcb1c74f3a2ee46487ceecf372e46bce53e8"
-  integrity sha512-mpSYqfsFvASnSn5qMiwrr4VKfumbPyONLCOPmsR3A6pTY/r0+tSaVbgPWSAIuzbk3lCTa+FForeTiO+wBQGkjA==
+v8-compile-cache-lib@^3.0.1:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
+  integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==
 
 v8-compile-cache@^2.0.3:
   version "2.3.0"
@@ -11382,12 +12314,12 @@ validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4:
     spdx-correct "^3.0.0"
     spdx-expression-parse "^3.0.0"
 
-validate-npm-package-name@^3.0.0, validate-npm-package-name@~3.0.0:
-  version "3.0.0"
-  resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e"
-  integrity sha1-X6kS2B630MdK/BQN5zF/DKffQ34=
+validate-npm-package-name@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-4.0.0.tgz#fe8f1c50ac20afdb86f177da85b3600f0ac0d747"
+  integrity sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==
   dependencies:
-    builtins "^1.0.3"
+    builtins "^5.0.0"
 
 vary@~1.1.2:
   version "1.1.2"
@@ -11431,17 +12363,24 @@ walk-up-path@^1.0.0:
   resolved "https://registry.yarnpkg.com/walk-up-path/-/walk-up-path-1.0.0.tgz#d4745e893dd5fd0dbb58dd0a4c6a33d9c9fec53e"
   integrity sha512-hwj/qMDUEjCU5h0xr90KGCf0tg0/LgJbmOWgrWKYlcJZM7XvquvUJZ0G/HMGr7F7OQMOUuPHWP9JpriinkAlkg==
 
-wcwidth@^1.0.0:
+warning@^4.0.2:
+  version "4.0.3"
+  resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
+  integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==
+  dependencies:
+    loose-envify "^1.0.0"
+
+wcwidth@^1.0.0, wcwidth@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
-  integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=
+  integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==
   dependencies:
     defaults "^1.0.3"
 
-web-push@^3.4.5:
-  version "3.4.5"
-  resolved "https://registry.yarnpkg.com/web-push/-/web-push-3.4.5.tgz#f94074ff150538872c7183e4d8881c8305920cf1"
-  integrity sha512-2njbTqZ6Q7ZqqK14YpK1GGmaZs3NmuGYF5b7abCXulUIWFSlSYcZ3NBJQRFcMiQDceD7vQknb8FUuvI1F7Qe/g==
+web-push@3.5.0:
+  version "3.5.0"
+  resolved "https://registry.yarnpkg.com/web-push/-/web-push-3.5.0.tgz#4576533746052eda3bd50414b54a1b0a21eeaeae"
+  integrity sha512-JC0V9hzKTqlDYJ+LTZUXtW7B175qwwaqzbbMSWDxHWxZvd3xY0C2rcotMGDavub2nAAFw+sXTsqR65/KY2A5AQ==
   dependencies:
     asn1.js "^5.3.0"
     http_ece "1.1.0"
@@ -11500,24 +12439,17 @@ which@^2.0.1, which@^2.0.2:
   dependencies:
     isexe "^2.0.0"
 
-wide-align@^1.1.0, wide-align@^1.1.2, wide-align@^1.1.5:
+wide-align@^1.1.2, wide-align@^1.1.5:
   version "1.1.5"
   resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.5.tgz#df1d4c206854369ecf3c9a4898f1b23fbd9d15d3"
   integrity sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==
   dependencies:
     string-width "^1.0.2 || 2 || 3 || 4"
 
-widest-line@^3.1.0:
-  version "3.1.0"
-  resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca"
-  integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==
-  dependencies:
-    string-width "^4.0.0"
-
-winston-daily-rotate-file@^4.6.1:
-  version "4.6.1"
-  resolved "https://registry.yarnpkg.com/winston-daily-rotate-file/-/winston-daily-rotate-file-4.6.1.tgz#35c9db5669c381ed32acdb5849de69ab046a7a71"
-  integrity sha512-Ycch4LZmTycbhgiI2eQXBKI1pKcEQgAqmBjyq7/dC6Dk77nasdxvhLKraqTdCw7wNDSs8/M0jXaLATHquG7xYg==
+winston-daily-rotate-file@4.7.1:
+  version "4.7.1"
+  resolved "https://registry.yarnpkg.com/winston-daily-rotate-file/-/winston-daily-rotate-file-4.7.1.tgz#f60a643af87f8867f23170d8cd87dbe3603a625f"
+  integrity sha512-7LGPiYGBPNyGHLn9z33i96zx/bd71pjBn9tqQzO3I4Tayv94WPmBNwKC7CO1wPHdP9uvu+Md/1nr6VSH9h0iaA==
   dependencies:
     file-stream-rotator "^0.6.1"
     object-hash "^2.0.1"
@@ -11533,10 +12465,10 @@ winston-transport@^4.4.0, winston-transport@^4.5.0:
     readable-stream "^3.6.0"
     triple-beam "^1.3.0"
 
-winston@^3.6.0:
-  version "3.6.0"
-  resolved "https://registry.yarnpkg.com/winston/-/winston-3.6.0.tgz#be32587a099a292b88c49fac6fa529d478d93fb6"
-  integrity sha512-9j8T75p+bcN6D00sF/zjFVmPp+t8KMPB1MzbbzYjeN9VWxdsYnTB40TkbNUEXAmILEfChMvAMgidlX64OG3p6w==
+winston@3.8.1:
+  version "3.8.1"
+  resolved "https://registry.yarnpkg.com/winston/-/winston-3.8.1.tgz#76f15b3478cde170b780234e0c4cf805c5a7fb57"
+  integrity sha512-r+6YAiCR4uI3N8eQNOg8k3P3PqwAm20cLKlzVD9E66Ch39+LZC+VH1UKf9JemQj2B3QoUHfKD7Poewn0Pr3Y1w==
   dependencies:
     "@dabh/diagnostics" "^2.0.2"
     async "^3.2.3"
@@ -11622,11 +12554,6 @@ write-json-file@^4.3.0:
     sort-keys "^4.0.0"
     write-file-atomic "^3.0.0"
 
-xdg-basedir@^4.0.0:
-  version "4.0.0"
-  resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
-  integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
-
 xml2js@0.4.16:
   version "0.4.16"
   resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.16.tgz#f82fccd2f9540d7e0a9b5dac163e7471195c9db3"
@@ -11643,7 +12570,7 @@ xml2js@0.4.19:
     sax ">=0.6.0"
     xmlbuilder "~9.0.1"
 
-xml2js@^0.4.23:
+xml2js@0.4.23, xml2js@^0.4.23:
   version "0.4.23"
   resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66"
   integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==
@@ -11678,11 +12605,6 @@ y18n@^5.0.5:
   resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
   integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
 
-yallist@^3.0.0, yallist@^3.1.1:
-  version "3.1.1"
-  resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
-  integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
-
 yallist@^4.0.0:
   version "4.0.0"
   resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
@@ -11693,7 +12615,7 @@ yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2:
   resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
   integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
 
-yamljs@^0.3.0:
+yamljs@0.3.0:
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/yamljs/-/yamljs-0.3.0.tgz#dc060bf267447b39f7304e9b2bfbe8b5a7ddb03b"
   integrity sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==
@@ -11732,10 +12654,10 @@ yargs@^16.0.0, yargs@^16.1.0, yargs@^16.2.0:
     y18n "^5.0.5"
     yargs-parser "^20.2.2"
 
-yargs@^17.0.0, yargs@^17.0.1:
-  version "17.3.1"
-  resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.3.1.tgz#da56b28f32e2fd45aefb402ed9c26f42be4c07b9"
-  integrity sha512-WUANQeVgjLbNsEmGk20f+nlHgOqzRFpiGWVaBrYGYIGANIIu3lWjoyi0fNlFmJkvfhCZ6BXINe7/W2O2bV4iaA==
+yargs@^17.0.0, yargs@^17.3.1:
+  version "17.5.1"
+  resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.5.1.tgz#e109900cab6fcb7fd44b1d8249166feb0b36e58e"
+  integrity sha512-t6YAJcxDkNX7NFYiVtKvWUz8l+PaKTLiL63mJYWR2GnHq2gjEWISzsLp9wg3aY36dY1j+gfIEL3pIF+XlJJfbA==
   dependencies:
     cliui "^7.0.2"
     escalade "^3.1.1"
@@ -11745,6 +12667,14 @@ yargs@^17.0.0, yargs@^17.0.1:
     y18n "^5.0.5"
     yargs-parser "^21.0.0"
 
+yauzl@^2.10.0:
+  version "2.10.0"
+  resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
+  integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==
+  dependencies:
+    buffer-crc32 "~0.2.3"
+    fd-slicer "~1.1.0"
+
 yn@3.1.1:
   version "3.1.1"
   resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
@@ -11755,7 +12685,7 @@ yocto-queue@^0.1.0:
   resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
   integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
 
-yup@^0.32.11:
+yup@0.32.11:
   version "0.32.11"
   resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.11.tgz#d67fb83eefa4698607982e63f7ca4c5ed3cf18c5"
   integrity sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==
@@ -11767,16 +12697,3 @@ yup@^0.32.11:
     nanoclone "^0.2.1"
     property-expr "^2.0.4"
     toposort "^2.0.2"
-
-zen-observable-ts@^1.0.0:
-  version "1.1.0"
-  resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz#2d1aa9d79b87058e9b75698b92791c1838551f83"
-  integrity sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA==
-  dependencies:
-    "@types/zen-observable" "0.8.3"
-    zen-observable "0.8.15"
-
-zen-observable@0.8.15:
-  version "0.8.15"
-  resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15"
-  integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==