Compare commits

..

28 Commits

Author SHA1 Message Date
Alex
13973dc53a Merge branch 'develop' into cleanup/dead-code 2026-06-01 19:24:11 +10:00
github-actions[bot]
32c99de874 feat: New Crowdin Translations (#1460)
Some checks are pending
🏗️ Build Apps / 🤖 Build Android APK (Phone) (push) Waiting to run
🏗️ Build Apps / 🤖 Build Android APK (TV) (push) Waiting to run
🏗️ Build Apps / 🍎 Build iOS IPA (Phone) (push) Waiting to run
🏗️ Build Apps / 🍎 Build iOS IPA (Phone - Unsigned) (push) Waiting to run
🏗️ Build Apps / 🍎 Build tvOS IPA (push) Waiting to run
🏗️ Build Apps / 🍎 Build tvOS IPA (Unsigned) (push) Waiting to run
🔒 Lockfile Consistency Check / 🔍 Check bun.lock and package.json consistency (push) Waiting to run
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (actions) (push) Waiting to run
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (javascript-typescript) (push) Waiting to run
🏷️🔀Merge Conflict Labeler / 🏷️ Labeling Merge Conflicts (push) Waiting to run
🌐 Translation Sync / sync-translations (push) Waiting to run
🚦 Security & Quality Gate / 📝 Validate PR Title (push) Waiting to run
🚦 Security & Quality Gate / 🔍 Vulnerable Dependencies (push) Waiting to run
🚦 Security & Quality Gate / 🚑 Expo Doctor Check (push) Waiting to run
🚦 Security & Quality Gate / 🔍 Lint & Test (check) (push) Waiting to run
🚦 Security & Quality Gate / 🔍 Lint & Test (format) (push) Waiting to run
🚦 Security & Quality Gate / 🔍 Lint & Test (lint) (push) Waiting to run
🚦 Security & Quality Gate / 🔍 Lint & Test (typecheck) (push) Waiting to run
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2026-06-01 10:33:17 +02:00
Fredrik Burmester
c232e433bf fix(ci): grant actions:read to github-release job (#1634) 2026-06-01 10:31:05 +02:00
Fredrik Burmester
07e2faff07 fix(tv): only add user-management entitlement for tvOS builds (#1633) 2026-06-01 10:28:21 +02:00
Fredrik Burmester
8507699cdd feat(eas): force bun on EAS via custom build configs + 5-build release workflow (#1632) 2026-06-01 10:24:52 +02:00
Gauvain
21fb056586 fix(i18n): make two hardcoded titles translatable (#1627) 2026-06-01 09:46:27 +02:00
Gauvain
1d79b513f3 fix(item): dedupe top people sections by id (#1623) 2026-06-01 09:37:45 +02:00
Gauvain
863dffd944 fix(chapters): keep landscape when opening chapter list on iOS (#1624) 2026-06-01 09:37:35 +02:00
lance chant
6aa0868bfd fix: fixed a runtime issue for android (#1628)
Signed-off-by: Lance Chant <13349722+lancechant@users.noreply.github.com>
2026-06-01 09:35:19 +02:00
Gauvain
8eeb571f33 refactor: remove dead code
Delete unused components, hooks and utilities that have no remaining references, and drop their now-unused exports (augmentations/string, Number.prototype.hoursToMilliseconds). Also drop the dangling ExampleGlobalModalUsage reference from GLOBAL_MODAL_GUIDE.md.
2026-06-01 00:54:18 +02:00
Felix Schneider
6b7ee0514f feat(i18n): add new translations for action sheet options (#1475)
Some checks failed
🏗️ Build Apps / 🤖 Build Android APK (Phone) (push) Has been cancelled
🏗️ Build Apps / 🤖 Build Android APK (TV) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build iOS IPA (Phone) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build iOS IPA (Phone - Unsigned) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build tvOS IPA (push) Has been cancelled
🏗️ Build Apps / 🍎 Build tvOS IPA (Unsigned) (push) Has been cancelled
🔒 Lockfile Consistency Check / 🔍 Check bun.lock and package.json consistency (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (javascript-typescript) (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (actions) (push) Has been cancelled
🏷️🔀Merge Conflict Labeler / 🏷️ Labeling Merge Conflicts (push) Has been cancelled
🌐 Translation Sync / sync-translations (push) Has been cancelled
🚦 Security & Quality Gate / 📝 Validate PR Title (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Vulnerable Dependencies (push) Has been cancelled
🚦 Security & Quality Gate / 🚑 Expo Doctor Check (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (check) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (format) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (lint) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (typecheck) (push) Has been cancelled
Co-authored-by: lance chant <13349722+lancechant@users.noreply.github.com>
Co-authored-by: Gauvain <contact@uruk.dev>
2026-05-31 23:45:45 +02:00
Fredrik Burmester
c663bd0413 fix(jellyseerr): correct RequestModal ref type to fix typecheck
advancedReqModalRef was typed as BottomSheetModal but RequestModal's
forwardRef expects BottomSheetModalMethods, causing a TS2322 error
that broke the Security & Quality Gate typecheck on develop.
2026-05-31 22:10:15 +02:00
Alex
52e6f56220 fix(auth): clear stored user on logout to prevent empty home on relaunch (#1622) 2026-05-31 21:52:41 +02:00
Fredrik Burmester
c981f59a50 fix(downloads): repair bottom sheets on iOS and restore downloads delete sheet
Some checks failed
🏗️ Build Apps / 🤖 Build Android APK (Phone) (push) Has been cancelled
🏗️ Build Apps / 🤖 Build Android APK (TV) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build iOS IPA (Phone) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build iOS IPA (Phone - Unsigned) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build tvOS IPA (push) Has been cancelled
🏗️ Build Apps / 🍎 Build tvOS IPA (Unsigned) (push) Has been cancelled
🔒 Lockfile Consistency Check / 🔍 Check bun.lock and package.json consistency (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (actions) (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (javascript-typescript) (push) Has been cancelled
🏷️🔀Merge Conflict Labeler / 🏷️ Labeling Merge Conflicts (push) Has been cancelled
🌐 Translation Sync / sync-translations (push) Has been cancelled
🚦 Security & Quality Gate / 📝 Validate PR Title (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Vulnerable Dependencies (push) Has been cancelled
🚦 Security & Quality Gate / 🚑 Expo Doctor Check (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (check) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (format) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (lint) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (typecheck) (push) Has been cancelled
Bump @gorhom/bottom-sheet 5.2.8 -> 5.2.14, which fixes BottomSheetModal
present() silently no-opping under Reanimated 4 / New Architecture (SDK 56).
Affected every sheet app-wide: present() was called with a valid ref but
nothing rendered (not even the backdrop). Verified on the iOS simulator that
the download options sheet now opens.

Also restore the downloads-page delete sheet (delete movies/series/other/all)
that was accidentally dropped in the Expo 54 rewrite (#1174), which left an
orphaned trigger button and underscore-silenced handlers.
2026-05-31 14:58:51 +02:00
Alex
62fc6f9a70 fix(progress-bar): Fix progress bar not reporting watch times (#1611)
Co-authored-by: Gauvain <contact@uruk.dev>
2026-05-31 22:12:13 +10:00
Fredrik Burmester
eb8dd51b4e feat(ci): EAS build + auto-submit release workflow for main (#1616) 2026-05-31 13:23:02 +02:00
Fredrik Burmester
ea5a999f21 fix(deps): declare react-native-tab-view and material-top-tabs (#1617) 2026-05-31 12:40:56 +02:00
Felix Schneider
dffcdef945 feat(i18n): Add translation for "ends at" (#1474)
Co-authored-by: Gauvain <contact@uruk.dev>
2026-05-31 12:10:22 +02:00
Fredrik Burmester
fa1c3f3947 chore(eas): pin appleTeamId and ascAppId in submit profiles
Some checks failed
🏗️ Build Apps / 🤖 Build Android APK (Phone) (push) Has been cancelled
🏗️ Build Apps / 🤖 Build Android APK (TV) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build iOS IPA (Phone) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build iOS IPA (Phone - Unsigned) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build tvOS IPA (push) Has been cancelled
🏗️ Build Apps / 🍎 Build tvOS IPA (Unsigned) (push) Has been cancelled
🔒 Lockfile Consistency Check / 🔍 Check bun.lock and package.json consistency (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (actions) (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (javascript-typescript) (push) Has been cancelled
🏷️🔀Merge Conflict Labeler / 🏷️ Labeling Merge Conflicts (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Vulnerable Dependencies (push) Has been cancelled
🚦 Security & Quality Gate / 📝 Validate PR Title (push) Has been cancelled
🚦 Security & Quality Gate / 🚑 Expo Doctor Check (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (check) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (format) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (lint) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (typecheck) (push) Has been cancelled
Avoid the interactive Apple team picker and app-existence lookup on
submit by pinning the Individual team (MWD5K362T8) and ASC App ID.
2026-05-31 11:22:59 +02:00
Fredrik Burmester
2761de5a74 chore(eas): use remote app version source with autoIncrement
Switch cli.appVersionSource to remote and enable autoIncrement on all
production profiles so EAS bumps the build number every release instead
of resetting to 1. Remove the dead android.versionCode from app.json and
the unused EAS Update channel (no expo-updates installed).
2026-05-31 11:22:59 +02:00
Fredrik Burmester
feca1d7e9c fix(android): resolve mpv-player Kotlin smart-cast build error (#1614) 2026-05-31 10:50:06 +02:00
Fredrik Burmester
6b6bfd1a89 fix(player): remove white blob artifacts on vertical sliders 2026-05-31 10:48:24 +02:00
Fredrik Burmester
d585b20f49 chore: version 2026-05-31 09:44:05 +02:00
Fredrik Burmester
692ccfdb2c fix(tvos): add arm64 UIRequiredDeviceCapabilities to Top Shelf extension
App Store Connect rejected TestFlight submissions because the Top Shelf
extension binary has a 64-bit slice but did not declare arm64 under
UIRequiredDeviceCapabilities in its Info.plist.
2026-05-31 09:42:09 +02:00
Fredrik Burmester
86e39c444c fix(ios): SDK 56 / iOS 26 EAS build fixes (SwiftUICore autolink + patch-package) (#1613) 2026-05-31 09:37:08 +02:00
Fredrik Burmester
ed7928b4d3 Merge remote-tracking branch 'origin/feat/tv-interface' into develop
Some checks failed
🏗️ Build Apps / 🤖 Build Android APK (Phone) (push) Has been cancelled
🏗️ Build Apps / 🤖 Build Android APK (TV) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build iOS IPA (Phone) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build iOS IPA (Phone - Unsigned) (push) Has been cancelled
🏗️ Build Apps / 🍎 Build tvOS IPA (push) Has been cancelled
🏗️ Build Apps / 🍎 Build tvOS IPA (Unsigned) (push) Has been cancelled
🔒 Lockfile Consistency Check / 🔍 Check bun.lock and package.json consistency (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (actions) (push) Has been cancelled
🛡️ CodeQL Analysis / 🔎 Analyze with CodeQL (javascript-typescript) (push) Has been cancelled
🏷️🔀Merge Conflict Labeler / 🏷️ Labeling Merge Conflicts (push) Has been cancelled
🚦 Security & Quality Gate / 📝 Validate PR Title (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Vulnerable Dependencies (push) Has been cancelled
🚦 Security & Quality Gate / 🚑 Expo Doctor Check (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (check) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (format) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (lint) (push) Has been cancelled
🚦 Security & Quality Gate / 🔍 Lint & Test (typecheck) (push) Has been cancelled
🌐 Translation Sync / sync-translations (push) Has been cancelled
2026-05-30 22:47:33 +02:00
lance chant
27dc7b5664 fix: android pip (#1605)
Signed-off-by: Lance Chant <13349722+lancechant@users.noreply.github.com>
2026-05-30 22:45:19 +02:00
Alex
a205c75895 chore(mpv-player): Update to MPVKIT 0.41 (#1604) 2026-05-30 22:45:07 +02:00
90 changed files with 7087 additions and 2188 deletions

View File

@@ -0,0 +1,25 @@
# Custom EAS Build config for Android phone APK (downloadable artifact).
# Same bun-forcing flow as android-production.yml, but builds an APK
# (assembleRelease) instead of an AAB — for sideloading / GitHub artifact.
# Referenced from eas.json: build.production-apk.android.config
build:
name: Android phone APK (bun)
steps:
- eas/checkout
- run:
name: Install dependencies (bun, frozen)
command: bun install --frozen-lockfile
- run:
name: Prebuild (Android, bun)
command: bunx expo prebuild --platform android --no-install
- eas/configure_android_version
- eas/inject_android_credentials
- eas/run_gradle:
inputs:
command: :app:assembleRelease
- eas/find_and_upload_build_artifacts

View File

@@ -0,0 +1,27 @@
# Custom EAS Build config for Android TV APK (downloadable artifact).
# Same bun-forcing flow, with EXPO_TV=1 (set via the profile env in
# eas.json) so prebuild generates the TV variant. Builds an APK for
# sideloading onto Android TV devices.
# Referenced from eas.json: build.production-apk-tv.android.config
build:
name: Android TV APK (bun)
steps:
- eas/checkout
- run:
name: Install dependencies (bun, frozen)
command: bun install --frozen-lockfile
# EXPO_TV=1 comes from the profile env, so prebuild targets Android TV.
- run:
name: Prebuild (Android TV, bun)
command: bunx expo prebuild --platform android --no-install
- eas/configure_android_version
- eas/inject_android_credentials
- eas/run_gradle:
inputs:
command: :app:assembleRelease
- eas/find_and_upload_build_artifacts

View File

@@ -0,0 +1,38 @@
# Custom EAS Build config for Android (production AAB).
#
# Why this exists: EAS's managed build can't detect Bun's text lockfile
# (bun.lock) and falls back to yarn, which breaks our install. The managed
# steps `eas/install_node_modules` and `eas/prebuild` both use "the package
# manager detected based on your project", so we replace them with explicit
# `bun` commands. Everything else uses EAS's built-in functions so we still
# get remote versioning, credentials, and artifact upload.
#
# Referenced from eas.json: build.production.android.config = android-production.yml
build:
name: Android production (bun)
steps:
- eas/checkout
- run:
name: Install dependencies (bun, frozen)
command: bun install --frozen-lockfile
# android/ is gitignored, so generate native code fresh. --no-install
# because deps are already installed above; bunx keeps it on bun.
- run:
name: Prebuild (Android, bun)
command: bunx expo prebuild --platform android --no-install
# Applies the EAS-resolved remote versionCode/versionName (autoIncrement
# in eas.json) into the freshly prebuilt android/ project.
- eas/configure_android_version
# Injects the remote Android keystore / signing config.
- eas/inject_android_credentials
# Build the Play Store app bundle (.aab).
- eas/run_gradle:
inputs:
command: :app:bundleRelease
- eas/find_and_upload_build_artifacts

View File

@@ -0,0 +1,44 @@
# Custom EAS Build config for iOS + tvOS (App Store), forcing bun.
#
# Shared by both the iPhone profile (production) and the tvOS profile
# (production_tv). The profile decides the rest:
# - production_tv sets EXPO_TV=1 (env) so prebuild targets tvOS, and
# credentialsSource: local (EAS can't manage tvOS creds remotely).
# - production uses remote-managed iOS credentials.
#
# Like the Android configs, this replaces eas/install_node_modules and
# eas/prebuild (both auto-detect the wrong package manager) with explicit
# bun commands, and keeps EAS built-ins for credentials/version/fastlane.
build:
name: iOS/tvOS App Store (bun)
steps:
- eas/checkout
- run:
name: Install dependencies (bun, frozen)
command: bun install --frozen-lockfile
- eas/resolve_apple_team_id_from_credentials:
id: resolve_team
# android/ + ios/ are gitignored, so generate native code fresh.
# EXPO_TV (from the profile env) selects iPhone vs tvOS. --no-install
# skips JS + pod install; we install pods explicitly below with bun deps.
- run:
name: Prebuild (iOS/tvOS, bun)
command: bunx expo prebuild --platform ios --no-install
- run:
name: Install CocoaPods
working_directory: ./ios
command: pod install
- eas/configure_ios_credentials
- eas/configure_ios_version
- eas/generate_gymfile_from_template:
inputs:
credentials: ${ eas.job.secrets.buildCredentials }
- eas/run_fastlane
- eas/find_and_upload_build_artifacts

216
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,216 @@
name: 🚀 Release (EAS build + submit)
# On merge to main (gated by the `production` GitHub Environment approval),
# build all targets on EAS in parallel via custom bun build configs:
# 1. iOS phone → App Store (auto-submit)
# 2. tvOS → App Store (auto-submit)
# 3. Android AAB → Google Play (auto-submit)
# 4. Android phone APK→ downloadable artifact
# 5. Android TV APK → downloadable artifact
# Note: EAS queues builds based on your plan's concurrency; parallel jobs
# here just submit them — EAS may still run them serially.
concurrency:
group: release-${{ github.ref }}
cancel-in-progress: false
on:
push:
branches: [main]
workflow_dispatch:
jobs:
approve:
name: 🔐 Approve release
runs-on: ubuntu-24.04
environment: production
steps:
- name: ✅ Release approved
run: echo "Release approved for ${{ github.sha }}"
build:
name: 🚀 ${{ matrix.name }}
needs: approve
runs-on: ubuntu-24.04
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include:
- name: 🍎 iOS
platform: ios
profile: production
submit: true
- name: 📺 tvOS
platform: ios
profile: production_tv
submit: true
- name: 🤖 Android AAB
platform: android
profile: production
submit: true
- name: 🤖 Android APK
platform: android
profile: production-apk
submit: false
artifact_name: streamyfin-android-phone-apk
- name: 📺 Android TV APK
platform: android
profile: production-apk-tv
submit: false
artifact_name: streamyfin-android-tv-apk
steps:
- name: 📥 Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
submodules: recursive
show-progress: false
- name: 🍞 Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: latest
- name: 💾 Cache Bun dependencies
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ~/.bun/install/cache
key: ${{ runner.os }}-bun-cache-${{ hashFiles('bun.lock') }}
restore-keys: |
${{ runner.os }}-bun-cache
- name: 📦 Install dependencies and reload submodules
run: |
bun install --frozen-lockfile
bun run submodule-reload
- name: 🏗️ Setup EAS
uses: expo/expo-github-action@b184ff86a3c926240f1b6db41764c83a01c02eef # main
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}
eas-cache: true
# tvOS uses credentialsSource: local — restore the gitignored
# credentials.json + cert + provisioning profiles from secrets.
- name: 🔐 Restore tvOS signing credentials
if: matrix.profile == 'production_tv'
env:
EAS_CREDENTIALS_JSON: ${{ secrets.EAS_CREDENTIALS_JSON }}
TVOS_DIST_CERT_P12_BASE64: ${{ secrets.TVOS_DIST_CERT_P12_BASE64 }}
TVOS_APP_PROFILE_BASE64: ${{ secrets.TVOS_APP_PROFILE_BASE64 }}
TVOS_TOPSHELF_PROFILE_BASE64: ${{ secrets.TVOS_TOPSHELF_PROFILE_BASE64 }}
run: |
mkdir -p certs profiles
printf '%s' "$EAS_CREDENTIALS_JSON" > credentials.json
echo "$TVOS_DIST_CERT_P12_BASE64" | base64 -d > certs/distribution.p12
echo "$TVOS_APP_PROFILE_BASE64" | base64 -d > profiles/Streamyfin_tvOS_App_Store.mobileprovision
echo "$TVOS_TOPSHELF_PROFILE_BASE64" | base64 -d > profiles/Streamyfin_TopShelf_tvOS_App_Store.mobileprovision
# Android Play submit needs the Google Play service account JSON.
- name: 🔐 Restore Google Play service account
if: matrix.platform == 'android' && matrix.submit
env:
GOOGLE_SERVICE_ACCOUNT_KEY: ${{ secrets.GOOGLE_SERVICE_ACCOUNT_KEY }}
run: printf '%s' "$GOOGLE_SERVICE_ACCOUNT_KEY" > google-service-account.json
# App Store Connect API key for iOS/tvOS submit (raw-PEM or base64).
- name: 🔐 Restore App Store Connect API key
if: matrix.platform == 'ios'
env:
APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }}
run: |
if printf '%s' "$APPLE_KEY_CONTENT" | grep -q "BEGIN PRIVATE KEY"; then
printf '%s' "$APPLE_KEY_CONTENT" > "$RUNNER_TEMP/asc_api_key.p8"
else
printf '%s' "$APPLE_KEY_CONTENT" | base64 -d > "$RUNNER_TEMP/asc_api_key.p8"
fi
# ── Submit builds: cloud build + auto-submit to the store ──
- name: 🚀 Build & submit (${{ matrix.name }})
if: matrix.submit
env:
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
EXPO_ASC_API_KEY_PATH: ${{ runner.temp }}/asc_api_key.p8
EXPO_ASC_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
EXPO_ASC_ISSUER_ID: ${{ secrets.APPLE_KEY_ISSUER_ID }}
run: |
eas build \
--platform ${{ matrix.platform }} \
--profile ${{ matrix.profile }} \
--auto-submit \
--non-interactive \
--wait
# ── Artifact builds: cloud build, then download + upload the APK ──
- name: 🏗️ Build artifact (${{ matrix.name }})
if: ${{ !matrix.submit }}
env:
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
run: |
eas build \
--platform ${{ matrix.platform }} \
--profile ${{ matrix.profile }} \
--non-interactive \
--wait \
--json > build-result.json
URL=$(node -e "const b=require('./build-result.json'); const x=Array.isArray(b)?b[0]:b; console.log(x.artifacts.applicationArchiveUrl)")
echo "Downloading artifact: $URL"
curl -fL "$URL" -o "${{ matrix.artifact_name }}.apk"
- name: 📤 Upload APK artifact (${{ matrix.name }})
if: ${{ !matrix.submit }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ matrix.artifact_name }}
path: ${{ matrix.artifact_name }}.apk
retention-days: 14
# Draft a GitHub Release with the two APKs attached. The tag comes from the
# merged-in app version (app.json → expo.version), NOT the auto-incremented
# build number — so cutting a release is a deliberate version bump via PR.
github-release:
name: 📦 Draft GitHub Release
needs: build
if: ${{ !cancelled() }}
runs-on: ubuntu-24.04
permissions:
contents: write
actions: read # required for `gh run download` to list/fetch this run's artifacts
steps:
- name: 📥 Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
show-progress: false
- name: 📦 Download APK artifacts from this run
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
mkdir -p apks
gh run download ${{ github.run_id }} --name streamyfin-android-phone-apk --dir apks
gh run download ${{ github.run_id }} --name streamyfin-android-tv-apk --dir apks
ls -la apks
- name: 📝 Draft release (tag = app.json version, not auto-bumped)
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION=$(node -e "console.log(require('./app.json').expo.version)")
TAG="v$VERSION"
echo "Release tag from merged app version: $TAG"
if gh release view "$TAG" >/dev/null 2>&1; then
echo "Release $TAG exists — updating APK assets"
gh release upload "$TAG" apks/*.apk --clobber
else
echo "Creating draft release $TAG"
gh release create "$TAG" \
--draft \
--generate-notes \
--title "$TAG" \
apks/*.apk
fi

9
.gitignore vendored
View File

@@ -18,6 +18,9 @@ web-build/
/androidmobile /androidmobile
/androidtv /androidtv
# Gradle caches (top-level + per-module native projects)
**/.gradle/
# Module-specific Builds # Module-specific Builds
modules/mpv-player/android/build modules/mpv-player/android/build
modules/player/android modules/player/android
@@ -73,6 +76,12 @@ modules/background-downloader/android/build/*
# ios:unsigned-build Artifacts # ios:unsigned-build Artifacts
build/ build/
# but keep EAS custom build configs (the generic build/ rule above matches .eas/build/)
!.eas/build/
!.eas/build/**
.claude/ .claude/
.agents/skills/** .agents/skills/**
skills-lock.json skills-lock.json
# CI-injected Google Play service account key (written at build time)
google-service-account.json

View File

@@ -143,14 +143,6 @@ interface ModalOptions {
} }
``` ```
## Examples
See `components/ExampleGlobalModalUsage.tsx` for comprehensive examples including:
- Simple content modal
- Modal with custom snap points
- Complex component in modal
- Success/error modals triggered from functions
## Default Styling ## Default Styling
The modal uses these default styles (can be overridden via options): The modal uses these default styles (can be overridden via options):

View File

@@ -2,7 +2,7 @@
"expo": { "expo": {
"name": "Streamyfin", "name": "Streamyfin",
"slug": "streamyfin", "slug": "streamyfin",
"version": "0.54.0", "version": "0.54.1",
"orientation": "default", "orientation": "default",
"icon": "./assets/images/icon.png", "icon": "./assets/images/icon.png",
"scheme": "streamyfin", "scheme": "streamyfin",
@@ -36,7 +36,6 @@
"appleTeamId": "MWD5K362T8" "appleTeamId": "MWD5K362T8"
}, },
"android": { "android": {
"versionCode": 93,
"adaptiveIcon": { "adaptiveIcon": {
"foregroundImage": "./assets/images/icon-android-plain.png", "foregroundImage": "./assets/images/icon-android-plain.png",
"monochromeImage": "./assets/images/icon-android-themed.png", "monochromeImage": "./assets/images/icon-android-themed.png",
@@ -144,8 +143,8 @@
[ [
"./plugins/withGitPod.js", "./plugins/withGitPod.js",
{ {
"podName": "MPVKit-GPL", "podName": "MPVKit",
"podspecUrl": "https://raw.githubusercontent.com/streamyfin/MPVKit/0.40.0-av/MPVKit-GPL.podspec" "podspecUrl": "https://raw.githubusercontent.com/mpv-ios/MPVKit/0.41.0-av/MPVKit.podspec"
} }
] ]
], ],

View File

@@ -1,4 +1,9 @@
import { BottomSheetModal } from "@gorhom/bottom-sheet"; import {
BottomSheetBackdrop,
type BottomSheetBackdropProps,
BottomSheetModal,
BottomSheetView,
} from "@gorhom/bottom-sheet";
import { useNavigation } from "expo-router"; import { useNavigation } from "expo-router";
import { useAtom } from "jotai"; import { useAtom } from "jotai";
import { useEffect, useMemo, useRef, useState } from "react"; import { useEffect, useMemo, useRef, useState } from "react";
@@ -7,6 +12,7 @@ import { Alert, Platform, ScrollView, View } from "react-native";
import { Pressable } from "react-native-gesture-handler"; import { Pressable } from "react-native-gesture-handler";
import { useSafeAreaInsets } from "react-native-safe-area-context"; import { useSafeAreaInsets } from "react-native-safe-area-context";
import { toast } from "sonner-native"; import { toast } from "sonner-native";
import { Button } from "@/components/Button";
import { Text } from "@/components/common/Text"; import { Text } from "@/components/common/Text";
import { TouchableItemRouter } from "@/components/common/TouchableItemRouter"; import { TouchableItemRouter } from "@/components/common/TouchableItemRouter";
import ActiveDownloads from "@/components/downloads/ActiveDownloads"; import ActiveDownloads from "@/components/downloads/ActiveDownloads";
@@ -101,7 +107,7 @@ export default function DownloadsPage() {
navigation.setOptions({ navigation.setOptions({
headerRight: () => ( headerRight: () => (
<Pressable <Pressable
onPress={bottomSheetModalRef.current?.present} onPress={() => bottomSheetModalRef.current?.present()}
className='px-2' className='px-2'
> >
<DownloadSize items={downloadedFiles?.map((f) => f.item) || []} /> <DownloadSize items={downloadedFiles?.map((f) => f.item) || []} />
@@ -116,7 +122,7 @@ export default function DownloadsPage() {
} }
}, [showMigration]); }, [showMigration]);
const _deleteMovies = () => const deleteMovies = () =>
deleteFileByType("Movie") deleteFileByType("Movie")
.then(() => .then(() =>
toast.success( toast.success(
@@ -127,7 +133,7 @@ export default function DownloadsPage() {
writeToLog("ERROR", reason); writeToLog("ERROR", reason);
toast.error(t("home.downloads.toasts.failed_to_delete_all_movies")); toast.error(t("home.downloads.toasts.failed_to_delete_all_movies"));
}); });
const _deleteShows = () => const deleteShows = () =>
deleteFileByType("Episode") deleteFileByType("Episode")
.then(() => .then(() =>
toast.success( toast.success(
@@ -138,7 +144,7 @@ export default function DownloadsPage() {
writeToLog("ERROR", reason); writeToLog("ERROR", reason);
toast.error(t("home.downloads.toasts.failed_to_delete_all_tvseries")); toast.error(t("home.downloads.toasts.failed_to_delete_all_tvseries"));
}); });
const _deleteOtherMedia = () => const deleteOtherMedia = () =>
Promise.all( Promise.all(
otherMedia otherMedia
.filter((item) => item.item.Type) .filter((item) => item.item.Type)
@@ -162,6 +168,9 @@ export default function DownloadsPage() {
), ),
); );
const deleteAllMedia = async () =>
await Promise.all([deleteMovies(), deleteShows(), deleteOtherMedia()]);
return ( return (
<OfflineModeProvider isOffline={true}> <OfflineModeProvider isOffline={true}>
<ScrollView <ScrollView
@@ -256,6 +265,42 @@ export default function DownloadsPage() {
)} )}
</View> </View>
</ScrollView> </ScrollView>
<BottomSheetModal
ref={bottomSheetModalRef}
enableDynamicSizing
handleIndicatorStyle={{
backgroundColor: "white",
}}
backgroundStyle={{
backgroundColor: "#171717",
}}
backdropComponent={(props: BottomSheetBackdropProps) => (
<BottomSheetBackdrop
{...props}
disappearsOnIndex={-1}
appearsOnIndex={0}
/>
)}
>
<BottomSheetView>
<View className='p-4 space-y-4 mb-4'>
<Button color='purple' onPress={deleteMovies}>
{t("home.downloads.delete_all_movies_button")}
</Button>
<Button color='purple' onPress={deleteShows}>
{t("home.downloads.delete_all_tvseries_button")}
</Button>
{otherMedia.length > 0 && (
<Button color='purple' onPress={deleteOtherMedia}>
{t("home.downloads.delete_all_other_media_button")}
</Button>
)}
<Button color='red' onPress={deleteAllMedia}>
{t("home.downloads.delete_all_button")}
</Button>
</View>
</BottomSheetView>
</BottomSheetModal>
</OfflineModeProvider> </OfflineModeProvider>
); );
} }

View File

@@ -6,6 +6,7 @@ import {
BottomSheetTextInput, BottomSheetTextInput,
BottomSheetView, BottomSheetView,
} from "@gorhom/bottom-sheet"; } from "@gorhom/bottom-sheet";
import type { BottomSheetModalMethods } from "@gorhom/bottom-sheet/lib/typescript/types";
import { useQuery } from "@tanstack/react-query"; import { useQuery } from "@tanstack/react-query";
import { Image } from "expo-image"; import { Image } from "expo-image";
import { useLocalSearchParams, useNavigation } from "expo-router"; import { useLocalSearchParams, useNavigation } from "expo-router";
@@ -76,7 +77,7 @@ const MobilePage: React.FC = () => {
const [issueMessage, setIssueMessage] = useState<string>(); const [issueMessage, setIssueMessage] = useState<string>();
const [requestBody, _setRequestBody] = useState<MediaRequestBody>(); const [requestBody, _setRequestBody] = useState<MediaRequestBody>();
const [issueTypeDropdownOpen, setIssueTypeDropdownOpen] = useState(false); const [issueTypeDropdownOpen, setIssueTypeDropdownOpen] = useState(false);
const advancedReqModalRef = useRef<BottomSheetModal>(null); const advancedReqModalRef = useRef<BottomSheetModalMethods>(null);
const bottomSheetModalRef = useRef<BottomSheetModal>(null); const bottomSheetModalRef = useRef<BottomSheetModal>(null);
const { const {

View File

@@ -825,12 +825,10 @@ export default function DirectPlayerPage() {
], ],
); );
/** PiP handler for MPV */
const _onPictureInPictureChange = useCallback( const _onPictureInPictureChange = useCallback(
(e: { nativeEvent: { isActive: boolean } }) => { (e: { nativeEvent: { isActive: boolean } }) => {
const { isActive } = e.nativeEvent; const { isActive } = e.nativeEvent;
setIsPipMode(isActive); setIsPipMode(isActive);
// Hide controls when entering PiP
if (isActive) { if (isActive) {
_setShowControls(false); _setShowControls(false);
} }
@@ -848,6 +846,9 @@ export default function DirectPlayerPage() {
// Memoize video ref functions to prevent unnecessary re-renders // Memoize video ref functions to prevent unnecessary re-renders
const startPictureInPicture = useCallback(async () => { const startPictureInPicture = useCallback(async () => {
// Hide controls BEFORE entering PiP so the window captures a clean view
_setShowControls(false);
setIsPipMode(true);
return videoRef.current?.startPictureInPicture?.(); return videoRef.current?.startPictureInPicture?.();
}, []); }, []);
@@ -1253,6 +1254,7 @@ export default function DirectPlayerPage() {
nowPlayingMetadata={nowPlayingMetadata} nowPlayingMetadata={nowPlayingMetadata}
onProgress={onProgress} onProgress={onProgress}
onPlaybackStateChange={onPlaybackStateChanged} onPlaybackStateChange={onPlaybackStateChanged}
onPictureInPictureChange={_onPictureInPictureChange}
onLoad={() => setIsVideoLoaded(true)} onLoad={() => setIsVideoLoaded(true)}
onError={(e: { nativeEvent: MpvOnErrorEventPayload }) => { onError={(e: { nativeEvent: MpvOnErrorEventPayload }) => {
console.error("Video Error:", e.nativeEvent); console.error("Video Error:", e.nativeEvent);

View File

@@ -1,4 +1,3 @@
export * from "./api"; export * from "./api";
export * from "./mmkv"; export * from "./mmkv";
export * from "./number"; export * from "./number";
export * from "./string";

View File

@@ -3,7 +3,6 @@ declare global {
bytesToReadable(decimals?: number): string; bytesToReadable(decimals?: number): string;
secondsToMilliseconds(): number; secondsToMilliseconds(): number;
minutesToMilliseconds(): number; minutesToMilliseconds(): number;
hoursToMilliseconds(): number;
} }
} }
@@ -28,8 +27,4 @@ Number.prototype.minutesToMilliseconds = function () {
return this.valueOf() * (60).secondsToMilliseconds(); return this.valueOf() * (60).secondsToMilliseconds();
}; };
Number.prototype.hoursToMilliseconds = function () {
return this.valueOf() * (60).minutesToMilliseconds();
};
export {}; export {};

View File

@@ -1,14 +0,0 @@
declare global {
interface String {
toTitle(): string;
}
}
String.prototype.toTitle = function () {
return this.replaceAll("_", " ").replace(
/\w\S*/g,
(text) => text.charAt(0).toUpperCase() + text.substring(1).toLowerCase(),
);
};
export {};

View File

@@ -11,9 +11,10 @@
"@expo/react-native-action-sheet": "^4.1.1", "@expo/react-native-action-sheet": "^4.1.1",
"@expo/ui": "~56.0.14", "@expo/ui": "~56.0.14",
"@expo/vector-icons": "^15.0.3", "@expo/vector-icons": "^15.0.3",
"@gorhom/bottom-sheet": "5.2.8", "@gorhom/bottom-sheet": "5.2.14",
"@jellyfin/sdk": "^0.13.0", "@jellyfin/sdk": "^0.13.0",
"@react-native-community/netinfo": "^12.0.0", "@react-native-community/netinfo": "^12.0.0",
"@react-navigation/material-top-tabs": "7.4.28",
"@react-navigation/native": "^7.2.5", "@react-navigation/native": "^7.2.5",
"@shopify/flash-list": "2.0.2", "@shopify/flash-list": "2.0.2",
"@tanstack/query-sync-storage-persister": "^5.100.14", "@tanstack/query-sync-storage-persister": "^5.100.14",
@@ -75,7 +76,7 @@
"react-native-ios-context-menu": "^3.2.1", "react-native-ios-context-menu": "^3.2.1",
"react-native-ios-utilities": "5.2.0", "react-native-ios-utilities": "5.2.0",
"react-native-mmkv": "4.1.1", "react-native-mmkv": "4.1.1",
"react-native-nitro-modules": "0.33.9", "react-native-nitro-modules": "0.33.1",
"react-native-pager-view": "8.0.1", "react-native-pager-view": "8.0.1",
"react-native-qrcode-svg": "^6.3.21", "react-native-qrcode-svg": "^6.3.21",
"react-native-reanimated": "4.3.1", "react-native-reanimated": "4.3.1",
@@ -83,6 +84,7 @@
"react-native-safe-area-context": "~5.7.0", "react-native-safe-area-context": "~5.7.0",
"react-native-screens": "4.25.2", "react-native-screens": "4.25.2",
"react-native-svg": "15.15.4", "react-native-svg": "15.15.4",
"react-native-tab-view": "4.3.0",
"react-native-text-ticker": "^1.15.0", "react-native-text-ticker": "^1.15.0",
"react-native-track-player": "github:lovegaoshi/react-native-track-player#APM", "react-native-track-player": "github:lovegaoshi/react-native-track-player#APM",
"react-native-udp": "^4.1.7", "react-native-udp": "^4.1.7",
@@ -114,11 +116,6 @@
}, },
}, },
}, },
"patchedDependencies": {
"react-native-ios-utilities@5.2.0": "bun-patches/react-native-ios-utilities@5.2.0.patch",
"react-native-udp@4.1.7": "bun-patches/react-native-udp@4.1.7.patch",
"react-native-bottom-tabs@1.2.0": "bun-patches/react-native-bottom-tabs@1.2.0.patch",
},
"packages": { "packages": {
"@adobe/css-tools": ["@adobe/css-tools@4.5.0", "", {}, "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q=="], "@adobe/css-tools": ["@adobe/css-tools@4.5.0", "", {}, "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q=="],
@@ -368,7 +365,7 @@
"@expo/xcpretty": ["@expo/xcpretty@4.4.4", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "chalk": "^4.1.0", "js-yaml": "^4.1.0" }, "bin": { "excpretty": "build/cli.js" } }, "sha512-4aQzz9vgxcNXFfo/iyNgDDYfsU5XGKKxWxZopw0cVotHiW+U8IJbIxMaxsINs6bHhtkG3StKNPcOrn3eBuxKPw=="], "@expo/xcpretty": ["@expo/xcpretty@4.4.4", "", { "dependencies": { "@babel/code-frame": "^7.20.0", "chalk": "^4.1.0", "js-yaml": "^4.1.0" }, "bin": { "excpretty": "build/cli.js" } }, "sha512-4aQzz9vgxcNXFfo/iyNgDDYfsU5XGKKxWxZopw0cVotHiW+U8IJbIxMaxsINs6bHhtkG3StKNPcOrn3eBuxKPw=="],
"@gorhom/bottom-sheet": ["@gorhom/bottom-sheet@5.2.8", "", { "dependencies": { "@gorhom/portal": "1.0.14", "invariant": "^2.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-native": "*", "react": "*", "react-native": "*", "react-native-gesture-handler": ">=2.16.1", "react-native-reanimated": ">=3.16.0 || >=4.0.0-" }, "optionalPeers": ["@types/react", "@types/react-native"] }, "sha512-+N27SMpbBxXZQ/IA2nlEV6RGxL/qSFHKfdFKcygvW+HqPG5jVNb1OqehLQsGfBP+Up42i0gW5ppI+DhpB7UCzA=="], "@gorhom/bottom-sheet": ["@gorhom/bottom-sheet@5.2.14", "", { "dependencies": { "@gorhom/portal": "1.0.14", "invariant": "^2.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-native": "*", "react": "*", "react-native": "*", "react-native-gesture-handler": ">=2.16.1", "react-native-reanimated": ">=3.16.0 || >=4.0.0-" }, "optionalPeers": ["@types/react", "@types/react-native"] }, "sha512-uLQFlDjp9z+jrOFcMSEldPqL5JdaXL3vXOh+juhwoNvXgTsEorJLjHTugXu+YccAG/0KJnShzKCrb71MHBsvJg=="],
"@gorhom/portal": ["@gorhom/portal@1.0.14", "", { "dependencies": { "nanoid": "^3.3.1" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-MXyL4xvCjmgaORr/rtryDNFy3kU4qUbKlwtQqqsygd0xX3mhKjOLn6mQK8wfu0RkoE0pBE0nAasRoHua+/QZ7A=="], "@gorhom/portal": ["@gorhom/portal@1.0.14", "", { "dependencies": { "nanoid": "^3.3.1" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-MXyL4xvCjmgaORr/rtryDNFy3kU4qUbKlwtQqqsygd0xX3mhKjOLn6mQK8wfu0RkoE0pBE0nAasRoHua+/QZ7A=="],
@@ -542,6 +539,10 @@
"@react-navigation/core": ["@react-navigation/core@7.17.5", "", { "dependencies": { "@react-navigation/routers": "^7.5.5", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "query-string": "^7.1.3", "react-is": "^19.1.0", "use-latest-callback": "^0.2.4", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "react": ">= 18.2.0" } }, "sha512-6fDCwDTWC7DJn0SDb9DJGRlipaygHIc+2elpZBJI6Crl/2Pu+Z1d6W4jMJ2gZO6iHKf+Pe5sUiQ/uwepGprZtg=="], "@react-navigation/core": ["@react-navigation/core@7.17.5", "", { "dependencies": { "@react-navigation/routers": "^7.5.5", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "query-string": "^7.1.3", "react-is": "^19.1.0", "use-latest-callback": "^0.2.4", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "react": ">= 18.2.0" } }, "sha512-6fDCwDTWC7DJn0SDb9DJGRlipaygHIc+2elpZBJI6Crl/2Pu+Z1d6W4jMJ2gZO6iHKf+Pe5sUiQ/uwepGprZtg=="],
"@react-navigation/elements": ["@react-navigation/elements@2.9.19", "", { "dependencies": { "color": "^4.2.3", "use-latest-callback": "^0.2.4", "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "@react-native-masked-view/masked-view": ">= 0.2.0", "@react-navigation/native": "^7.2.5", "react": ">= 18.2.0", "react-native": "*", "react-native-safe-area-context": ">= 4.0.0" }, "optionalPeers": ["@react-native-masked-view/masked-view"] }, "sha512-gBUvCZuUkOGw1KpLQEZIkByUz8RYPwXeoA6mZFJy9K1mxd8GdqHDMFCIoB0lfPz9rgrHj99RvtdlGZ/ZzkZv2A=="],
"@react-navigation/material-top-tabs": ["@react-navigation/material-top-tabs@7.4.28", "", { "dependencies": { "@react-navigation/elements": "^2.9.19", "color": "^4.2.3", "react-native-tab-view": "^4.3.0" }, "peerDependencies": { "@react-navigation/native": "^7.2.5", "react": ">= 18.2.0", "react-native": "*", "react-native-pager-view": ">= 6.0.0", "react-native-safe-area-context": ">= 4.0.0" } }, "sha512-WZHJSGV2PQOD2Vr9LF8apGvcsbDKukzF3Fhh8xVNIesqaSi9TPProv4dRw6YkenUkjvFVZYkOjvwAJOToePVpA=="],
"@react-navigation/native": ["@react-navigation/native@7.2.5", "", { "dependencies": { "@react-navigation/core": "^7.17.5", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*" } }, "sha512-01AAUQiiHQAfTabq+ZyU1/ZWq+AbB/J3v0CB0UTJSON6M6cuadWNsbChzrZUdqQvHrXvg96U5i2PQLJzK3+zpg=="], "@react-navigation/native": ["@react-navigation/native@7.2.5", "", { "dependencies": { "@react-navigation/core": "^7.17.5", "escape-string-regexp": "^4.0.0", "fast-deep-equal": "^3.1.3", "nanoid": "^3.3.11", "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*" } }, "sha512-01AAUQiiHQAfTabq+ZyU1/ZWq+AbB/J3v0CB0UTJSON6M6cuadWNsbChzrZUdqQvHrXvg96U5i2PQLJzK3+zpg=="],
"@react-navigation/routers": ["@react-navigation/routers@7.5.5", "", { "dependencies": { "nanoid": "^3.3.11" } }, "sha512-9/hhMte12Kgu+pMnLfA4EWJ0OQmIEAMVMX06FPH2yGkEQSQ3JhhCN/GkcRikzQhtEi97VYYQA15umptBUShcOQ=="], "@react-navigation/routers": ["@react-navigation/routers@7.5.5", "", { "dependencies": { "nanoid": "^3.3.11" } }, "sha512-9/hhMte12Kgu+pMnLfA4EWJ0OQmIEAMVMX06FPH2yGkEQSQ3JhhCN/GkcRikzQhtEi97VYYQA15umptBUShcOQ=="],
@@ -1578,7 +1579,7 @@
"react-native-mmkv": ["react-native-mmkv@4.1.1", "", { "peerDependencies": { "react": "*", "react-native": "*", "react-native-nitro-modules": "*" } }, "sha512-nYFjM27l7zVhIiyAqWEFRagGASecb13JMIlzAuOeakRRz9GMJ49hCQntUBE2aeuZRE4u4ehSqTOomB0mTF56Ew=="], "react-native-mmkv": ["react-native-mmkv@4.1.1", "", { "peerDependencies": { "react": "*", "react-native": "*", "react-native-nitro-modules": "*" } }, "sha512-nYFjM27l7zVhIiyAqWEFRagGASecb13JMIlzAuOeakRRz9GMJ49hCQntUBE2aeuZRE4u4ehSqTOomB0mTF56Ew=="],
"react-native-nitro-modules": ["react-native-nitro-modules@0.33.9", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-BM9C5mCGYYjrc8CDWZZ0anLWU/knH2xaEuFzvzogKTOW6fzgS6mmsCdM3ty+AhImJNSYwK19DLrHaqwnrrwEzw=="], "react-native-nitro-modules": ["react-native-nitro-modules@0.33.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-Kdo8qiqlkGAEs7fq29i0yiZs0Gf7ucmMiFsH8PH4uzsnSGEt2CQRBJGnQKKMl9vJYL8e7rzA0TZKRwO/L8G/Sg=="],
"react-native-pager-view": ["react-native-pager-view@8.0.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-pGOne2o0y0HOQLrlTLcGgOE48uJlqSZHRRwdW8nL6JJozMkPGJYi/G9e0EsJoWFpXYONjiDgr8IwxC4F6/r7Lg=="], "react-native-pager-view": ["react-native-pager-view@8.0.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-pGOne2o0y0HOQLrlTLcGgOE48uJlqSZHRRwdW8nL6JJozMkPGJYi/G9e0EsJoWFpXYONjiDgr8IwxC4F6/r7Lg=="],
@@ -1594,9 +1595,11 @@
"react-native-svg": ["react-native-svg@15.15.4", "", { "dependencies": { "css-select": "^5.1.0", "css-tree": "^1.1.3", "warn-once": "0.1.1" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-boT/vIRgj6zZKBpfTPJJiYWMbZE9duBMOwPK6kCSTgxsS947IFMOq9OgIFkpWZTB7t229H24pDRkh3W9ZK/J1A=="], "react-native-svg": ["react-native-svg@15.15.4", "", { "dependencies": { "css-select": "^5.1.0", "css-tree": "^1.1.3", "warn-once": "0.1.1" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-boT/vIRgj6zZKBpfTPJJiYWMbZE9duBMOwPK6kCSTgxsS947IFMOq9OgIFkpWZTB7t229H24pDRkh3W9ZK/J1A=="],
"react-native-tab-view": ["react-native-tab-view@4.3.0", "", { "dependencies": { "use-latest-callback": "^0.2.4" }, "peerDependencies": { "react": ">= 18.2.0", "react-native": "*", "react-native-pager-view": ">= 6.0.0" } }, "sha512-qPMF75uz/7+MuVG2g+YETdGMzlWZnhC6iI4h/7EBbwIBwNBIBi2z4OA6KhY3IOOBwGHXEIz5IyA6doDqifYBHg=="],
"react-native-text-ticker": ["react-native-text-ticker@1.15.0", "", {}, "sha512-d/uK+PIOhsYMy1r8h825iq/nADiHsabz3WMbRJSnkpQYn+K9aykUAXRRhu8ZbTAzk4CgnUWajJEFxS5ZDygsdg=="], "react-native-text-ticker": ["react-native-text-ticker@1.15.0", "", {}, "sha512-d/uK+PIOhsYMy1r8h825iq/nADiHsabz3WMbRJSnkpQYn+K9aykUAXRRhu8ZbTAzk4CgnUWajJEFxS5ZDygsdg=="],
"react-native-track-player": ["react-native-track-player@github:lovegaoshi/react-native-track-player#33a3ecd", { "peerDependencies": { "react": "*", "react-native": "*", "react-native-windows": "*", "shaka-player": "^4.7.9" }, "optionalPeers": ["react-native-windows", "shaka-player"] }, "lovegaoshi-react-native-track-player-33a3ecd", "sha512-vfkld2jUj7EPkAjIc/Vbx4Q4MtOOLmYtCYCE2dWJsyLnPqgj1f0xVzBxbeVP7dfT+eSh4KIXfdxESXaHgrXIlw=="], "react-native-track-player": ["react-native-track-player@github:lovegaoshi/react-native-track-player#33a3ecd", { "peerDependencies": { "react": "*", "react-native": "*", "react-native-windows": "*", "shaka-player": "^4.7.9" }, "optionalPeers": ["react-native-windows", "shaka-player"] }, "lovegaoshi-react-native-track-player-33a3ecd"],
"react-native-udp": ["react-native-udp@4.1.7", "", { "dependencies": { "buffer": "^5.6.0", "events": "^3.1.0" } }, "sha512-NUE3zewu61NCdSsLlj+l0ad6qojcVEZPT4hVG/x6DU9U4iCzwtfZSASh9vm7teAcVzLkdD+cO3411LHshAi/wA=="], "react-native-udp": ["react-native-udp@4.1.7", "", { "dependencies": { "buffer": "^5.6.0", "events": "^3.1.0" } }, "sha512-NUE3zewu61NCdSsLlj+l0ad6qojcVEZPT4hVG/x6DU9U4iCzwtfZSASh9vm7teAcVzLkdD+cO3411LHshAi/wA=="],
@@ -2006,6 +2009,10 @@
"@react-native/metro-babel-transformer/@babel/core": ["@babel/core@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/template": "^7.28.6", "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw=="], "@react-native/metro-babel-transformer/@babel/core": ["@babel/core@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/template": "^7.28.6", "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw=="],
"@react-navigation/elements/color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="],
"@react-navigation/material-top-tabs/color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="],
"@testing-library/dom/aria-query": ["aria-query@5.3.0", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A=="], "@testing-library/dom/aria-query": ["aria-query@5.3.0", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A=="],
"@testing-library/dom/dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="], "@testing-library/dom/dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="],
@@ -2224,6 +2231,14 @@
"@react-native-community/cli-server-api/open/is-wsl": ["is-wsl@1.1.0", "", {}, "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw=="], "@react-native-community/cli-server-api/open/is-wsl": ["is-wsl@1.1.0", "", {}, "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw=="],
"@react-navigation/elements/color/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
"@react-navigation/elements/color/color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
"@react-navigation/material-top-tabs/color/color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
"@react-navigation/material-top-tabs/color/color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="],
"@testing-library/dom/pretty-format/react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="], "@testing-library/dom/pretty-format/react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="],
"ansi-fragments/slice-ansi/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="], "ansi-fragments/slice-ansi/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
@@ -2336,6 +2351,14 @@
"@expo/package-manager/ora/strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="], "@expo/package-manager/ora/strip-ansi/ansi-regex": ["ansi-regex@4.1.1", "", {}, "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g=="],
"@react-navigation/elements/color/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
"@react-navigation/elements/color/color-string/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
"@react-navigation/material-top-tabs/color/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
"@react-navigation/material-top-tabs/color/color-string/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
"ansi-fragments/slice-ansi/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="], "ansi-fragments/slice-ansi/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
"chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], "chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],

View File

@@ -1,203 +0,0 @@
/**
* Example Usage of Global Modal
*
* This file demonstrates how to use the global modal system from anywhere in your app.
* You can delete this file after understanding how it works.
*/
import { Ionicons } from "@expo/vector-icons";
import { TouchableOpacity, View } from "react-native";
import { Text } from "@/components/common/Text";
import { useGlobalModal } from "@/providers/GlobalModalProvider";
/**
* Example 1: Simple Content Modal
*/
export const SimpleModalExample = () => {
const { showModal } = useGlobalModal();
const handleOpenModal = () => {
showModal(
<View className='p-6'>
<Text className='text-2xl font-bold mb-4 text-white'>Simple Modal</Text>
<Text className='text-white mb-4'>
This is a simple modal with just some text content.
</Text>
<Text className='text-neutral-400'>
Swipe down or tap outside to close.
</Text>
</View>,
);
};
return (
<TouchableOpacity
onPress={handleOpenModal}
className='bg-purple-600 px-4 py-2 rounded-lg'
>
<Text className='text-white font-semibold'>Open Simple Modal</Text>
</TouchableOpacity>
);
};
/**
* Example 2: Modal with Custom Snap Points
*/
export const CustomSnapPointsExample = () => {
const { showModal } = useGlobalModal();
const handleOpenModal = () => {
showModal(
<View className='p-6' style={{ minHeight: 400 }}>
<Text className='text-2xl font-bold mb-4 text-white'>
Custom Snap Points
</Text>
<Text className='text-white mb-4'>
This modal has custom snap points (25%, 50%, 90%).
</Text>
<View className='bg-neutral-800 p-4 rounded-lg'>
<Text className='text-white'>
Try dragging the modal to different heights!
</Text>
</View>
</View>,
{
snapPoints: ["25%", "50%", "90%"],
enableDynamicSizing: false,
},
);
};
return (
<TouchableOpacity
onPress={handleOpenModal}
className='bg-blue-600 px-4 py-2 rounded-lg'
>
<Text className='text-white font-semibold'>Custom Snap Points</Text>
</TouchableOpacity>
);
};
/**
* Example 3: Complex Component in Modal
*/
const SettingsModalContent = () => {
const { hideModal } = useGlobalModal();
const settings = [
{
id: 1,
title: "Notifications",
icon: "notifications-outline" as const,
enabled: true,
},
{ id: 2, title: "Dark Mode", icon: "moon-outline" as const, enabled: true },
{
id: 3,
title: "Auto-play",
icon: "play-outline" as const,
enabled: false,
},
];
return (
<View className='p-6'>
<Text className='text-2xl font-bold mb-6 text-white'>Settings</Text>
{settings.map((setting, index) => (
<View
key={setting.id}
className={`flex-row items-center justify-between py-4 ${
index !== settings.length - 1 ? "border-b border-neutral-700" : ""
}`}
>
<View className='flex-row items-center gap-3'>
<Ionicons name={setting.icon} size={24} color='white' />
<Text className='text-white text-lg'>{setting.title}</Text>
</View>
<View
className={`w-12 h-7 rounded-full ${
setting.enabled ? "bg-purple-600" : "bg-neutral-600"
}`}
>
<View
className={`w-5 h-5 rounded-full bg-white shadow-md transform ${
setting.enabled ? "translate-x-6" : "translate-x-1"
}`}
style={{ marginTop: 4 }}
/>
</View>
</View>
))}
<TouchableOpacity
onPress={hideModal}
className='bg-purple-600 px-4 py-3 rounded-lg mt-6'
>
<Text className='text-white font-semibold text-center'>Close</Text>
</TouchableOpacity>
</View>
);
};
export const ComplexModalExample = () => {
const { showModal } = useGlobalModal();
const handleOpenModal = () => {
showModal(<SettingsModalContent />);
};
return (
<TouchableOpacity
onPress={handleOpenModal}
className='bg-green-600 px-4 py-2 rounded-lg'
>
<Text className='text-white font-semibold'>Complex Component</Text>
</TouchableOpacity>
);
};
/**
* Example 4: Modal Triggered from Function (e.g., API response)
*/
export const useShowSuccessModal = () => {
const { showModal } = useGlobalModal();
return (message: string) => {
showModal(
<View className='p-6 items-center'>
<View className='bg-green-500 rounded-full p-4 mb-4'>
<Ionicons name='checkmark' size={48} color='white' />
</View>
<Text className='text-2xl font-bold mb-2 text-white'>Success!</Text>
<Text className='text-white text-center'>{message}</Text>
</View>,
);
};
};
/**
* Main Demo Component
*/
export const GlobalModalDemo = () => {
const showSuccess = useShowSuccessModal();
return (
<View className='p-6 gap-4'>
<Text className='text-2xl font-bold mb-4 text-white'>
Global Modal Examples
</Text>
<SimpleModalExample />
<CustomSnapPointsExample />
<ComplexModalExample />
<TouchableOpacity
onPress={() => showSuccess("Operation completed successfully!")}
className='bg-orange-600 px-4 py-2 rounded-lg'
>
<Text className='text-white font-semibold'>Show Success Modal</Text>
</TouchableOpacity>
</View>
);
};

View File

@@ -74,6 +74,9 @@ function ChapterListComponent({
transparent transparent
animationType='slide' animationType='slide'
onRequestClose={onClose} onRequestClose={onClose}
// iOS defaults <Modal> to portrait-only; without this it rotates the app
// back to portrait when opened from the landscape player. Android ignores it.
supportedOrientations={["portrait", "landscape"]}
> >
<Pressable onPress={onClose} style={styles.backdrop}> <Pressable onPress={onClose} style={styles.backdrop}>
<Pressable onPress={(e) => e.stopPropagation()} style={styles.sheet}> <Pressable onPress={(e) => e.stopPropagation()} style={styles.sheet}>

View File

@@ -1,20 +0,0 @@
import { Image } from "expo-image";
import { View } from "react-native";
export const LargePoster: React.FC<{ url?: string | null }> = ({ url }) => {
if (!url)
return (
<View className='p-4 rounded-xl overflow-hidden '>
<View className='w-full aspect-video rounded-xl overflow-hidden border border-neutral-800' />
</View>
);
return (
<View className='p-4 rounded-xl overflow-hidden '>
<Image
source={{ uri: url }}
className='w-full aspect-video rounded-xl overflow-hidden border border-neutral-800'
/>
</View>
);
};

View File

@@ -37,11 +37,12 @@ export const ProgressBar: React.FC<ProgressBarProps> = ({ item }) => {
} }
/> />
<View <View
style={{ style={
width: `${progress}%`, Platform.isTV
backgroundColor: Platform.isTV ? "#ffffff" : undefined, ? { width: `${progress}%`, backgroundColor: "#ffffff" }
}} : { width: `${progress}%` }
className={`absolute bottom-0 left-0 h-1 w-full ${Platform.isTV ? "" : "bg-purple-600"}`} }
className={`absolute bottom-0 left-0 h-1 ${Platform.isTV ? "" : "bg-purple-600"}`}
/> />
</> </>
); );

View File

@@ -2,6 +2,7 @@ import { useActionSheet } from "@expo/react-native-action-sheet";
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models"; import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { useSegments } from "expo-router"; import { useSegments } from "expo-router";
import { type PropsWithChildren, useCallback } from "react"; import { type PropsWithChildren, useCallback } from "react";
import { useTranslation } from "react-i18next";
import { import {
Platform, Platform,
TouchableOpacity, TouchableOpacity,
@@ -149,6 +150,7 @@ export const TouchableItemRouter: React.FC<PropsWithChildren<Props>> = ({
children, children,
...props ...props
}) => { }) => {
const { t } = useTranslation();
const segments = useSegments(); const segments = useSegments();
const { showActionSheetWithOptions } = useActionSheet(); const { showActionSheetWithOptions } = useActionSheet();
const markAsPlayedStatus = useMarkAsPlayed([item]); const markAsPlayedStatus = useMarkAsPlayed([item]);
@@ -182,11 +184,13 @@ export const TouchableItemRouter: React.FC<PropsWithChildren<Props>> = ({
return; return;
const options: string[] = [ const options: string[] = [
"Mark as Played", t("common.mark_as_played"),
"Mark as Not Played", t("common.mark_as_not_played"),
isFavorite ? "Unmark as Favorite" : "Mark as Favorite", isFavorite
...(isOffline ? ["Delete Download"] : []), ? t("music.track_options.remove_from_favorites")
"Cancel", : t("music.track_options.add_to_favorites"),
...(isOffline ? [t("home.downloads.delete_download")] : []),
t("common.cancel"),
]; ];
const cancelButtonIndex = options.length - 1; const cancelButtonIndex = options.length - 1;
const destructiveButtonIndex = isOffline const destructiveButtonIndex = isOffline
@@ -219,6 +223,7 @@ export const TouchableItemRouter: React.FC<PropsWithChildren<Props>> = ({
isOffline, isOffline,
deleteFile, deleteFile,
item.Id, item.Id,
t,
]); ]);
if ( if (

View File

@@ -1,28 +0,0 @@
import { View, type ViewProps } from "react-native";
interface Props extends ViewProps {
index: number;
}
export const VerticalSkeleton: React.FC<Props> = ({ index, ...props }) => {
return (
<View
key={index}
style={{
width: "32%",
}}
className='flex flex-col'
{...props}
>
<View
style={{
aspectRatio: "10/15",
}}
className='w-full bg-neutral-800 mb-2 rounded-lg'
/>
<View className='h-2 bg-neutral-800 rounded-full mb-1' />
<View className='h-2 bg-neutral-800 rounded-full mb-1' />
<View className='h-2 bg-neutral-800 rounded-full mb-2 w-1/2' />
</View>
);
};

View File

@@ -37,7 +37,20 @@ export const ItemPeopleSections: React.FC<Props> = ({ item, ...props }) => {
return { ...item, People: people } as BaseItemDto; return { ...item, People: people } as BaseItemDto;
}, [item, people]); }, [item, people]);
const topPeople = useMemo(() => people.slice(0, 3), [people]); // Jellyfin can list the same person several times (e.g. an actor also
// credited as writer). Dedupe by Id so the same actor section isn't rendered
// twice and we still surface 3 distinct people.
const topPeople = useMemo(() => {
const seen = new Set<string>();
const unique: BaseItemPerson[] = [];
for (const person of people) {
if (!person.Id || seen.has(person.Id)) continue;
seen.add(person.Id);
unique.push(person);
if (unique.length >= 3) break;
}
return unique;
}, [people]);
const renderActorSection = useCallback( const renderActorSection = useCallback(
(person: BaseItemPerson, idx: number, total: number) => { (person: BaseItemPerson, idx: number, total: number) => {

View File

@@ -1,12 +0,0 @@
// You can explore the built-in icon families and icons on the web at https://icons.expo.fyi/
import type { IconProps } from "@expo/vector-icons/build/createIconSet";
import Ionicons from "@expo/vector-icons/Ionicons";
import type { ComponentProps } from "react";
export function TabBarIcon({
style,
...rest
}: IconProps<ComponentProps<typeof Ionicons>["name"]>) {
return <Ionicons size={26} style={[{ marginBottom: -3 }, style]} {...rest} />;
}

View File

@@ -1,63 +0,0 @@
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { Image } from "expo-image";
import { useAtom } from "jotai";
import { useMemo, useState } from "react";
import { View } from "react-native";
import { WatchedIndicator } from "@/components/WatchedIndicator";
import { apiAtom } from "@/providers/JellyfinProvider";
type MoviePosterProps = {
item: BaseItemDto;
showProgress?: boolean;
};
export const EpisodePoster: React.FC<MoviePosterProps> = ({
item,
showProgress = false,
}) => {
const [api] = useAtom(apiAtom);
const url = useMemo(() => {
if (item.Type === "Episode") {
return `${api?.basePath}/Items/${item.ParentBackdropItemId}/Images/Thumb?fillHeight=389&quality=80&tag=${item.ParentThumbImageTag}`;
}
}, [item]);
const [progress, _setProgress] = useState(
item.UserData?.PlayedPercentage || 0,
);
const blurhash = useMemo(() => {
const key = item.ImageTags?.Primary as string;
return item.ImageBlurHashes?.Primary?.[key];
}, [item]);
return (
<View className='relative rounded-lg overflow-hidden border border-neutral-900'>
<Image
placeholder={{
blurhash,
}}
key={item.Id}
id={item.Id}
source={
url
? {
uri: url,
}
: null
}
cachePolicy={"memory-disk"}
contentFit='cover'
style={{
aspectRatio: "10/15",
width: "100%",
}}
/>
<WatchedIndicator item={item} />
{showProgress && progress > 0 && (
<View className='h-1 bg-red-600 w-full' />
)}
</View>
);
};

View File

@@ -1,48 +0,0 @@
import { Image } from "expo-image";
import { useAtom } from "jotai";
import { useMemo } from "react";
import { View } from "react-native";
import { apiAtom } from "@/providers/JellyfinProvider";
type PosterProps = {
id?: string;
showProgress?: boolean;
};
const ParentPoster: React.FC<PosterProps> = ({ id }) => {
const [api] = useAtom(apiAtom);
const url = useMemo(
() => `${api?.basePath}/Items/${id}/Images/Primary`,
[id],
);
if (!url || !id)
return (
<View
className='border border-neutral-900'
style={{
aspectRatio: "10/15",
}}
/>
);
return (
<View className='rounded-lg overflow-hidden border border-neutral-900'>
<Image
key={id}
id={id}
source={{
uri: url,
}}
cachePolicy={"memory-disk"}
contentFit='cover'
style={{
aspectRatio: "10/15",
}}
/>
</View>
);
};
export default ParentPoster;

View File

@@ -1,29 +0,0 @@
import { useTranslation } from "react-i18next";
import { View } from "react-native";
import useRouter from "@/hooks/useAppRouter";
import { useSessions, type useSessionsProps } from "@/hooks/useSessions";
import { useSettings } from "@/utils/atoms/settings";
import { ListGroup } from "../list/ListGroup";
import { ListItem } from "../list/ListItem";
export const Dashboard = () => {
const { settings } = useSettings();
const { sessions = [] } = useSessions({} as useSessionsProps);
const router = useRouter();
const { t } = useTranslation();
if (!settings) return null;
return (
<View>
<ListGroup title={t("home.settings.dashboard.title")} className='mt-4'>
<ListItem
className={sessions.length !== 0 ? "bg-purple-900" : ""}
onPress={() => router.push("/settings/dashboard/sessions")}
title={t("home.settings.dashboard.sessions_title")}
showArrow
/>
</ListGroup>
</View>
);
};

View File

@@ -1,3 +0,0 @@
export default function DownloadSettings() {
return null;
}

View File

@@ -1,3 +0,0 @@
export default function DownloadSettings() {
return null;
}

View File

@@ -229,7 +229,7 @@ export const LibraryOptionsSheet: React.FC<Props> = ({
/> />
</OptionGroup> </OptionGroup>
<OptionGroup title='Options'> <OptionGroup title={t("library.options.options_title")}>
<ToggleItem <ToggleItem
label={t("library.options.show_titles")} label={t("library.options.show_titles")}
value={settings.showTitles} value={settings.showTitles}

View File

@@ -105,14 +105,14 @@ const AudioSlider: React.FC<AudioSliderProps> = ({ setVisibility }) => {
maximumValue={max} maximumValue={max}
thumbWidth={0} thumbWidth={0}
onValueChange={handleValueChange} onValueChange={handleValueChange}
renderBubble={() => null}
renderThumb={() => null}
containerStyle={{ containerStyle={{
borderRadius: 50, borderRadius: 50,
}} }}
theme={{ theme={{
minimumTrackTintColor: "#FDFDFD", minimumTrackTintColor: "#FDFDFD",
maximumTrackTintColor: "#5A5A5A", maximumTrackTintColor: "#5A5A5A",
bubbleBackgroundColor: "transparent", // Hide the value bubble
bubbleTextColor: "transparent", // Hide the value text
}} }}
/> />
<Ionicons <Ionicons

View File

@@ -88,14 +88,14 @@ const BrightnessSlider = () => {
maximumValue={max} maximumValue={max}
thumbWidth={0} thumbWidth={0}
onValueChange={handleValueChange} onValueChange={handleValueChange}
renderBubble={() => null}
renderThumb={() => null}
containerStyle={{ containerStyle={{
borderRadius: 50, borderRadius: 50,
}} }}
theme={{ theme={{
minimumTrackTintColor: "#FDFDFD", minimumTrackTintColor: "#FDFDFD",
maximumTrackTintColor: "#5A5A5A", maximumTrackTintColor: "#5A5A5A",
bubbleBackgroundColor: "transparent", // Hide the value bubble
bubbleTextColor: "transparent", // Hide the value text
}} }}
/> />
<Ionicons <Ionicons

View File

@@ -1,4 +1,5 @@
import type { FC } from "react"; import type { FC } from "react";
import { useTranslation } from "react-i18next";
import { View } from "react-native"; import { View } from "react-native";
import { Text } from "@/components/common/Text"; import { Text } from "@/components/common/Text";
import { formatTimeString } from "@/utils/time"; import { formatTimeString } from "@/utils/time";
@@ -16,6 +17,8 @@ export const TimeDisplay: FC<TimeDisplayProps> = ({
currentTime, currentTime,
remainingTime, remainingTime,
}) => { }) => {
const { t } = useTranslation();
const getFinishTime = () => { const getFinishTime = () => {
const now = new Date(); const now = new Date();
// remainingTime is in ms // remainingTime is in ms
@@ -37,7 +40,7 @@ export const TimeDisplay: FC<TimeDisplayProps> = ({
-{formatTimeString(remainingTime, "ms")} -{formatTimeString(remainingTime, "ms")}
</Text> </Text>
<Text className='text-[10px] text-neutral-500 opacity-70'> <Text className='text-[10px] text-neutral-500 opacity-70'>
ends at {getFinishTime()} {t("player.ends_at", { time: getFinishTime() })}
</Text> </Text>
</View> </View>
</View> </View>

View File

@@ -1,39 +0,0 @@
import type { DefaultLanguageOption } from "@/utils/atoms/settings";
export const LANGUAGES: DefaultLanguageOption[] = [
{ label: "English", value: "eng" },
{ label: "Spanish", value: "spa" },
{ label: "Chinese (Mandarin)", value: "cmn" },
{ label: "Hindi", value: "hin" },
{ label: "Arabic", value: "ara" },
{ label: "French", value: "fra" },
{ label: "Russian", value: "rus" },
{ label: "Portuguese", value: "por" },
{ label: "Japanese", value: "jpn" },
{ label: "German", value: "deu" },
{ label: "Italian", value: "ita" },
{ label: "Korean", value: "kor" },
{ label: "Turkish", value: "tur" },
{ label: "Dutch", value: "nld" },
{ label: "Polish", value: "pol" },
{ label: "Vietnamese", value: "vie" },
{ label: "Thai", value: "tha" },
{ label: "Indonesian", value: "ind" },
{ label: "Greek", value: "ell" },
{ label: "Swedish", value: "swe" },
{ label: "Danish", value: "dan" },
{ label: "Norwegian", value: "nor" },
{ label: "Finnish", value: "fin" },
{ label: "Czech", value: "ces" },
{ label: "Hungarian", value: "hun" },
{ label: "Romanian", value: "ron" },
{ label: "Ukrainian", value: "ukr" },
{ label: "Hebrew", value: "heb" },
{ label: "Bengali", value: "ben" },
{ label: "Punjabi", value: "pan" },
{ label: "Tagalog", value: "tgl" },
{ label: "Swahili", value: "swa" },
{ label: "Malay", value: "msa" },
{ label: "Persian", value: "fas" },
{ label: "Urdu", value: "urd" },
];

View File

@@ -1,6 +1,7 @@
{ {
"cli": { "cli": {
"version": ">= 9.1.0" "version": ">= 16.0.0",
"appVersionSource": "remote"
}, },
"build": { "build": {
"development": { "development": {
@@ -51,44 +52,70 @@
} }
}, },
"production": { "production": {
"bun": "1.3.5",
"environment": "production", "environment": "production",
"channel": "0.54.0", "autoIncrement": true,
"android": { "android": {
"image": "latest" "image": "latest",
"config": "android-production.yml"
},
"ios": {
"config": "ios-production.yml"
} }
}, },
"production-apk": { "production-apk": {
"bun": "1.3.5",
"environment": "production", "environment": "production",
"channel": "0.54.0", "autoIncrement": true,
"android": { "android": {
"buildType": "apk", "buildType": "apk",
"image": "latest" "image": "latest",
"config": "android-production-apk.yml"
} }
}, },
"production-apk-tv": { "production-apk-tv": {
"bun": "1.3.5",
"environment": "production", "environment": "production",
"channel": "0.54.0", "autoIncrement": true,
"android": { "android": {
"buildType": "apk", "buildType": "apk",
"image": "latest" "image": "latest",
"config": "android-production-tv.yml"
}, },
"env": { "env": {
"EXPO_TV": "1" "EXPO_TV": "1"
} }
}, },
"production_tv": { "production_tv": {
"bun": "1.3.5",
"environment": "production", "environment": "production",
"channel": "0.54.0", "autoIncrement": true,
"env": { "env": {
"EXPO_TV": "1" "EXPO_TV": "1"
}, },
"ios": { "ios": {
"credentialsSource": "local" "credentialsSource": "local",
"config": "ios-production.yml"
} }
} }
}, },
"submit": { "submit": {
"production": {}, "production": {
"production_tv": {} "ios": {
"appleTeamId": "MWD5K362T8",
"ascAppId": "6593660679"
},
"android": {
"serviceAccountKeyPath": "./google-service-account.json",
"track": "internal",
"releaseStatus": "completed"
}
},
"production_tv": {
"ios": {
"appleTeamId": "MWD5K362T8",
"ascAppId": "6593660679"
}
}
} }
} }

View File

@@ -1,37 +0,0 @@
import { useCallback, useEffect, useRef } from "react";
import { useSharedValue } from "react-native-reanimated";
export const useControlsVisibility = (timeout = 3000) => {
const opacity = useSharedValue(1);
const hideControlsTimerRef = useRef<ReturnType<typeof setTimeout> | null>(
null,
);
const showControls = useCallback(() => {
opacity.value = 1;
if (hideControlsTimerRef.current) {
clearTimeout(hideControlsTimerRef.current);
}
hideControlsTimerRef.current = setTimeout(() => {
opacity.value = 0;
}, timeout);
}, [timeout]);
const hideControls = useCallback(() => {
opacity.value = 0;
if (hideControlsTimerRef.current) {
clearTimeout(hideControlsTimerRef.current);
}
}, []);
useEffect(() => {
return () => {
if (hideControlsTimerRef.current) {
clearTimeout(hideControlsTimerRef.current);
}
};
}, []);
return { opacity, showControls, hideControls };
};

View File

@@ -1,35 +0,0 @@
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client";
import { useCallback } from "react";
import useRouter from "@/hooks/useAppRouter";
import { usePlaySettings } from "@/providers/PlaySettingsProvider";
import { writeToLog } from "@/utils/log";
export const useDownloadedFileOpener = () => {
const router = useRouter();
const { setPlayUrl, setOfflineSettings } = usePlaySettings();
const openFile = useCallback(
async (item: BaseItemDto) => {
if (!item.Id) {
writeToLog("ERROR", "Attempted to open a file without an ID.");
console.error("Attempted to open a file without an ID.");
return;
}
const queryParams = new URLSearchParams({
itemId: item.Id,
offline: "true",
playbackPosition:
item.UserData?.PlaybackPositionTicks?.toString() ?? "0",
});
try {
router.push(`/player/direct-player?${queryParams.toString()}`);
} catch (error) {
writeToLog("ERROR", "Error opening file", error);
console.error("Error opening file:", error);
}
},
[setOfflineSettings, setPlayUrl, router],
);
return { openFile };
};

View File

@@ -1,120 +0,0 @@
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client";
import { useAtom, useAtomValue } from "jotai";
import { useEffect, useMemo } from "react";
import { Platform } from "react-native";
import type * as ImageColorsType from "react-native-image-colors";
import { apiAtom } from "@/providers/JellyfinProvider";
// Conditionally import react-native-image-colors only on non-TV platforms
const ImageColors = Platform.isTV
? null
: (require("react-native-image-colors") as typeof ImageColorsType);
import {
adjustToNearBlack,
calculateTextColor,
isCloseToBlack,
itemThemeColorAtom,
} from "@/utils/atoms/primaryColor";
import { getItemImage } from "@/utils/getItemImage";
import { storage } from "@/utils/mmkv";
/**
* Custom hook to extract and manage image colors for a given item.
*
* @param item - The BaseItemDto object representing the item.
* @param disabled - A boolean flag to disable color extraction.
*
*/
export const useImageColors = ({
item,
url,
disabled,
}: {
item?: BaseItemDto | null;
url?: string | null;
disabled?: boolean;
}) => {
const api = useAtomValue(apiAtom);
const [, setPrimaryColor] = useAtom(itemThemeColorAtom);
const isTv = Platform.isTV;
const source = useMemo(() => {
if (!api) return;
if (url) return { uri: url };
if (item)
return getItemImage({
item,
api,
variant: "Primary",
quality: 80,
width: 300,
});
return null;
}, [api, item, url]);
useEffect(() => {
if (isTv) return;
if (disabled) return;
if (source?.uri) {
const _primary = storage.getString(`${source.uri}-primary`);
const _text = storage.getString(`${source.uri}-text`);
if (_primary && _text) {
setPrimaryColor({
primary: _primary,
text: _text,
});
return;
}
// Extract colors from the image
if (!ImageColors?.getColors) return;
ImageColors.getColors(source.uri, {
fallback: "#fff",
cache: false,
})
.then((colors: ImageColorsType.ImageColorsResult) => {
let primary = "#fff";
let text = "#000";
let backup = "#fff";
// Select the appropriate color based on the platform
if (colors.platform === "android") {
primary = colors.dominant;
backup = colors.vibrant;
} else if (colors.platform === "ios") {
primary = colors.detail;
backup = colors.primary;
}
// Adjust the primary color if it's too close to black
if (primary && isCloseToBlack(primary)) {
if (backup && !isCloseToBlack(backup)) primary = backup;
primary = adjustToNearBlack(primary);
}
// Calculate the text color based on the primary color
if (primary) text = calculateTextColor(primary);
setPrimaryColor({
primary,
text,
});
// Cache the colors in storage
if (source.uri && primary) {
storage.set(`${source.uri}-primary`, primary);
storage.set(`${source.uri}-text`, text);
}
})
.catch((error: any) => {
console.error("Error getting colors", error);
});
}
}, [isTv, source?.uri, setPrimaryColor, disabled]);
if (isTv) return;
};

View File

@@ -1,46 +1,20 @@
plugins { apply plugin: 'expo-module-gradle-plugin'
id 'com.android.library'
id 'kotlin-android'
}
group = 'expo.modules.backgrounddownloader' group = 'expo.modules.backgrounddownloader'
version = '1.0.0' version = '1.0.0'
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle") expoModule {
def kotlinVersion = findProperty('android.kotlinVersion') ?: '1.9.25' canBePublished false
}
apply from: expoModulesCorePlugin
applyKotlinExpoModulesCorePlugin()
useDefaultAndroidSdkVersions()
useCoreDependencies()
useExpoPublishing()
android { android {
namespace "expo.modules.backgrounddownloader" namespace "expo.modules.backgrounddownloader"
defaultConfig {
compileOptions { versionCode 1
sourceCompatibility JavaVersion.VERSION_17 versionName "1.0.0"
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
lintOptions {
abortOnError false
} }
} }
dependencies { dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
implementation "com.squareup.okhttp3:okhttp:4.12.0" implementation "com.squareup.okhttp3:okhttp:4.12.0"
} }
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
kotlinOptions {
jvmTarget = "17"
}
}

View File

@@ -236,37 +236,43 @@ class MPVLayerRenderer(private val context: Context) : MPVLib.EventObserver {
} }
/** /**
* Attach surface and re-enable video output. * Attach surface and ensure video output is active.
* Based on Findroid's implementation. *
* During PiP transitions, the surface is destroyed and recreated by Android.
* We keep the VO pipeline alive (not killed with vo=null) so that rendering
* resumes immediately when the new surface is attached — avoiding the black
* screen that occurs when the VO is fully re-initialized via setOptionString.
*/ */
fun attachSurface(surface: Surface) { fun attachSurface(surface: Surface) {
this.surface = surface this.surface = surface
Log.i(TAG, "[PiP] attachSurface — isRunning=$isRunning, vo=$voDriver, surface=${surface.hashCode()}")
if (isRunning) { if (isRunning) {
MPVLib.attachSurface(surface) MPVLib.attachSurface(surface)
// Re-enable video output after attaching surface (Findroid approach)
MPVLib.setOptionString("force-window", "yes") MPVLib.setOptionString("force-window", "yes")
MPVLib.setOptionString("vo", voDriver) // Read back vo to confirm it's still active
Log.i(TAG, "Surface attached, video output re-enabled (vo=$voDriver)") val activeVo = try { MPVLib.getPropertyString("vo") } catch (e: Exception) { null }
Log.i(TAG, "[PiP] attachSurface — attached, activeVo=$activeVo")
} }
} }
/** /**
* Detach surface and disable video output. * Detach surface without killing the VO pipeline.
* Based on Findroid's implementation. *
* The previous approach (vo=null / force-window=no) destroyed the entire video
* output pipeline on every surface transition. During PiP mode, the rapid
* destroy/recreate cycle caused a black screen because setOptionString("vo", ...)
* did not properly re-initialize rendering into the new PiP surface.
*
* By keeping the VO alive, frames are simply dropped while no surface is
* attached, and rendering resumes immediately when the new surface arrives.
*/ */
fun detachSurface() { fun detachSurface() {
this.surface = null this.surface = null
Log.i(TAG, "[PiP] detachSurface — isRunning=$isRunning, vo=$voDriver")
if (isRunning) { if (isRunning) {
try {
// Disable video output before detaching surface (Findroid approach)
MPVLib.setOptionString("vo", "null")
MPVLib.setOptionString("force-window", "no")
Log.i(TAG, "Video output disabled before surface detach")
} catch (e: Exception) {
Log.e(TAG, "Failed to disable video output: ${e.message}")
}
MPVLib.detachSurface() MPVLib.detachSurface()
val activeVo = try { MPVLib.getPropertyString("vo") } catch (e: Exception) { null }
Log.i(TAG, "[PiP] detachSurface — detached, activeVo=$activeVo (should still be $voDriver)")
} }
} }
@@ -277,7 +283,24 @@ class MPVLayerRenderer(private val context: Context) : MPVLib.EventObserver {
fun updateSurfaceSize(width: Int, height: Int) { fun updateSurfaceSize(width: Int, height: Int) {
if (isRunning) { if (isRunning) {
MPVLib.setPropertyString("android-surface-size", "${width}x$height") MPVLib.setPropertyString("android-surface-size", "${width}x$height")
Log.i(TAG, "Surface size updated: ${width}x$height") Log.i(TAG, "[PiP] updateSurfaceSize ${width}x${height}")
} else {
Log.w(TAG, "[PiP] updateSurfaceSize — called but renderer not running")
}
}
/**
* Force mpv to render a frame to the current surface.
* Steps forward one frame then seeks back to the original position.
* Used after PiP entry to work around mpv stopping pixel output.
*/
fun forceRedraw() {
if (!isRunning) return
val pos = cachedPosition
Log.i(TAG, "[PiP] forceRedraw — stepping frame then seeking to $pos")
MPVLib.command(arrayOf("frame-step"))
if (pos > 0) {
MPVLib.command(arrayOf("seek", pos.toString(), "absolute"))
} }
} }
@@ -692,9 +715,7 @@ class MPVLayerRenderer(private val context: Context) : MPVLib.EventObserver {
// dropped), so we (re)apply here for embedded and external alike. // dropped), so we (re)apply here for embedded and external alike.
// This is what makes a carried-over subtitle show up on the next // This is what makes a carried-over subtitle show up on the next
// episode without a manual re-selection. // episode without a manual re-selection.
if (initialAudioId != null && initialAudioId > 0) { initialAudioId?.let { if (it > 0) setAudioTrack(it) }
setAudioTrack(initialAudioId)
}
initialSubtitleId?.let { setSubtitleTrack(it) } ?: disableSubtitles() initialSubtitleId?.let { setSubtitleTrack(it) } ?: disableSubtitles()
if (!isReadyToSeek) { if (!isReadyToSeek) {

View File

@@ -198,7 +198,7 @@ class MpvPlayerModule : Module() {
} }
// Defines events that the view can send to JavaScript // Defines events that the view can send to JavaScript
Events("onLoad", "onPlaybackStateChange", "onProgress", "onError", "onTracksReady") Events("onLoad", "onPlaybackStateChange", "onProgress", "onError", "onTracksReady", "onPictureInPictureChange")
} }
} }
} }

View File

@@ -2,12 +2,15 @@ package expo.modules.mpvplayer
import android.content.Context import android.content.Context
import android.graphics.Color import android.graphics.Color
import android.os.Build import android.graphics.Rect
import android.graphics.SurfaceTexture
import android.os.Handler
import android.os.Looper
import android.util.Log import android.util.Log
import android.view.Surface import android.view.Surface
import android.view.SurfaceHolder import android.view.TextureView
import android.view.SurfaceView import android.view.View
import android.widget.FrameLayout import android.view.ViewGroup
import expo.modules.kotlin.AppContext import expo.modules.kotlin.AppContext
import expo.modules.kotlin.viewevent.EventDispatcher import expo.modules.kotlin.viewevent.EventDispatcher
import expo.modules.kotlin.views.ExpoView import expo.modules.kotlin.views.ExpoView
@@ -28,10 +31,10 @@ data class VideoLoadConfig(
/** /**
* MpvPlayerView - ExpoView that hosts the MPV player. * MpvPlayerView - ExpoView that hosts the MPV player.
* This mirrors the iOS MpvPlayerView implementation. * Uses TextureView for reliable Picture-in-Picture support.
*/ */
class MpvPlayerView(context: Context, appContext: AppContext) : ExpoView(context, appContext), class MpvPlayerView(context: Context, appContext: AppContext) : ExpoView(context, appContext),
MPVLayerRenderer.Delegate, SurfaceHolder.Callback { MPVLayerRenderer.Delegate, TextureView.SurfaceTextureListener {
companion object { companion object {
private const val TAG = "MpvPlayerView" private const val TAG = "MpvPlayerView"
@@ -43,8 +46,9 @@ class MpvPlayerView(context: Context, appContext: AppContext) : ExpoView(context
val onProgress by EventDispatcher() val onProgress by EventDispatcher()
val onError by EventDispatcher() val onError by EventDispatcher()
val onTracksReady by EventDispatcher() val onTracksReady by EventDispatcher()
val onPictureInPictureChange by EventDispatcher()
private var surfaceView: SurfaceView private var textureView: TextureView
private var renderer: MPVLayerRenderer? = null private var renderer: MPVLayerRenderer? = null
private var pipController: PiPController? = null private var pipController: PiPController? = null
@@ -56,23 +60,29 @@ class MpvPlayerView(context: Context, appContext: AppContext) : ExpoView(context
private var pendingConfig: VideoLoadConfig? = null private var pendingConfig: VideoLoadConfig? = null
private var rendererStarted: Boolean = false private var rendererStarted: Boolean = false
private var pendingSurface: Surface? = null private var pendingSurface: Surface? = null
private var surfaceTexture: SurfaceTexture? = null
// PiP state tracking
private var isWaitingForPiPTransition: Boolean = false
private var isPiPSurfaceForced: Boolean = false
private val pipHandler = Handler(Looper.getMainLooper())
init { init {
setBackgroundColor(Color.BLACK) setBackgroundColor(Color.BLACK)
// Create SurfaceView for video rendering // Create TextureView for video rendering (composites into app window for PiP support)
surfaceView = SurfaceView(context).apply { textureView = TextureView(context).apply {
layoutParams = FrameLayout.LayoutParams( layoutParams = ViewGroup.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT ViewGroup.LayoutParams.MATCH_PARENT
) )
holder.addCallback(this@MpvPlayerView) surfaceTextureListener = this@MpvPlayerView
} }
addView(surfaceView) addView(textureView)
// Initialize PiP controller with Expo's AppContext for proper activity access // Initialize PiP controller with Expo's AppContext for proper activity access
pipController = PiPController(context, appContext) pipController = PiPController(context, appContext)
pipController?.setPlayerView(surfaceView) pipController?.setPlayerView(textureView)
pipController?.delegate = object : PiPController.Delegate { pipController?.delegate = object : PiPController.Delegate {
override fun onPlay() { override fun onPlay() {
play() play()
@@ -85,6 +95,23 @@ class MpvPlayerView(context: Context, appContext: AppContext) : ExpoView(context
override fun onSeekBy(seconds: Double) { override fun onSeekBy(seconds: Double) {
seekBy(seconds) seekBy(seconds)
} }
override fun onPictureInPictureModeChanged(isInPiP: Boolean) {
if (isInPiP) {
if (!isWaitingForPiPTransition) {
isWaitingForPiPTransition = true
pipHandler.removeCallbacksAndMessages(null)
for (delay in longArrayOf(500, 1000, 1500, 2000)) {
pipHandler.postDelayed({ forcePiPBufferSize() }, delay)
}
}
} else {
isWaitingForPiPTransition = false
pipHandler.removeCallbacksAndMessages(null)
restoreFromPiP()
}
onPictureInPictureChange(mapOf("isActive" to isInPiP))
}
} }
// Renderer is created lazily in loadVideo once we have the voDriver setting // Renderer is created lazily in loadVideo once we have the voDriver setting
@@ -102,13 +129,10 @@ class MpvPlayerView(context: Context, appContext: AppContext) : ExpoView(context
try { try {
renderer?.start(voDriver ?: "gpu-next") renderer?.start(voDriver ?: "gpu-next")
rendererStarted = true rendererStarted = true
Log.i(TAG, "Renderer started with vo=$voDriver")
// If surface was created before renderer started, attach it now
pendingSurface?.let { surface -> pendingSurface?.let { surface ->
renderer?.attachSurface(surface) renderer?.attachSurface(surface)
pendingSurface = null pendingSurface = null
Log.i(TAG, "Attached pending surface after renderer start")
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Failed to start renderer: ${e.message}") Log.e(TAG, "Failed to start renderer: ${e.message}")
@@ -116,18 +140,18 @@ class MpvPlayerView(context: Context, appContext: AppContext) : ExpoView(context
} }
} }
// MARK: - SurfaceHolder.Callback // MARK: - TextureView.SurfaceTextureListener
override fun surfaceCreated(holder: SurfaceHolder) { override fun onSurfaceTextureAvailable(surfaceTexture: SurfaceTexture, width: Int, height: Int) {
Log.i(TAG, "Surface created") this.surfaceTexture = surfaceTexture
val surface = Surface(surfaceTexture)
surfaceTexture.setDefaultBufferSize(width, height)
surfaceReady = true surfaceReady = true
if (rendererStarted) { if (rendererStarted) {
renderer?.attachSurface(holder.surface) renderer?.attachSurface(surface)
} else { } else {
// Renderer not started yet - store surface to attach after start pendingSurface = surface
pendingSurface = holder.surface
Log.i(TAG, "Surface created before renderer started, storing as pending")
} }
// If we have a pending load, execute it now // If we have a pending load, execute it now
@@ -138,16 +162,20 @@ class MpvPlayerView(context: Context, appContext: AppContext) : ExpoView(context
} }
} }
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { override fun onSurfaceTextureSizeChanged(surfaceTexture: SurfaceTexture, width: Int, height: Int) {
Log.i(TAG, "Surface changed: ${width}x${height}") surfaceTexture.setDefaultBufferSize(width, height)
// Update MPV with the new surface size (Findroid approach)
renderer?.updateSurfaceSize(width, height) renderer?.updateSurfaceSize(width, height)
} }
override fun surfaceDestroyed(holder: SurfaceHolder) { override fun onSurfaceTextureDestroyed(surfaceTexture: SurfaceTexture): Boolean {
Log.i(TAG, "Surface destroyed") this.surfaceTexture = null
surfaceReady = false surfaceReady = false
renderer?.detachSurface() renderer?.detachSurface()
return false // mpv manages the SurfaceTexture
}
override fun onSurfaceTextureUpdated(surfaceTexture: SurfaceTexture) {
// Called every frame — no action needed, mpv drives rendering directly
} }
// MARK: - Video Loading // MARK: - Video Loading
@@ -239,11 +267,60 @@ class MpvPlayerView(context: Context, appContext: AppContext) : ExpoView(context
// MARK: - Picture in Picture // MARK: - Picture in Picture
fun startPictureInPicture() { fun startPictureInPicture() {
Log.i(TAG, "startPictureInPicture called") isWaitingForPiPTransition = true
pipController?.startPictureInPicture() pipController?.startPictureInPicture()
// Resize buffer to match PiP window after animation settles
pipHandler.removeCallbacksAndMessages(null)
for (delay in longArrayOf(500, 1000, 1500, 2000)) {
pipHandler.postDelayed({ forcePiPBufferSize() }, delay)
}
}
/**
* Resize the SurfaceTexture buffer AND TextureView layout to match the PiP
* visible rect so mpv renders at the PiP window's actual dimensions.
*/
private fun forcePiPBufferSize() {
if (!isWaitingForPiPTransition || !surfaceReady) return
val rect = Rect()
textureView.getGlobalVisibleRect(rect)
val visW = rect.width()
val visH = rect.height()
val vw = textureView.width
val vh = textureView.height
if (visW <= 0 || visH <= 0 || (vw == visW && vh == visH)) return
surfaceTexture?.setDefaultBufferSize(visW, visH)
renderer?.updateSurfaceSize(visW, visH)
// Force TextureView layout to match PiP visible area.
// layoutParams alone doesn't work during PiP because the parent
// never re-lays out its children.
textureView.measure(
View.MeasureSpec.makeMeasureSpec(visW, View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(visH, View.MeasureSpec.EXACTLY)
)
textureView.layout(0, 0, visW, visH)
isPiPSurfaceForced = true
}
private fun restoreFromPiP() {
if (!isPiPSurfaceForced) return
isPiPSurfaceForced = false
val lp = textureView.layoutParams
lp.width = ViewGroup.LayoutParams.MATCH_PARENT
lp.height = ViewGroup.LayoutParams.MATCH_PARENT
textureView.layoutParams = lp
textureView.requestLayout()
} }
fun stopPictureInPicture() { fun stopPictureInPicture() {
isWaitingForPiPTransition = false
pipHandler.removeCallbacksAndMessages(null)
pipController?.stopPictureInPicture() pipController?.stopPictureInPicture()
} }
@@ -368,7 +445,6 @@ class MpvPlayerView(context: Context, appContext: AppContext) : ExpoView(context
} }
override fun onPauseChanged(isPaused: Boolean) { override fun onPauseChanged(isPaused: Boolean) {
// Sync PiP playback rate
pipController?.setPlaybackRate(if (isPaused) 0.0 else 1.0) pipController?.setPlaybackRate(if (isPaused) 0.0 else 1.0)
onPlaybackStateChange(mapOf( onPlaybackStateChange(mapOf(
@@ -394,7 +470,6 @@ class MpvPlayerView(context: Context, appContext: AppContext) : ExpoView(context
} }
override fun onVideoDimensionsChanged(width: Int, height: Int) { override fun onVideoDimensionsChanged(width: Int, height: Int) {
// Update PiP controller with video dimensions for proper aspect ratio
pipController?.setVideoDimensions(width, height) pipController?.setVideoDimensions(width, height)
} }
@@ -405,9 +480,12 @@ class MpvPlayerView(context: Context, appContext: AppContext) : ExpoView(context
// MARK: - Cleanup // MARK: - Cleanup
fun cleanup() { fun cleanup() {
isWaitingForPiPTransition = false
pipHandler.removeCallbacksAndMessages(null)
pipController?.stopPictureInPicture() pipController?.stopPictureInPicture()
renderer?.stop() renderer?.stop()
surfaceView.holder.removeCallback(this) surfaceTexture = null
surfaceReady = false
} }
override fun onDetachedFromWindow() { override fun onDetachedFromWindow() {

View File

@@ -1,33 +1,42 @@
package expo.modules.mpvplayer package expo.modules.mpvplayer
import android.app.Activity import android.app.Activity
import android.app.Application
import android.app.PictureInPictureParams import android.app.PictureInPictureParams
import android.app.RemoteAction
import android.content.BroadcastReceiver
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.graphics.drawable.Icon
import android.graphics.Rect import android.graphics.Rect
import android.os.Build import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.util.Log import android.util.Log
import android.util.Rational import android.util.Rational
import android.view.View import android.view.View
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import expo.modules.kotlin.AppContext import expo.modules.kotlin.AppContext
/**
* Picture-in-Picture controller for Android.
* This mirrors the iOS PiPController implementation.
*/
class PiPController(private val context: Context, private val appContext: AppContext? = null) { class PiPController(private val context: Context, private val appContext: AppContext? = null) {
companion object { companion object {
private const val TAG = "PiPController" private const val TAG = "PiPController"
private const val DEFAULT_ASPECT_WIDTH = 16 private const val DEFAULT_ASPECT_WIDTH = 16
private const val DEFAULT_ASPECT_HEIGHT = 9 private const val DEFAULT_ASPECT_HEIGHT = 9
private const val ACTION_PIP_PLAY_PAUSE = "expo.modules.mpvplayer.PIP_PLAY_PAUSE"
private const val ACTION_PIP_SKIP_FORWARD = "expo.modules.mpvplayer.PIP_SKIP_FORWARD"
private const val ACTION_PIP_SKIP_BACKWARD = "expo.modules.mpvplayer.PIP_SKIP_BACKWARD"
} }
interface Delegate { interface Delegate {
fun onPlay() fun onPlay()
fun onPause() fun onPause()
fun onSeekBy(seconds: Double) fun onSeekBy(seconds: Double)
fun onPictureInPictureModeChanged(isInPiP: Boolean)
} }
var delegate: Delegate? = null var delegate: Delegate? = null
@@ -36,16 +45,18 @@ class PiPController(private val context: Context, private val appContext: AppCon
private var currentDuration: Double = 0.0 private var currentDuration: Double = 0.0
private var playbackRate: Double = 1.0 private var playbackRate: Double = 1.0
// Video dimensions for proper aspect ratio
private var videoWidth: Int = 0 private var videoWidth: Int = 0
private var videoHeight: Int = 0 private var videoHeight: Int = 0
// Reference to the player view for source rect
private var playerView: View? = null private var playerView: View? = null
/** // PiP state tracking
* Check if Picture-in-Picture is supported on this device private var isInPiPMode: Boolean = false
*/ private var pipEntryNotified: Boolean = false
private val pipHandler = Handler(Looper.getMainLooper())
private var lifecycleCallbacks: Application.ActivityLifecycleCallbacks? = null
private var lifecycleRegistered = false
private var pipBroadcastReceiver: BroadcastReceiver? = null
fun isPictureInPictureSupported(): Boolean { fun isPictureInPictureSupported(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE) context.packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
@@ -54,9 +65,6 @@ class PiPController(private val context: Context, private val appContext: AppCon
} }
} }
/**
* Check if Picture-in-Picture is currently active
*/
fun isPictureInPictureActive(): Boolean { fun isPictureInPictureActive(): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val activity = getActivity() val activity = getActivity()
@@ -65,14 +73,11 @@ class PiPController(private val context: Context, private val appContext: AppCon
return false return false
} }
/**
* Start Picture-in-Picture mode
*/
fun startPictureInPicture() { fun startPictureInPicture() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
val activity = getActivity()
if (activity == null) { val activity = getActivity() ?: run {
Log.e(TAG, "Cannot start PiP: no activity found") Log.e(TAG, "Cannot start PiP: no activity")
return return
} }
@@ -83,50 +88,53 @@ class PiPController(private val context: Context, private val appContext: AppCon
try { try {
val params = buildPiPParams(forEntering = true) val params = buildPiPParams(forEntering = true)
activity.enterPictureInPictureMode(params) val result = activity.enterPictureInPictureMode(params)
Log.i(TAG, "Entered PiP mode")
if (!result) {
Log.e(TAG, "enterPictureInPictureMode rejected by system")
isInPiPMode = false
return
}
isInPiPMode = true
pipEntryNotified = true
delegate?.onPictureInPictureModeChanged(true)
registerLifecycleCallbacks()
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Failed to enter PiP: ${e.message}") Log.e(TAG, "Failed to enter PiP: ${e.message}")
} }
} else {
Log.w(TAG, "PiP requires Android O or higher")
}
} }
/**
* Stop Picture-in-Picture mode
*/
fun stopPictureInPicture() { fun stopPictureInPicture() {
// On Android, exiting PiP is typically done by the user isInPiPMode = false
// or by finishing the activity. We can request to move task to back. pipEntryNotified = false
unregisterLifecycleCallbacks()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val activity = getActivity() val activity = getActivity()
if (activity?.isInPictureInPictureMode == true) { if (activity?.isInPictureInPictureMode == true) {
// Move task to back which will exit PiP
activity.moveTaskToBack(false) activity.moveTaskToBack(false)
} }
} }
} }
/** fun isCurrentlyInPiP(): Boolean = isInPiPMode
* Update the current playback position and duration
* Note: We don't update PiP params here as we're not using progress in PiP controls
*/
fun setCurrentTime(position: Double, duration: Double) { fun setCurrentTime(position: Double, duration: Double) {
currentPosition = position currentPosition = position
currentDuration = duration currentDuration = duration
} }
/**
* Set the playback rate (0.0 for paused, 1.0 for playing)
*/
fun setPlaybackRate(rate: Double) { fun setPlaybackRate(rate: Double) {
playbackRate = rate playbackRate = rate
// Update PiP params to reflect play/pause state if (rate > 0) {
registerLifecycleCallbacks()
}
// Update PiP params so autoEnterEnabled and action icons track play/pause state
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val activity = getActivity() val activity = getActivity()
if (activity?.isInPictureInPictureMode == true) { if (activity != null) {
try { try {
activity.setPictureInPictureParams(buildPiPParams()) activity.setPictureInPictureParams(buildPiPParams())
} catch (e: Exception) { } catch (e: Exception) {
@@ -136,23 +144,14 @@ class PiPController(private val context: Context, private val appContext: AppCon
} }
} }
/**
* Set the video dimensions for proper aspect ratio calculation
*/
fun setVideoDimensions(width: Int, height: Int) { fun setVideoDimensions(width: Int, height: Int) {
if (width > 0 && height > 0) { if (width > 0 && height > 0) {
videoWidth = width videoWidth = width
videoHeight = height videoHeight = height
Log.i(TAG, "Video dimensions set: ${width}x${height}")
// Update PiP params if active
updatePiPParamsIfNeeded() updatePiPParamsIfNeeded()
} }
} }
/**
* Set the player view reference for source rect hint
*/
fun setPlayerView(view: View?) { fun setPlayerView(view: View?) {
playerView = view playerView = view
} }
@@ -170,22 +169,15 @@ class PiPController(private val context: Context, private val appContext: AppCon
} }
} }
/**
* Build Picture-in-Picture params for the current player state.
* Calculates proper aspect ratio and source rect based on video and view dimensions.
*/
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O)
private fun buildPiPParams(forEntering: Boolean = false): PictureInPictureParams { private fun buildPiPParams(forEntering: Boolean = false): PictureInPictureParams {
val view = playerView val view = playerView
val viewWidth = view?.width ?: 0 val viewWidth = view?.width ?: 0
val viewHeight = view?.height ?: 0 val viewHeight = view?.height ?: 0
// Display aspect ratio from view (exactly like Findroid)
val displayAspectRatio = Rational(viewWidth.coerceAtLeast(1), viewHeight.coerceAtLeast(1)) val displayAspectRatio = Rational(viewWidth.coerceAtLeast(1), viewHeight.coerceAtLeast(1))
// Video aspect ratio with 2.39:1 clamping (exactly like Findroid) // Video aspect ratio with 2.39:1 clamping
// Findroid: Rational(it.width.coerceAtMost((it.height * 2.39f).toInt()),
// it.height.coerceAtMost((it.width * 2.39f).toInt()))
val aspectRatio = if (videoWidth > 0 && videoHeight > 0) { val aspectRatio = if (videoWidth > 0 && videoHeight > 0) {
Rational( Rational(
videoWidth.coerceAtMost((videoHeight * 2.39f).toInt()), videoWidth.coerceAtMost((videoHeight * 2.39f).toInt()),
@@ -195,26 +187,13 @@ class PiPController(private val context: Context, private val appContext: AppCon
Rational(DEFAULT_ASPECT_WIDTH, DEFAULT_ASPECT_HEIGHT) Rational(DEFAULT_ASPECT_WIDTH, DEFAULT_ASPECT_HEIGHT)
} }
// Source rect hint calculation (exactly like Findroid)
val sourceRectHint = if (viewWidth > 0 && viewHeight > 0 && videoWidth > 0 && videoHeight > 0) { val sourceRectHint = if (viewWidth > 0 && viewHeight > 0 && videoWidth > 0 && videoHeight > 0) {
if (displayAspectRatio < aspectRatio) { if (displayAspectRatio < aspectRatio) {
// Letterboxing - black bars top/bottom
val space = ((viewHeight - (viewWidth.toFloat() / aspectRatio.toFloat())) / 2).toInt() val space = ((viewHeight - (viewWidth.toFloat() / aspectRatio.toFloat())) / 2).toInt()
Rect( Rect(0, space, viewWidth, (viewWidth.toFloat() / aspectRatio.toFloat()).toInt() + space)
0,
space,
viewWidth,
(viewWidth.toFloat() / aspectRatio.toFloat()).toInt() + space
)
} else { } else {
// Pillarboxing - black bars left/right
val space = ((viewWidth - (viewHeight.toFloat() * aspectRatio.toFloat())) / 2).toInt() val space = ((viewWidth - (viewHeight.toFloat() * aspectRatio.toFloat())) / 2).toInt()
Rect( Rect(space, 0, (viewHeight.toFloat() * aspectRatio.toFloat()).toInt() + space, viewHeight)
space,
0,
(viewHeight.toFloat() * aspectRatio.toFloat()).toInt() + space,
viewHeight
)
} }
} else { } else {
null null
@@ -225,39 +204,217 @@ class PiPController(private val context: Context, private val appContext: AppCon
sourceRectHint?.let { builder.setSourceRectHint(it) } sourceRectHint?.let { builder.setSourceRectHint(it) }
// On Android 12+, enable auto-enter (like Findroid) ensurePiPReceiverRegistered()
builder.setActions(buildPiPActions())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
builder.setAutoEnterEnabled(true) builder.setAutoEnterEnabled(forEntering || playbackRate > 0)
} }
return builder.build() return builder.build()
} }
private fun getActivity(): Activity? { private fun getActivity(): Activity? {
// First try Expo's AppContext (preferred in React Native)
appContext?.currentActivity?.let { return it } appContext?.currentActivity?.let { return it }
// Fallback: Try to get from context wrapper chain
var ctx = context var ctx = context
while (ctx is android.content.ContextWrapper) { while (ctx is android.content.ContextWrapper) {
if (ctx is Activity) { if (ctx is Activity) return ctx
return ctx
}
ctx = ctx.baseContext ctx = ctx.baseContext
} }
return null return null
} }
/** // MARK: - Lifecycle-based PiP Detection
* Handle PiP action (called from activity when user taps PiP controls)
*/ private fun registerLifecycleCallbacks() {
fun handlePiPAction(action: String) { if (lifecycleRegistered) return
when (action) {
"play" -> delegate?.onPlay() val app = context.applicationContext as? Application ?: run {
"pause" -> delegate?.onPause() Log.w(TAG, "Cannot access Application for lifecycle callbacks, falling back to polling")
"skip_forward" -> delegate?.onSeekBy(10.0) startFallbackPolling()
"skip_backward" -> delegate?.onSeekBy(-10.0) return
}
lifecycleCallbacks = object : Application.ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
override fun onActivityStarted(activity: Activity) {}
override fun onActivityResumed(activity: Activity) {
if (!isInPiPMode) return
if (!activity.isInPictureInPictureMode) {
isInPiPMode = false
pipEntryNotified = false
delegate?.onPictureInPictureModeChanged(false)
}
}
override fun onActivityPaused(activity: Activity) {
// Proactively hide controls when user leaves while playing,
// before the PiP window captures the UI. onActivityStopped
// will restore if PiP didn't actually enter.
if (playbackRate > 0 && !isInPiPMode) {
isInPiPMode = true
pipEntryNotified = true
delegate?.onPictureInPictureModeChanged(true)
}
}
override fun onActivityStopped(activity: Activity) {
pipHandler.postDelayed({
val inPip = activity.isInPictureInPictureMode
if (inPip && !isInPiPMode) {
isInPiPMode = true
pipEntryNotified = true
delegate?.onPictureInPictureModeChanged(true)
return@postDelayed
}
if (!isInPiPMode) return@postDelayed
if (inPip) return@postDelayed
// Not in PiP after 1s — check again to avoid false positive during transition
pipHandler.postDelayed({
if (!isInPiPMode) return@postDelayed
if (!activity.isInPictureInPictureMode) {
isInPiPMode = false
pipEntryNotified = false
delegate?.onPictureInPictureModeChanged(false)
}
}, 1500)
}, 1000)
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityDestroyed(activity: Activity) {
isInPiPMode = false
}
}
app.registerActivityLifecycleCallbacks(lifecycleCallbacks)
lifecycleRegistered = true
}
private fun unregisterLifecycleCallbacks() {
if (!lifecycleRegistered) return
lifecycleCallbacks?.let {
(context.applicationContext as? Application)
?.unregisterActivityLifecycleCallbacks(it)
}
lifecycleCallbacks = null
lifecycleRegistered = false
pipHandler.removeCallbacksAndMessages(null)
unregisterPiPBroadcastReceiver()
}
private fun startFallbackPolling() {
var falseReadCount = 0
pipHandler.removeCallbacksAndMessages(null)
pipHandler.postDelayed(object : Runnable {
override fun run() {
if (!isInPiPMode) return
var ctx = context
var activity: Activity? = null
while (ctx is android.content.ContextWrapper) {
if (ctx is Activity) { activity = ctx; break }
ctx = ctx.baseContext
}
val stillInPip = activity?.isInPictureInPictureMode == true
if (!stillInPip) {
falseReadCount++
if (falseReadCount >= 3) {
isInPiPMode = false
delegate?.onPictureInPictureModeChanged(false)
return
}
pipHandler.postDelayed(this, 500)
return
}
falseReadCount = 0
pipHandler.postDelayed(this, 1000)
}
}, 3000)
}
// MARK: - PiP Remote Actions
private fun ensurePiPReceiverRegistered() {
if (pipBroadcastReceiver != null) return
pipBroadcastReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when (intent.action) {
ACTION_PIP_PLAY_PAUSE -> {
if (playbackRate > 0) delegate?.onPause() else delegate?.onPlay()
}
ACTION_PIP_SKIP_FORWARD -> delegate?.onSeekBy(10.0)
ACTION_PIP_SKIP_BACKWARD -> delegate?.onSeekBy(-10.0)
} }
} }
} }
val filter = IntentFilter().apply {
addAction(ACTION_PIP_PLAY_PAUSE)
addAction(ACTION_PIP_SKIP_FORWARD)
addAction(ACTION_PIP_SKIP_BACKWARD)
}
val registerFlags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
Context.RECEIVER_EXPORTED
} else {
0
}
context.applicationContext.registerReceiver(pipBroadcastReceiver, filter, registerFlags)
}
private fun unregisterPiPBroadcastReceiver() {
pipBroadcastReceiver?.let {
try {
context.applicationContext.unregisterReceiver(it)
} catch (_: Exception) {}
}
pipBroadcastReceiver = null
}
private fun buildPiPActions(): List<RemoteAction> {
val isPlaying = playbackRate > 0
return listOf(
RemoteAction(
Icon.createWithResource(context, android.R.drawable.ic_media_rew),
"Rewind", "Skip backward 10 seconds",
createPiPPendingIntent(ACTION_PIP_SKIP_BACKWARD)
),
RemoteAction(
Icon.createWithResource(
context,
if (isPlaying) android.R.drawable.ic_media_pause else android.R.drawable.ic_media_play
),
if (isPlaying) "Pause" else "Play",
if (isPlaying) "Pause playback" else "Resume playback",
createPiPPendingIntent(ACTION_PIP_PLAY_PAUSE)
),
RemoteAction(
Icon.createWithResource(context, android.R.drawable.ic_media_ff),
"Fast Forward", "Skip forward 10 seconds",
createPiPPendingIntent(ACTION_PIP_SKIP_FORWARD)
)
)
}
private fun createPiPPendingIntent(action: String): android.app.PendingIntent {
val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
android.app.PendingIntent.FLAG_IMMUTABLE
} else {
0
}
return android.app.PendingIntent.getBroadcast(
context.applicationContext, 0, Intent(action), flags
)
}
}

View File

@@ -1,32 +1,19 @@
Pod::Spec.new do |s| Pod::Spec.new do |s|
s.name = 'MpvPlayer' s.name = 'MpvPlayer'
s.version = '1.0.0' s.version = '1.0.0'
s.summary = 'MPVKit for Expo' s.summary = 'MPV-based video player for Streamyfin (Expo module)'
s.description = 'MPVKit for Expo' s.author = 'Streamyfin'
s.author = 'mpvkit' s.homepage = 'https://github.com/streamyfin/streamyfin'
s.homepage = 'https://github.com/mpvkit/MPVKit' s.platforms = { :ios => '15.1', :tvos => '15.1' }
s.platforms = { s.source = { git: '' }
:ios => '15.1',
:tvos => '15.1'
}
s.source = { git: 'https://github.com/mpvkit/MPVKit.git' }
s.static_framework = true s.static_framework = true
s.dependency 'ExpoModulesCore' s.dependency 'ExpoModulesCore'
s.dependency 'MPVKit-GPL' s.dependency 'MPVKit'
# Swift/Objective-C compatibility
s.pod_target_xcconfig = { s.pod_target_xcconfig = {
'DEFINES_MODULE' => 'YES', 'DEFINES_MODULE' => 'YES',
'VALID_ARCHS' => 'arm64', 'SWIFT_COMPILATION_MODE' => 'wholemodule'
'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386',
'DEBUG_INFORMATION_FORMAT' => 'dwarf',
'STRIP_INSTALLED_PRODUCT' => 'YES',
'DEPLOYMENT_POSTPROCESSING' => 'YES',
}
s.user_target_xcconfig = {
'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386'
} }
s.source_files = "*.{h,m,mm,swift,hpp,cpp}" s.source_files = "*.{h,m,mm,swift,hpp,cpp}"

View File

@@ -25,6 +25,10 @@ export type OnErrorEventPayload = {
export type OnTracksReadyEventPayload = Record<string, never>; export type OnTracksReadyEventPayload = Record<string, never>;
export type OnPictureInPictureChangePayload = {
isActive: boolean;
};
export type NowPlayingMetadata = { export type NowPlayingMetadata = {
title?: string; title?: string;
artist?: string; artist?: string;
@@ -77,6 +81,9 @@ export type MpvPlayerViewProps = {
onProgress?: (event: { nativeEvent: OnProgressEventPayload }) => void; onProgress?: (event: { nativeEvent: OnProgressEventPayload }) => void;
onError?: (event: { nativeEvent: OnErrorEventPayload }) => void; onError?: (event: { nativeEvent: OnErrorEventPayload }) => void;
onTracksReady?: (event: { nativeEvent: OnTracksReadyEventPayload }) => void; onTracksReady?: (event: { nativeEvent: OnTracksReadyEventPayload }) => void;
onPictureInPictureChange?: (event: {
nativeEvent: OnPictureInPictureChangePayload;
}) => void;
}; };
export interface MpvPlayerViewRef { export interface MpvPlayerViewRef {

View File

@@ -7,6 +7,8 @@ import { MpvPlayerViewProps, MpvPlayerViewRef } from "./MpvPlayer.types";
const NativeView: React.ComponentType<MpvPlayerViewProps & { ref?: any }> = const NativeView: React.ComponentType<MpvPlayerViewProps & { ref?: any }> =
requireNativeView("MpvPlayer"); requireNativeView("MpvPlayer");
const PIP_LOG = "[PiP] MpvPlayerView.tsx:";
export default React.forwardRef<MpvPlayerViewRef, MpvPlayerViewProps>( export default React.forwardRef<MpvPlayerViewRef, MpvPlayerViewProps>(
function MpvPlayerView(props, ref) { function MpvPlayerView(props, ref) {
const nativeRef = useRef<any>(null); const nativeRef = useRef<any>(null);
@@ -40,16 +42,24 @@ export default React.forwardRef<MpvPlayerViewRef, MpvPlayerViewProps>(
return await nativeRef.current?.getDuration(); return await nativeRef.current?.getDuration();
}, },
startPictureInPicture: async () => { startPictureInPicture: async () => {
console.log(PIP_LOG, "startPictureInPicture → native");
await nativeRef.current?.startPictureInPicture(); await nativeRef.current?.startPictureInPicture();
console.log(PIP_LOG, "startPictureInPicture ← native returned");
}, },
stopPictureInPicture: async () => { stopPictureInPicture: async () => {
console.log(PIP_LOG, "stopPictureInPicture → native");
await nativeRef.current?.stopPictureInPicture(); await nativeRef.current?.stopPictureInPicture();
console.log(PIP_LOG, "stopPictureInPicture ← native returned");
}, },
isPictureInPictureSupported: async () => { isPictureInPictureSupported: async () => {
return await nativeRef.current?.isPictureInPictureSupported(); const result = await nativeRef.current?.isPictureInPictureSupported();
console.log(PIP_LOG, "isPictureInPictureSupported =", result);
return result;
}, },
isPictureInPictureActive: async () => { isPictureInPictureActive: async () => {
return await nativeRef.current?.isPictureInPictureActive(); const result = await nativeRef.current?.isPictureInPictureActive();
console.log(PIP_LOG, "isPictureInPictureActive =", result);
return result;
}, },
getSubtitleTracks: async () => { getSubtitleTracks: async () => {
return await nativeRef.current?.getSubtitleTracks(); return await nativeRef.current?.getSubtitleTracks();

View File

@@ -1,11 +1,13 @@
import { useTranslation } from "react-i18next";
import { MpvPlayerViewProps } from "./MpvPlayer.types"; import { MpvPlayerViewProps } from "./MpvPlayer.types";
export default function MpvPlayerView(props: MpvPlayerViewProps) { export default function MpvPlayerView(props: MpvPlayerViewProps) {
const url = props.source?.url ?? ""; const url = props.source?.url ?? "";
const { t } = useTranslation();
return ( return (
<div> <div>
<iframe <iframe
title='MPV Player' title={t("player.mpv_player_title")}
style={{ flex: 1 }} style={{ flex: 1 }}
src={url} src={url}
onLoad={() => props.onLoad?.({ nativeEvent: { url } })} onLoad={() => props.onLoad?.({ nativeEvent: { url } })}

View File

@@ -32,9 +32,10 @@
"@expo/react-native-action-sheet": "^4.1.1", "@expo/react-native-action-sheet": "^4.1.1",
"@expo/ui": "~56.0.14", "@expo/ui": "~56.0.14",
"@expo/vector-icons": "^15.0.3", "@expo/vector-icons": "^15.0.3",
"@gorhom/bottom-sheet": "5.2.8", "@gorhom/bottom-sheet": "5.2.14",
"@jellyfin/sdk": "^0.13.0", "@jellyfin/sdk": "^0.13.0",
"@react-native-community/netinfo": "^12.0.0", "@react-native-community/netinfo": "^12.0.0",
"@react-navigation/material-top-tabs": "7.4.28",
"@react-navigation/native": "^7.2.5", "@react-navigation/native": "^7.2.5",
"@shopify/flash-list": "2.0.2", "@shopify/flash-list": "2.0.2",
"@tanstack/query-sync-storage-persister": "^5.100.14", "@tanstack/query-sync-storage-persister": "^5.100.14",
@@ -96,7 +97,7 @@
"react-native-ios-context-menu": "^3.2.1", "react-native-ios-context-menu": "^3.2.1",
"react-native-ios-utilities": "5.2.0", "react-native-ios-utilities": "5.2.0",
"react-native-mmkv": "4.1.1", "react-native-mmkv": "4.1.1",
"react-native-nitro-modules": "0.33.9", "react-native-nitro-modules": "0.33.1",
"react-native-pager-view": "8.0.1", "react-native-pager-view": "8.0.1",
"react-native-qrcode-svg": "^6.3.21", "react-native-qrcode-svg": "^6.3.21",
"react-native-reanimated": "4.3.1", "react-native-reanimated": "4.3.1",
@@ -104,6 +105,7 @@
"react-native-safe-area-context": "~5.7.0", "react-native-safe-area-context": "~5.7.0",
"react-native-screens": "4.25.2", "react-native-screens": "4.25.2",
"react-native-svg": "15.15.4", "react-native-svg": "15.15.4",
"react-native-tab-view": "4.3.0",
"react-native-text-ticker": "^1.15.0", "react-native-text-ticker": "^1.15.0",
"react-native-track-player": "github:lovegaoshi/react-native-track-player#APM", "react-native-track-player": "github:lovegaoshi/react-native-track-player#APM",
"react-native-udp": "^4.1.7", "react-native-udp": "^4.1.7",
@@ -162,10 +164,5 @@
}, },
"trustedDependencies": [ "trustedDependencies": [
"unrs-resolver" "unrs-resolver"
], ]
"patchedDependencies": {
"react-native-udp@4.1.7": "bun-patches/react-native-udp@4.1.7.patch",
"react-native-bottom-tabs@1.2.0": "bun-patches/react-native-bottom-tabs@1.2.0.patch",
"react-native-ios-utilities@5.2.0": "bun-patches/react-native-ios-utilities@5.2.0.patch"
}
} }

View File

@@ -1,10 +1,7 @@
diff --git a/node_modules/react-native-bottom-tabs/.bun-tag-b32ab1c60a5dfcf7 b/.bun-tag-b32ab1c60a5dfcf7 diff --git a/node_modules/react-native-bottom-tabs/ios/BottomAccessoryProvider.swift b/node_modules/react-native-bottom-tabs/ios/BottomAccessoryProvider.swift
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/ios/BottomAccessoryProvider.swift b/ios/BottomAccessoryProvider.swift
index 539efee7156599e1fc795e11bf411b7dfaf12ec7..b2af39a2e6b014e9b1ae0a51b21115c19280df69 100644 index 539efee7156599e1fc795e11bf411b7dfaf12ec7..b2af39a2e6b014e9b1ae0a51b21115c19280df69 100644
--- a/ios/BottomAccessoryProvider.swift --- a/node_modules/react-native-bottom-tabs/ios/BottomAccessoryProvider.swift
+++ b/ios/BottomAccessoryProvider.swift +++ b/node_modules/react-native-bottom-tabs/ios/BottomAccessoryProvider.swift
@@ -8,7 +8,7 @@ import SwiftUI @@ -8,7 +8,7 @@ import SwiftUI
self.delegate = delegate self.delegate = delegate
} }
@@ -14,10 +11,10 @@ index 539efee7156599e1fc795e11bf411b7dfaf12ec7..b2af39a2e6b014e9b1ae0a51b21115c1
@available(iOS 26.0, *) @available(iOS 26.0, *)
public func emitPlacementChanged(_ placement: TabViewBottomAccessoryPlacement?) { public func emitPlacementChanged(_ placement: TabViewBottomAccessoryPlacement?) {
var placementValue = "none" var placementValue = "none"
diff --git a/ios/TabView/NewTabView.swift b/ios/TabView/NewTabView.swift diff --git a/node_modules/react-native-bottom-tabs/ios/TabView/NewTabView.swift b/node_modules/react-native-bottom-tabs/ios/TabView/NewTabView.swift
index 22c52cdf25ad0f7398d89197cb431ca8dc8e0f99..81411376e68803de8bd83515d42565cfa95daf2b 100644 index 22c52cdf25ad0f7398d89197cb431ca8dc8e0f99..81411376e68803de8bd83515d42565cfa95daf2b 100644
--- a/ios/TabView/NewTabView.swift --- a/node_modules/react-native-bottom-tabs/ios/TabView/NewTabView.swift
+++ b/ios/TabView/NewTabView.swift +++ b/node_modules/react-native-bottom-tabs/ios/TabView/NewTabView.swift
@@ -78,11 +78,11 @@ struct ConditionalBottomAccessoryModifier: ViewModifier { @@ -78,11 +78,11 @@ struct ConditionalBottomAccessoryModifier: ViewModifier {
} }
@@ -56,10 +53,10 @@ index 22c52cdf25ad0f7398d89197cb431ca8dc8e0f99..81411376e68803de8bd83515d42565cf
} }
#endif #endif
+ +
diff --git a/ios/TabViewImpl.swift b/ios/TabViewImpl.swift diff --git a/node_modules/react-native-bottom-tabs/ios/TabViewImpl.swift b/node_modules/react-native-bottom-tabs/ios/TabViewImpl.swift
index 72938be90540ea3a483d7db9a80fb74c04d31272..277278ffdd9268a96cb09869eb1d0c0d5e6ad300 100644 index 72938be90540ea3a483d7db9a80fb74c04d31272..277278ffdd9268a96cb09869eb1d0c0d5e6ad300 100644
--- a/ios/TabViewImpl.swift --- a/node_modules/react-native-bottom-tabs/ios/TabViewImpl.swift
+++ b/ios/TabViewImpl.swift +++ b/node_modules/react-native-bottom-tabs/ios/TabViewImpl.swift
@@ -281,7 +281,7 @@ extension View { @@ -281,7 +281,7 @@ extension View {
@ViewBuilder @ViewBuilder
@@ -69,10 +66,10 @@ index 72938be90540ea3a483d7db9a80fb74c04d31272..277278ffdd9268a96cb09869eb1d0c0d
if #available(iOS 26.0, macOS 26.0, *) { if #available(iOS 26.0, macOS 26.0, *) {
if let behavior { if let behavior {
self.tabBarMinimizeBehavior(behavior.convert()) self.tabBarMinimizeBehavior(behavior.convert())
diff --git a/ios/TabViewProps.swift b/ios/TabViewProps.swift diff --git a/node_modules/react-native-bottom-tabs/ios/TabViewProps.swift b/node_modules/react-native-bottom-tabs/ios/TabViewProps.swift
index 9cfb29a983b34d3f84fc7a678d19ef4ff30e0325..6a5854483e66200b71722bbac12e100742222bd3 100644 index 9cfb29a983b34d3f84fc7a678d19ef4ff30e0325..6a5854483e66200b71722bbac12e100742222bd3 100644
--- a/ios/TabViewProps.swift --- a/node_modules/react-native-bottom-tabs/ios/TabViewProps.swift
+++ b/ios/TabViewProps.swift +++ b/node_modules/react-native-bottom-tabs/ios/TabViewProps.swift
@@ -6,7 +6,7 @@ internal enum MinimizeBehavior: String { @@ -6,7 +6,7 @@ internal enum MinimizeBehavior: String {
case onScrollUp case onScrollUp
case onScrollDown case onScrollDown

View File

@@ -1,7 +1,7 @@
diff --git a/ios/Sources/Extensions+Helpers/RCTView+Helpers.swift b/ios/Sources/Extensions+Helpers/RCTView+Helpers.swift diff --git a/node_modules/react-native-ios-utilities/ios/Sources/Extensions+Helpers/RCTView+Helpers.swift b/node_modules/react-native-ios-utilities/ios/Sources/Extensions+Helpers/RCTView+Helpers.swift
index 09be306d5aa39337c5114c2ad6ba7513218e0751..24ff8ee2c36fef8632a7e012514fd04db9bf89fd 100644 index 09be306d5aa39337c5114c2ad6ba7513218e0751..24ff8ee2c36fef8632a7e012514fd04db9bf89fd 100644
--- a/ios/Sources/Extensions+Helpers/RCTView+Helpers.swift --- a/node_modules/react-native-ios-utilities/ios/Sources/Extensions+Helpers/RCTView+Helpers.swift
+++ b/ios/Sources/Extensions+Helpers/RCTView+Helpers.swift +++ b/node_modules/react-native-ios-utilities/ios/Sources/Extensions+Helpers/RCTView+Helpers.swift
@@ -25,15 +25,14 @@ public extension RCTView { @@ -25,15 +25,14 @@ public extension RCTView {
return rootView.recursivelyFindSubview(whereType: targetType); return rootView.recursivelyFindSubview(whereType: targetType);
}; };

View File

@@ -1,10 +1,7 @@
diff --git a/node_modules/react-native-udp/.bun-tag-ea7df8754aa4db91 b/.bun-tag-ea7df8754aa4db91 diff --git a/node_modules/react-native-udp/react-native-udp.podspec b/node_modules/react-native-udp/react-native-udp.podspec
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/react-native-udp.podspec b/react-native-udp.podspec
index 7450cc7d0862aadfb47d796929c801a3dc423a57..fa3e42c0152ef2d87536b8c2e484f64d525e35ec 100644 index 7450cc7d0862aadfb47d796929c801a3dc423a57..fa3e42c0152ef2d87536b8c2e484f64d525e35ec 100644
--- a/react-native-udp.podspec --- a/node_modules/react-native-udp/react-native-udp.podspec
+++ b/react-native-udp.podspec +++ b/node_modules/react-native-udp/react-native-udp.podspec
@@ -9,7 +9,8 @@ Pod::Spec.new do |s| @@ -9,7 +9,8 @@ Pod::Spec.new do |s|
s.homepage = package_json["homepage"] s.homepage = package_json["homepage"]
s.license = package_json["license"] s.license = package_json["license"]

View File

@@ -39,6 +39,28 @@ function buildPatch() {
" end", " end",
" end", " end",
"", "",
" # iOS 26 / Xcode 26: the APP target itself compiles ExpoModulesProvider.swift,",
" # which imports SwiftUI-based modules (ExpoUI, ExpoGlassEffect, GlassPoster, ExpoBlur, …).",
" # That emits a `-framework SwiftUICore` autolink into the app executable's OWN object",
" # files, so the pods-only flag above is not enough — the app's link still fails with",
" # `cannot link directly with 'SwiftUICore'`. Drop the autolink on the user app target",
" # too. Phone-only — tvOS has no SwiftUICore split and must stay untouched.",
" if ENV['EXPO_TV'] != '1'",
" installer.aggregate_targets.each do |agg|",
" next unless agg.user_project",
" agg.user_project.native_targets.each do |target|",
" target.build_configurations.each do |cfg|",
" existing = cfg.build_settings['OTHER_SWIFT_FLAGS'] || '$(inherited)'",
" existing = existing.join(' ') if existing.is_a?(Array)",
" unless existing.include?('-disable-autolink-framework -Xfrontend SwiftUICore')",
" cfg.build_settings['OTHER_SWIFT_FLAGS'] = existing + ' -Xfrontend -disable-autolink-framework -Xfrontend SwiftUICore'",
" end",
" end",
" end",
" agg.user_project.save",
" end",
" end",
"",
" # Safely patch RCTThirdPartyComponentsProvider.mm to avoid startup crash on unlinked Fabric components", " # Safely patch RCTThirdPartyComponentsProvider.mm to avoid startup crash on unlinked Fabric components",
' filepath = "#{installer.sandbox.root}/../build/generated/ios/ReactCodegen/RCTThirdPartyComponentsProvider.mm"', ' filepath = "#{installer.sandbox.root}/../build/generated/ios/ReactCodegen/RCTThirdPartyComponentsProvider.mm"',
" if File.exist?(filepath)", " if File.exist?(filepath)",

View File

@@ -4,9 +4,16 @@ const { withEntitlementsPlist } = require("expo/config-plugins");
* Expo config plugin to add User Management entitlement for tvOS profile linking * Expo config plugin to add User Management entitlement for tvOS profile linking
*/ */
const withTVUserManagement = (config) => { const withTVUserManagement = (config) => {
// Only add for tvOS builds. The entitlement is restricted by Apple and must
// be present in the provisioning profile, so injecting it into mobile builds
// breaks signing ("Entitlement ... not found and could not be included in
// profile"). The entitlement is only needed for tvOS
// TVUserManager.currentUserIdentifier.
if (process.env.EXPO_TV !== "1") {
return config;
}
return withEntitlementsPlist(config, (config) => { return withEntitlementsPlist(config, (config) => {
// Only add for tvOS builds (check if building for TV)
// The entitlement is needed for TVUserManager.currentUserIdentifier to work
config.modResults["com.apple.developer.user-management"] = [ config.modResults["com.apple.developer.user-management"] = [
"runs-as-current-user", "runs-as-current-user",
]; ];

View File

@@ -53,7 +53,7 @@ const initialApi = (() => {
const id = getOrSetDeviceId(); const id = getOrSetDeviceId();
const deviceName = getDeviceNameSync(); const deviceName = getDeviceNameSync();
const jellyfinInstance = new Jellyfin({ const jellyfinInstance = new Jellyfin({
clientInfo: { name: "Streamyfin", version: "0.54.0" }, clientInfo: { name: "Streamyfin", version: "0.54.1" },
deviceInfo: { deviceInfo: {
name: deviceName, name: deviceName,
id, id,
@@ -69,6 +69,13 @@ const initialApi = (() => {
const initialUser = (() => { const initialUser = (() => {
try { try {
// Only return a stored user if we also have a token. Otherwise the
// user atom would be populated while the api atom is null (e.g. after
// a logout that left stale user JSON in storage), which causes
// useProtectedRoute to keep us inside the (auth) group instead of
// redirecting to /login.
const token = storage.getString("token");
if (!token) return null;
const userStr = storage.getString("user"); const userStr = storage.getString("user");
if (userStr) { if (userStr) {
return JSON.parse(userStr) as UserDto; return JSON.parse(userStr) as UserDto;
@@ -128,7 +135,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
const id = getOrSetDeviceId(); const id = getOrSetDeviceId();
const deviceName = getDeviceNameSync(); const deviceName = getDeviceNameSync();
return new Jellyfin({ return new Jellyfin({
clientInfo: { name: "Streamyfin", version: "0.54.0" }, clientInfo: { name: "Streamyfin", version: "0.54.1" },
deviceInfo: { deviceInfo: {
name: deviceName, name: deviceName,
id, id,
@@ -162,7 +169,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
return { return {
authorization: `MediaBrowser Client="Streamyfin", Device=${ authorization: `MediaBrowser Client="Streamyfin", Device=${
Platform.OS === "android" ? "Android" : "iOS" Platform.OS === "android" ? "Android" : "iOS"
}, DeviceId="${deviceId}", Version="0.54.0"`, }, DeviceId="${deviceId}", Version="0.54.1"`,
}; };
}, [deviceId]); }, [deviceId]);
@@ -402,6 +409,7 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
); );
storage.remove("token"); storage.remove("token");
storage.remove("user");
clearTVDiscoverySafely(); clearTVDiscoverySafely();
setUser(null); setUser(null);
setApi(null); setApi(null);

View File

@@ -29,6 +29,10 @@
<string>$(MARKETING_VERSION)</string> <string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string> <string>$(CURRENT_PROJECT_VERSION)</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
<key>NSExtension</key> <key>NSExtension</key>
<dict> <dict>
<key>NSExtensionPointIdentifier</key> <key>NSExtensionPointIdentifier</key>

View File

@@ -4,6 +4,9 @@
"error_title": "خطأ", "error_title": "خطأ",
"login_title": "تسجيل الدخول", "login_title": "تسجيل الدخول",
"login_to_title": "تسجيل الدخول إلى", "login_to_title": "تسجيل الدخول إلى",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "اسم المستخدم", "username_placeholder": "اسم المستخدم",
"password_placeholder": "كلمة المرور", "password_placeholder": "كلمة المرور",
"login_button": "تسجيل الدخول", "login_button": "تسجيل الدخول",
@@ -30,48 +33,54 @@
"connect_button": "اتصل", "connect_button": "اتصل",
"previous_servers": "الخوادم السابقة", "previous_servers": "الخوادم السابقة",
"clear_button": "مسح", "clear_button": "مسح",
"swipe_to_remove": "Swipe to remove", "swipe_to_remove": "مرر للإزالة",
"search_for_local_servers": "البحث عن الخوادم المحلية", "search_for_local_servers": "البحث عن الخوادم المحلية",
"searching": "جاري البحث...", "searching": "جاري البحث...",
"servers": "الخوادم", "servers": "الخوادم",
"saved": "Saved", "saved": "تم الحفظ",
"session_expired": "Session Expired", "session_expired": "انتهت الجلسة",
"please_login_again": "Your saved session has expired. Please log in again.", "please_login_again": "انتهت مدة صلاحية جلستك. الرجاء تسجيل الدخول مرة أخرى.",
"remove_saved_login": "Remove Saved Login", "remove_saved_login": "إزالة تسجيل دخول محفوظ",
"remove_saved_login_description": "This will remove your saved credentials for this server. You'll need to enter your username and password again next time.", "remove_saved_login_description": "سيؤدي هذا إلى إزالة بيانات تسجيل الدخول الخاص بك المحفوظة لهذا الخادم. ستحتاج إلى إدخال اسم المستخدم وكلمة المرور مرة أخرى في المرة القادمة.",
"accounts_count": "{{count}} accounts", "accounts_count": "الحسابات {{count}}",
"select_account": "Select Account", "select_account": "اختر الحساب",
"add_account": "Add Account", "add_account": "إضافة حساب",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "سيؤدي هذا إلى إزالة بيانات تسجيل الدخول لـ {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "حفظ الحساب",
"save_for_later": "Save this account", "save_for_later": "حفظ هذا الحساب",
"security_option": "Security Option", "security_option": "‮خيارات الأمان",
"no_protection": "No protection", "no_protection": "بدون حماية",
"no_protection_desc": "Quick login without authentication", "no_protection_desc": "تسجيل دخول سريع بدون مصادقة",
"pin_code": "PIN code", "pin_code": "رمز PIN",
"pin_code_desc": "4-digit PIN required when switching", "pin_code_desc": "رمز PIN مكون من 4 أرقام مطلوب عند التبديل",
"password": "Re-enter password", "password": "أعد إدخال كلمة المرور",
"password_desc": "Password required when switching", "password_desc": "كلمة المرور مطلوبة عند التبديل",
"save_button": "Save", "save_button": "حفظ",
"cancel_button": "Cancel" "cancel_button": "إلغاء"
}, },
"pin": { "pin": {
"enter_pin": "Enter PIN", "enter_pin": "‏أدخل رمز PIN",
"enter_pin_for": "Enter PIN for {{username}}", "enter_pin_for": "أدخل رمز PIN لـ {{username}}",
"enter_4_digits": "Enter 4 digits", "enter_4_digits": "ادخل 4 أرقام",
"invalid_pin": "Invalid PIN", "invalid_pin": "PIN غير صالح",
"setup_pin": "Set Up PIN", "setup_pin": "تعيين رمز PIN",
"confirm_pin": "Confirm PIN", "confirm_pin": "تأكيد رمز PIN",
"pins_dont_match": "PINs don't match", "pins_dont_match": "رموز PIN غير متطابقة",
"forgot_pin": "Forgot PIN?", "forgot_pin": "نسيت رمز PIN؟",
"forgot_pin_desc": "Your saved credentials will be removed" "forgot_pin_desc": "سيتم إزالة بيانات تسجيل الدخول المحفوظة الخاصة بك"
}, },
"password": { "password": {
"enter_password": "Enter Password", "enter_password": "أدخل كلمة المرور",
"enter_password_for": "Enter password for {{username}}", "enter_password_for": "أدخل كلمة المرور لـ {{username}}",
"invalid_password": "Invalid password" "invalid_password": "كلمة المرور غير صحيحة"
}, },
"home": { "home": {
"checking_server_connection": "التحقق من اتصال الخادم...", "checking_server_connection": "التحقق من اتصال الخادم...",
@@ -86,8 +95,9 @@
"oops": "عفوًا!", "oops": "عفوًا!",
"error_message": "حدث خطأ ما.\nيرجى تسجيل الخروج ثم الدخول مرة أخرى.", "error_message": "حدث خطأ ما.\nيرجى تسجيل الخروج ثم الدخول مرة أخرى.",
"continue_watching": "متابعة المشاهدة", "continue_watching": "متابعة المشاهدة",
"continue": "Continue",
"next_up": "التالي", "next_up": "التالي",
"continue_and_next_up": "Continue & Next Up", "continue_and_next_up": "تابع و التالي",
"recently_added_in": "أضيف مؤخراً في {{libraryName}}", "recently_added_in": "أضيف مؤخراً في {{libraryName}}",
"suggested_movies": "أفلام مقترحة", "suggested_movies": "أفلام مقترحة",
"suggested_episodes": "حلقات مقترحة", "suggested_episodes": "حلقات مقترحة",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "الإعدادات", "settings_title": "الإعدادات",
"log_out_button": "تسجيل الخروج", "log_out_button": "تسجيل الخروج",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "الأقسام" "title": "الأقسام"
}, },
@@ -120,36 +136,45 @@
}, },
"appearance": { "appearance": {
"title": "المظهر", "title": "المظهر",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up", "merge_next_up_continue_watching": "دمج تابع المشاهدة والتالي",
"hide_remote_session_button": "Hide Remote Session Button" "hide_remote_session_button": "إخفاء زر جلسة البث عن بُعد",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "الشبكة",
"local_network": "Local Network", "local_network": "الشبكة المحلية",
"auto_switch_enabled": "Auto-switch when at home", "auto_switch_enabled": "التبديل التلقائي عند المنزل",
"auto_switch_description": "Automatically switch to local URL when connected to home WiFi", "auto_switch_description": "التبديل تلقائياً إلى رابط URL محلي عند الاتصال بشبكة WiFi المنزلية",
"local_url": "Local URL", "local_url": "رابط محلي",
"local_url_hint": "Enter your local server address (e.g., http://192.168.1.100:8096)", "local_url_hint": "أدخل عنوان الخادم المحلي الخاص بك (على سبيل المثال http://192.168.1.100:8096)",
"local_url_placeholder": "http://192.168.1.100:8096", "local_url_placeholder": "http://192.168.1.100:8096",
"home_wifi_networks": "Home WiFi Networks", "home_wifi_networks": "شبكات WiFi المنزل",
"add_current_network": "Add \"{{ssid}}\"", "add_current_network": "إضافة \"{{ssid}}\"",
"not_connected_to_wifi": "Not connected to WiFi", "not_connected_to_wifi": "غير متصل بشبكة WiFi",
"no_networks_configured": "No networks configured", "no_networks_configured": "لا توجد شبكات مكونة",
"add_network_hint": "Add your home WiFi network to enable auto-switching", "add_network_hint": "إضافة شبكة WiFi المنزلية الخاصة بك لتمكين التبديل التلقائي",
"current_wifi": "Current WiFi", "current_wifi": "شبكة WiFi الحالية",
"using_url": "Using", "using_url": "استخدام",
"local": "Local URL", "local": "رابط محلي",
"remote": "Remote URL", "remote": "الـ URL الخارجي",
"not_connected": "Not connected", "not_connected": "غير متصل",
"current_server": "Current Server", "current_server": "الخادم الحالي",
"remote_url": "Remote URL", "remote_url": "الـ URL الخارجي",
"active_url": "Active URL", "active_url": "الرابط النشط",
"not_configured": "Not configured", "not_configured": "لم يتم تكوينه",
"network_added": "Network added", "network_added": "تمت إضافة الشبكة",
"network_already_added": "Network already added", "network_already_added": "الشبكة مضافة مسبقاً",
"no_wifi_connected": "Not connected to WiFi", "no_wifi_connected": "غير متصل بشبكة WiFi",
"permission_denied": "Location permission denied", "permission_denied": "تم رفض إذن الوصول إلى الموقع",
"permission_denied_explanation": "Location permission is required to detect WiFi network for auto-switching. Please enable it in Settings." "permission_denied_explanation": "يتطلب التعرف على شبكة WiFi للتبديل التلقائي الحصول على إذن الوصول إلى الموقع. يرجى تفعيله من الإعدادات."
}, },
"user_info": { "user_info": {
"user_info_title": "معلومات المستخدم", "user_info_title": "معلومات المستخدم",
@@ -174,6 +199,22 @@
"rewind_length": "مدة الترجيع", "rewind_length": "مدة الترجيع",
"seconds_unit": "ث" "seconds_unit": "ث"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "التحكم بالإيماءات", "gesture_controls_title": "التحكم بالإيماءات",
"horizontal_swipe_skip": "السحب الأفقي للتخطي", "horizontal_swipe_skip": "السحب الأفقي للتخطي",
@@ -182,10 +223,10 @@
"left_side_brightness_description": "اسحب لأعلى/لأسفل على الجانب الأيسر لضبط السطوع", "left_side_brightness_description": "اسحب لأعلى/لأسفل على الجانب الأيسر لضبط السطوع",
"right_side_volume": "التحكم في مستوى الصوت من الجانب الأيمن", "right_side_volume": "التحكم في مستوى الصوت من الجانب الأيمن",
"right_side_volume_description": "اسحب لأعلى/لأسفل على الجانب الأيمن لضبط مستوى الصوت", "right_side_volume_description": "اسحب لأعلى/لأسفل على الجانب الأيمن لضبط مستوى الصوت",
"hide_volume_slider": "Hide Volume Slider", "hide_volume_slider": "إخفاء شريط مستوى الصوت",
"hide_volume_slider_description": "Hide the volume slider in the video player", "hide_volume_slider_description": "إخفاء شريط التحكم في مستوى الصوت في مشغل الفيديو",
"hide_brightness_slider": "Hide Brightness Slider", "hide_brightness_slider": "إخفاء شريط السطوع",
"hide_brightness_slider_description": "Hide the brightness slider in the video player" "hide_brightness_slider_description": "إخفاء شريط التحكم في السطوع في مشغل الفيديو"
}, },
"audio": { "audio": {
"audio_title": "الصوت", "audio_title": "الصوت",
@@ -195,12 +236,12 @@
"none": "لا شيء", "none": "لا شيء",
"language": "اللغة", "language": "اللغة",
"transcode_mode": { "transcode_mode": {
"title": "Audio Transcoding", "title": "تحويل ترميز الصوت",
"description": "Controls how surround audio (7.1, TrueHD, DTS-HD) is handled", "description": "يتحكم في كيفية التعامل مع الصوت المحيطي (7.1، TrueHD، DTS-HD)",
"auto": "Auto", "auto": "تلقائي",
"stereo": "Force Stereo", "stereo": "إجبار تشغيل ستيريو",
"5_1": "Allow 5.1", "5_1": "السماح بـ 5.1",
"passthrough": "Passthrough" "passthrough": "تمرير الصوت"
} }
}, },
"subtitles": { "subtitles": {
@@ -251,29 +292,45 @@
"Normal": "عادي", "Normal": "عادي",
"Thick": "سميك" "Thick": "سميك"
}, },
"subtitle_color": "Subtitle Color", "subtitle_color": "لون الترجمة",
"subtitle_background_color": "Background Color", "subtitle_background_color": "لون الخلفية",
"subtitle_font": "Subtitle Font", "subtitle_font": "خط الترجمة",
"ksplayer_title": "KSPlayer Settings", "ksplayer_title": "إعدادات KSPlayer",
"hardware_decode": "Hardware Decoding", "hardware_decode": "فك الترميز بواسطة الجهاز",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues." "hardware_decode_description": "استخدم تسريع العتاد لفك ترميز الفيديو. قم بتعطيله إذا واجهت مشكلات في التشغيل.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "إعدادات ترجمة VLC",
"hint": "Customize subtitle appearance for VLC player. Changes take effect on next playback.", "hint": "تخصيص مظهر الترجمة لمشغل VLC. تصبح التغييرات سارية المفعول عند التشغيل التالي.",
"text_color": "Text Color", "text_color": "لون النص",
"background_color": "Background Color", "background_color": "لون الخلفية",
"background_opacity": "Background Opacity", "background_opacity": "شفافية الخلفية",
"outline_color": "Outline Color", "outline_color": "لون إطار الخط",
"outline_opacity": "Outline Opacity", "outline_opacity": "شفافية إطار الخط",
"outline_thickness": "Outline Thickness", "outline_thickness": "سمك إطار الخط",
"bold": "Bold Text", "bold": "خط عريض",
"margin": "Bottom Margin" "margin": "الهامش السفلي"
}, },
"video_player": { "video_player": {
"title": "Video Player", "title": "مشغل الفيديو",
"video_player": "Video Player", "video_player": "مشغل الفيديو",
"video_player_description": "Choose which video player to use on iOS.", "video_player_description": "اختر مشغل الفيديو الذي سيتم استخدامه على نظام iOS.",
"ksplayer": "KSPlayer", "ksplayer": "KSPlayer",
"vlc": "VLC" "vlc": "VLC"
}, },
@@ -305,8 +362,8 @@
"select_liraries_you_want_to_hide": "اختر المكتبات التي تريد إخفاءها من تبويب المكتبة وأقسام الصفحة الرئيسية.", "select_liraries_you_want_to_hide": "اختر المكتبات التي تريد إخفاءها من تبويب المكتبة وأقسام الصفحة الرئيسية.",
"disable_haptic_feedback": "تعطيل ردود الفعل اللمسية", "disable_haptic_feedback": "تعطيل ردود الفعل اللمسية",
"default_quality": "الجودة الافتراضية", "default_quality": "الجودة الافتراضية",
"default_playback_speed": "Default Playback Speed", "default_playback_speed": "سرعة التشغيل الافتراضية",
"auto_play_next_episode": "Auto-play Next Episode", "auto_play_next_episode": "تشغيل الحلقة التالية تلقائياً",
"max_auto_play_episode_count": "الحد الأقصى لعدد الحلقات التي يتم تشغيلها تلقائيًا", "max_auto_play_episode_count": "الحد الأقصى لعدد الحلقات التي يتم تشغيلها تلقائيًا",
"disabled": "معطل" "disabled": "معطل"
}, },
@@ -314,15 +371,15 @@
"downloads_title": "التنزيلات" "downloads_title": "التنزيلات"
}, },
"music": { "music": {
"title": "Music", "title": "الموسيقى",
"playback_title": "Playback", "playback_title": "التشغيل",
"playback_description": "Configure how music is played.", "playback_description": "ضبط كيفية تشغيل الموسيقى.",
"prefer_downloaded": "Prefer Downloaded Songs", "prefer_downloaded": "تفضيل الأغاني التي تم تنزيلها",
"caching_title": "Caching", "caching_title": "التخزين المؤقت",
"caching_description": "Automatically cache upcoming tracks for smoother playback.", "caching_description": "تخزين الأغاني التالية مؤقتاً تلقائياً لضمان تشغيل أكثر سلاسة.",
"lookahead_enabled": "Enable Look-Ahead Caching", "lookahead_enabled": "تفعيل التخزين المؤقت الاستباقي",
"lookahead_count": "Tracks to Pre-cache", "lookahead_count": "عدد الأغاني المراد تخزينها مسبقاً",
"max_cache_size": "Max Cache Size" "max_cache_size": "الحد الأقصى لحجم التخزين المؤقت"
}, },
"plugins": { "plugins": {
"plugins_title": "الإضافات", "plugins_title": "الإضافات",
@@ -357,39 +414,39 @@
"save_button": "حفظ", "save_button": "حفظ",
"toasts": { "toasts": {
"saved": "تم الحفظ", "saved": "تم الحفظ",
"refreshed": "Settings refreshed from server" "refreshed": "تم تحديث الإعدادات من الخادم"
}, },
"refresh_from_server": "Refresh Settings from Server" "refresh_from_server": "تحديث الإعدادات من الخادم"
}, },
"streamystats": { "streamystats": {
"enable_streamystats": "Enable Streamystats", "enable_streamystats": "تفعيل Streamystats",
"disable_streamystats": "Disable Streamystats", "disable_streamystats": "تعطيل Streamystats",
"enable_search": "Use for Search", "enable_search": "استخدم للبحث",
"url": "URL", "url": "الرابط",
"server_url_placeholder": "http(s)://streamystats.example.com", "server_url_placeholder": "http(s)://streamystats.example.com",
"streamystats_search_hint": "Enter the URL for your Streamystats server. The URL should include http or https and optionally the port.", "streamystats_search_hint": "أدخل رابط خادم Streamystats الخاص بك. يجب أن يتضمن الرابط البروتوكول http أو https مع رقم المنفذ اختيارياً.",
"read_more_about_streamystats": "Read More About Streamystats.", "read_more_about_streamystats": "اقرأ المزيد عن Streamystats.",
"save_button": "Save", "save_button": "حفظ",
"save": "Save", "save": "حفظ",
"features_title": "Features", "features_title": "المميزات",
"home_sections_title": "Home Sections", "home_sections_title": "أقسام الرئيسية",
"enable_movie_recommendations": "Movie Recommendations", "enable_movie_recommendations": "توصيات الأفلام",
"enable_series_recommendations": "Series Recommendations", "enable_series_recommendations": "توصيات المسلسلات",
"enable_promoted_watchlists": "Promoted Watchlists", "enable_promoted_watchlists": "قوائم مشاهدة مختارة",
"hide_watchlists_tab": "Hide Watchlists Tab", "hide_watchlists_tab": "إخفاء تبويب قوائم المشاهدة",
"home_sections_hint": "Show personalized recommendations and promoted watchlists from Streamystats on the home page.", "home_sections_hint": "إظهار التوصيات المخصصة وقوائم المشاهدة المختارة من Streamystats في الصفحة الرئيسية.",
"recommended_movies": "Recommended Movies", "recommended_movies": "أفلام موصى بها",
"recommended_series": "Recommended Series", "recommended_series": "مسلسلات موصى بها",
"toasts": { "toasts": {
"saved": "Saved", "saved": "تم الحفظ",
"refreshed": "Settings refreshed from server", "refreshed": "تم تحديث الإعدادات من الخادم",
"disabled": "Streamystats disabled" "disabled": "تم تعطيل Streamystats"
}, },
"refresh_from_server": "Refresh Settings from Server" "refresh_from_server": "تحديث الإعدادات من الخادم"
}, },
"kefinTweaks": { "kefinTweaks": {
"watchlist_enabler": "Enable our Watchlist integration", "watchlist_enabler": "تفعيل الربط مع قائمة المشاهدة الخاصة بنا",
"watchlist_button": "Toggle Watchlist integration" "watchlist_button": "تبديل حالة ربط قائمة المشاهدة"
} }
}, },
"storage": { "storage": {
@@ -398,15 +455,21 @@
"device_usage": "الجهاز {{availableSpace}}%", "device_usage": "الجهاز {{availableSpace}}%",
"size_used": "تم استخدام {{used}} من {{total}}", "size_used": "تم استخدام {{used}} من {{total}}",
"delete_all_downloaded_files": "حذف جميع الملفات التي تم تنزيلها", "delete_all_downloaded_files": "حذف جميع الملفات التي تم تنزيلها",
"music_cache_title": "Music Cache", "music_cache_title": "التخزين المؤقت للموسيقى",
"music_cache_description": "Automatically cache songs as you listen for smoother playback and offline support", "music_cache_description": "تخزين الأغاني تلقائياً أثناء الاستماع لضمان تشغيل أكثر سلاسة ودعم الاستماع بدون اتصال",
"enable_music_cache": "Enable Music Cache", "enable_music_cache": "تمكين التخزين المؤقت للموسيقى",
"clear_music_cache": "Clear Music Cache", "clear_music_cache": "مسح التخزين المؤقت للموسيقى",
"music_cache_size": "{{size}} cached", "music_cache_size": "تم تخزين {{size}} مؤقتاً",
"music_cache_cleared": "Music cache cleared", "music_cache_cleared": "تم مسح التخزين المؤقت للموسيقى",
"delete_all_downloaded_songs": "Delete All Downloaded Songs", "delete_all_downloaded_songs": "حذف جميع الأغاني التي تم تنزيلها",
"downloaded_songs_size": "{{size}} downloaded", "downloaded_songs_size": "تم تنزيل {{size}}",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "تم حذف الأغاني التي تم تنزيلها",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "المقدمة", "title": "المقدمة",
@@ -430,6 +493,21 @@
"error_deleting_files": "خطأ في حذف الملفات", "error_deleting_files": "خطأ في حذف الملفات",
"background_downloads_enabled": "تم تفعيل التنزيلات في الخلفية", "background_downloads_enabled": "تم تفعيل التنزيلات في الخلفية",
"background_downloads_disabled": "تم تعطيل التنزيلات في الخلفية" "background_downloads_disabled": "تم تعطيل التنزيلات في الخلفية"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "يتطلب التحديث الجديد تنزيل المحتوى مرة أخرى. يرجى إزالة كل المحتوى الذي تم تنزيله والمحاولة مرة أخرى.", "new_app_version_requires_re_download_description": "يتطلب التحديث الجديد تنزيل المحتوى مرة أخرى. يرجى إزالة كل المحتوى الذي تم تنزيله والمحاولة مرة أخرى.",
"back": "رجوع", "back": "رجوع",
"delete": "حذف", "delete": "حذف",
"delete_download": "Delete Download",
"something_went_wrong": "حدث خطأ ما", "something_went_wrong": "حدث خطأ ما",
"could_not_get_stream_url_from_jellyfin": "تعذر الحصول على رابط البث من Jellyfin", "could_not_get_stream_url_from_jellyfin": "تعذر الحصول على رابط البث من Jellyfin",
"eta": "الوقت المتبقي {{eta}}", "eta": "الوقت المتبقي {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "اختر", "select": "اختر",
"no_trailer_available": "لا يوجد مقطع دعائي متوفر", "no_trailer_available": "لا يوجد مقطع دعائي متوفر",
"video": "فيديو", "video": "فيديو",
"audio": "الصوت", "audio": "الصوت",
"subtitle": "الترجمة", "subtitle": "الترجمة",
"play": "تشغيل", "play": "تشغيل",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "لا شيء", "none": "لا شيء",
"track": "Track", "track": "أغنية",
"cancel": "Cancel", "cancel": "إلغاء",
"delete": "Delete", "stop": "Stop",
"ok": "OK", "delete": "حذف",
"remove": "Remove", "ok": "حسناً",
"next": "Next", "remove": "إزالة",
"back": "Back", "next": "التالي",
"continue": "Continue", "back": "رجوع",
"verifying": "Verifying..." "continue": "متابعة",
"verifying": "جارٍ التحقق...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "بحث...", "search": "بحث...",
@@ -521,10 +606,10 @@
"episodes": "حلقات", "episodes": "حلقات",
"collections": "مجموعات", "collections": "مجموعات",
"actors": "ممثلون", "actors": "ممثلون",
"artists": "Artists", "artists": "الفنانون",
"albums": "Albums", "albums": "الألبومات",
"songs": "Songs", "songs": "الأغاني",
"playlists": "Playlists", "playlists": "قوائم التشغيل",
"request_movies": "طلب أفلام", "request_movies": "طلب أفلام",
"request_series": "طلب مسلسلات", "request_series": "طلب مسلسلات",
"recently_added": "أضيف مؤخرًا", "recently_added": "أضيف مؤخرًا",
@@ -556,6 +641,7 @@
"movies": "أفلام", "movies": "أفلام",
"series": "مسلسلات", "series": "مسلسلات",
"boxsets": "مجموعات", "boxsets": "مجموعات",
"playlists": "Playlists",
"items": "عناصر" "items": "عناصر"
}, },
"options": { "options": {
@@ -566,15 +652,20 @@
"poster": "ملصق", "poster": "ملصق",
"cover": "غلاف", "cover": "غلاف",
"show_titles": "إظهار العناوين", "show_titles": "إظهار العناوين",
"show_stats": "إظهار الإحصائيات" "show_stats": "إظهار الإحصائيات",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "الأنواع", "genres": "الأنواع",
"years": "السنوات", "years": "السنوات",
"sort_by": "ترتيب حسب", "sort_by": "ترتيب حسب",
"filter_by": "Filter By", "filter_by": "تصفية حسب",
"sort_order": "اتجاه الترتيب", "sort_order": "اتجاه الترتيب",
"tags": "الوسوم" "tags": "الوسوم",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "لا توجد روابط" "no_links": "لا توجد روابط"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "خطأ", "error": "خطأ",
"failed_to_get_stream_url": "فشل في الحصول على رابط البث", "failed_to_get_stream_url": "فشل في الحصول على رابط البث",
"an_error_occured_while_playing_the_video": "حدث خطأ أثناء تشغيل الفيديو. تحقق من السجلات في الإعدادات.", "an_error_occured_while_playing_the_video": "حدث خطأ أثناء تشغيل الفيديو. تحقق من السجلات في الإعدادات.",
@@ -604,11 +697,39 @@
"index": "الفِهْرِس:", "index": "الفِهْرِس:",
"continue_watching": "متابعة المشاهدة", "continue_watching": "متابعة المشاهدة",
"go_back": "رجوع", "go_back": "رجوع",
"downloaded_file_title": "You have this file downloaded", "downloaded_file_title": "تم تنزيل هذا الملف",
"downloaded_file_message": "هل تريد تشغيل الملف الذي تم تنزيله؟", "downloaded_file_message": "هل تريد تشغيل الملف الذي تم تنزيله؟",
"downloaded_file_yes": "نعم", "downloaded_file_yes": "نعم",
"downloaded_file_no": "لا", "downloaded_file_no": "لا",
"downloaded_file_cancel": "Cancel" "downloaded_file_cancel": "إلغاء",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "التالي", "next_up": "التالي",
@@ -617,6 +738,11 @@
"series": "مسلسلات", "series": "مسلسلات",
"seasons": "مواسم", "seasons": "مواسم",
"season": "موسم", "season": "موسم",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "لا توجد حلقات لهذا الموسم", "no_episodes_for_this_season": "لا توجد حلقات لهذا الموسم",
"overview": "نظرة عامة", "overview": "نظرة عامة",
"more_with": "المزيد مع {{name}}", "more_with": "المزيد مع {{name}}",
@@ -624,13 +750,24 @@
"no_similar_items_found": "لم يتم العثور على عناصر مشابهة", "no_similar_items_found": "لم يتم العثور على عناصر مشابهة",
"video": "فيديو", "video": "فيديو",
"more_details": "المزيد من التفاصيل", "more_details": "المزيد من التفاصيل",
"media_options": "Media Options", "media_options": "خيارات الوسائط",
"quality": "الجودة", "quality": "الجودة",
"audio": "الصوت", "audio": "الصوت",
"subtitles": "الترجمة", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "عرض المزيد", "show_more": "عرض المزيد",
"show_less": "عرض أقل", "show_less": "عرض أقل",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "ظهر في", "appeared_in": "ظهر في",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "تعذر تحميل العنصر", "could_not_load_item": "تعذر تحميل العنصر",
"none": "لا شيء", "none": "لا شيء",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "تنزيل {{item_count}} عناصر", "download_x_item": "تنزيل {{item_count}} عناصر",
"download_unwatched_only": "غير المشاهدة فقط", "download_unwatched_only": "غير المشاهدة فقط",
"download_button": "تنزيل" "download_button": "تنزيل"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "التالي", "next": "التالي",
@@ -652,7 +795,18 @@
"movies": "أفلام", "movies": "أفلام",
"sports": "رياضة", "sports": "رياضة",
"for_kids": "للأطفال", "for_kids": "للأطفال",
"news": "أخبار" "news": "أخبار",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "تأكيد", "confirm": "تأكيد",
@@ -697,6 +851,12 @@
"decline": "رفض", "decline": "رفض",
"requested_by": "مطلوب من {{user}}", "requested_by": "مطلوب من {{user}}",
"unknown_user": "مستخدم غير معروف", "unknown_user": "مستخدم غير معروف",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "خادم Seerr لا يستوفي الحد الأدنى للإصدار المطلوب! يرجى التحديث إلى إصدار 2.0.0 على الأقل", "jellyseer_does_not_meet_requirements": "خادم Seerr لا يستوفي الحد الأدنى للإصدار المطلوب! يرجى التحديث إلى إصدار 2.0.0 على الأقل",
"jellyseerr_test_failed": "فشل اختبار Seerr. يرجى المحاولة مرة أخرى.", "jellyseerr_test_failed": "فشل اختبار Seerr. يرجى المحاولة مرة أخرى.",
@@ -716,130 +876,162 @@
"search": "بحث", "search": "بحث",
"library": "المكتبة", "library": "المكتبة",
"custom_links": "روابط مخصصة", "custom_links": "روابط مخصصة",
"favorites": "المفضلة" "favorites": "المفضلة",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Music", "title": "الموسيقى",
"tabs": { "tabs": {
"suggestions": "Suggestions", "suggestions": "الإقتراحات",
"albums": "Albums", "albums": "الألبومات",
"artists": "Artists", "artists": "الفنانون",
"playlists": "Playlists", "playlists": "قوائم التشغيل",
"tracks": "tracks" "tracks": "الأغاني"
}, },
"filters": { "filters": {
"all": "All" "all": "الكل"
}, },
"recently_added": "Recently Added", "recently_added": "أضيف مؤخرًا",
"recently_played": "Recently Played", "recently_played": "تم تشغيله مؤخرًا",
"frequently_played": "Frequently Played", "frequently_played": "الأكثر تشغيلاً",
"explore": "Explore", "explore": "اكتشف",
"top_tracks": "Top Tracks", "top_tracks": "أفضل الأغاني",
"play": "Play", "play": "تشغيل",
"shuffle": "Shuffle", "shuffle": "ترتيب عشوائي",
"play_top_tracks": "Play Top Tracks", "play_top_tracks": "تشغيل أفضل الأغاني",
"no_suggestions": "No suggestions available", "no_suggestions": "لا توجد مقترحات متاحة",
"no_albums": "No albums found", "no_albums": "لا توجد ألبومات",
"no_artists": "No artists found", "no_artists": "لا يوجد فنانون",
"no_playlists": "No playlists found", "no_playlists": "لا توجد قوائم تشغيل",
"album_not_found": "Album not found", "album_not_found": "الألبوم غير موجود",
"artist_not_found": "Artist not found", "artist_not_found": "الفنان غير موجود",
"playlist_not_found": "Playlist not found", "playlist_not_found": "قائمة التشغيل غير موجودة",
"track_options": { "track_options": {
"play_next": "Play Next", "play_next": "تشغيل التالي",
"add_to_queue": "Add to Queue", "add_to_queue": "إضافة إلى قائمة الانتظار",
"add_to_playlist": "Add to Playlist", "add_to_playlist": "أضف إلى قائمة التشغيل",
"download": "Download", "download": "تنزيل",
"downloaded": "Downloaded", "downloaded": "تم التنزيل",
"downloading": "Downloading...", "downloading": "جارٍ التنزيل...",
"cached": "Cached", "cached": "تم التخزين مؤقتاً",
"delete_download": "Delete Download", "delete_download": "حذف ملف التنزيل",
"delete_cache": "Remove from Cache", "delete_cache": "إزالة من التخزين المؤقت",
"go_to_artist": "Go to Artist", "go_to_artist": "انتقال إلى الفنان",
"go_to_album": "Go to Album", "go_to_album": "انتقال إلى الألبوم",
"add_to_favorites": "Add to Favorites", "add_to_favorites": "إضافة إلى المفضلة",
"remove_from_favorites": "Remove from Favorites", "remove_from_favorites": "إزالة من المفضلة",
"remove_from_playlist": "Remove from Playlist" "remove_from_playlist": "إزالة من قائمة التشغيل"
}, },
"playlists": { "playlists": {
"create_playlist": "Create Playlist", "create_playlist": "إنشاء قائمة التشغيل",
"playlist_name": "Playlist Name", "playlist_name": "اسم قائمة التشغيل",
"enter_name": "Enter playlist name", "enter_name": "أدخل اسم قائمة التشغيل",
"create": "Create", "create": "إنشاء",
"search_playlists": "Search playlists...", "search_playlists": "البحث عن قوائم التشغيل...",
"added_to": "Added to {{name}}", "added_to": "تمت الإضافة إلى {{name}}",
"added": "Added to playlist", "added": "تمت الإضافة إلى قائمة التشغيل",
"removed_from": "Removed from {{name}}", "removed_from": "تمت الإزالة من {{name}}",
"removed": "Removed from playlist", "removed": "تمت الازالة من قائمة التشغيل",
"created": "Playlist created", "created": "تم إنشاء قائمة التشغيل",
"create_new": "Create New Playlist", "create_new": "إنشاء قائمة تشغيل جديدة",
"failed_to_add": "Failed to add to playlist", "failed_to_add": "فشلت الإضافة إلى قائمة التشغيل",
"failed_to_remove": "Failed to remove from playlist", "failed_to_remove": "فشلت الإزالة من قائمة التشغيل",
"failed_to_create": "Failed to create playlist", "failed_to_create": "فشل إنشاء قائمة التشغيل",
"delete_playlist": "Delete Playlist", "delete_playlist": "حذف قائمة التشغيل",
"delete_confirm": "Are you sure you want to delete \"{{name}}\"? This action cannot be undone.", "delete_confirm": "هل أنت متأكد من رغبتك في حذف {{name}}؟ لا يمكن التراجع عن هذا الإجراء.",
"deleted": "Playlist deleted", "deleted": "تم حذف قائمة التشغيل",
"failed_to_delete": "Failed to delete playlist" "failed_to_delete": "فشل إنشاء قائمة التشغيل"
}, },
"sort": { "sort": {
"title": "Sort By", "title": "ترتيب حسب",
"alphabetical": "Alphabetical", "alphabetical": "أبجدي",
"date_created": "Date Created" "date_created": "تاريخ الإنشاء"
} }
}, },
"watchlists": { "watchlists": {
"title": "Watchlists", "title": "قوائم المشاهدة",
"my_watchlists": "My Watchlists", "my_watchlists": "قوائم المشاهدة الخاصة بي",
"public_watchlists": "Public Watchlists", "public_watchlists": "قوائم مشاهدة عامة",
"create_title": "Create Watchlist", "create_title": "إنشاء قائمة مشاهدة",
"edit_title": "Edit Watchlist", "edit_title": "تعديل قائمة المشاهدة",
"create_button": "Create Watchlist", "create_button": "إنشاء قائمة مشاهدة",
"save_button": "Save Changes", "save_button": "حفظ التغييرات",
"delete_button": "Delete", "delete_button": "حذف",
"remove_button": "Remove", "remove_button": "إزالة",
"cancel_button": "Cancel", "cancel_button": "إلغاء",
"name_label": "Name", "name_label": "الاسم",
"name_placeholder": "Enter watchlist name", "name_placeholder": "أدخل اسم قائمة المشاهدة",
"description_label": "Description", "description_label": "الوصف",
"description_placeholder": "Enter description (optional)", "description_placeholder": "أدخل الوصف (اختياري)",
"is_public_label": "Public Watchlist", "is_public_label": "قائمة مشاهدة عامة",
"is_public_description": "Allow others to view this watchlist", "is_public_description": "السماح للآخرين بعرض قائمة المشاهدة هذه",
"allowed_type_label": "Content Type", "allowed_type_label": "نوع المحتوى",
"sort_order_label": "Default Sort Order", "sort_order_label": "الترتيب الافتراضي",
"empty_title": "No Watchlists", "empty_title": "لا توجد قوائم مشاهدة",
"empty_description": "Create your first watchlist to start organizing your media", "empty_description": "قم بإنشاء أول قائمة مشاهدة لبدء تنظيم الوسائط الخاصة بك",
"empty_watchlist": "This watchlist is empty", "empty_watchlist": "قائمة المشاهدة هذه فارغة",
"empty_watchlist_hint": "Add items from your library to this watchlist", "empty_watchlist_hint": "إضافة عناصر من مكتبتك إلى قائمة المشاهدة هذه",
"not_configured_title": "Streamystats Not Configured", "not_configured_title": "لم يتم ضبط Streamystats",
"not_configured_description": "Configure Streamystats in settings to use watchlists", "not_configured_description": "اضبط Streamystats في الإعدادات لاستخدام قوائم المشاهدة",
"go_to_settings": "Go to Settings", "go_to_settings": "الذهاب إلى الإعدادات",
"add_to_watchlist": "Add to Watchlist", "add_to_watchlist": "إضافة إلى قائمة المشاهدة",
"remove_from_watchlist": "Remove from Watchlist", "remove_from_watchlist": "إزالة من قائمة المشاهدة",
"select_watchlist": "Select Watchlist", "select_watchlist": "تحديد قائمة المشاهدة",
"create_new": "Create New Watchlist", "create_new": "إنشاء قائمة مشاهدة جديدة",
"item": "item", "item": "عنصر",
"items": "items", "items": "عناصر",
"public": "Public", "public": "عامة",
"private": "Private", "private": "خاصة",
"you": "You", "you": "أنت",
"by_owner": "By another user", "by_owner": "بواسطة مستخدم آخر",
"not_found": "Watchlist not found", "not_found": "قائمة المشاهدة غير موجودة",
"delete_confirm_title": "Delete Watchlist", "delete_confirm_title": "حذف قائمة المشاهدة",
"delete_confirm_message": "Are you sure you want to delete \"{{name}}\"? This action cannot be undone.", "delete_confirm_message": "هل أنت متأكد من رغبتك في حذف \"{{name}}\"؟ لا يمكن التراجع عن هذا الإجراء.",
"remove_item_title": "Remove from Watchlist", "remove_item_title": "إزالة من قائمة المشاهدة",
"remove_item_message": "Remove \"{{name}}\" from this watchlist?", "remove_item_message": "إزالة \"{{name}}\" من قائمة المشاهدة هذه؟",
"loading": "Loading watchlists...", "loading": "تحميل قوائم المشاهدة...",
"no_compatible_watchlists": "No compatible watchlists", "no_compatible_watchlists": "لا توجد قوائم مشاهدة متوافقة",
"create_one_first": "Create a watchlist that accepts this content type" "create_one_first": "إنشاء قائمة مشاهدة تقبل نوع المحتوى هذا"
}, },
"playback_speed": { "playback_speed": {
"title": "Playback Speed", "title": "سرعة التشغيل",
"apply_to": "Apply To", "apply_to": "تطبيق على",
"speed": "Speed", "speed": "السرعة",
"scope": { "scope": {
"media": "This media only", "media": "الوسائط هذه فقط",
"show": "This show", "show": "هذا المسلسل",
"all": "All media (default)" "all": "جميع الوسائط (الافتراضي)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Error", "error_title": "Error",
"login_title": "Inicia sessió", "login_title": "Inicia sessió",
"login_to_title": "Inicia sessió a", "login_to_title": "Inicia sessió a",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Nom d'usuari", "username_placeholder": "Nom d'usuari",
"password_placeholder": "Contrasenya", "password_placeholder": "Contrasenya",
"login_button": "Inicia sessió", "login_button": "Inicia sessió",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} accounts",
"select_account": "Select Account", "select_account": "Select Account",
"add_account": "Add Account", "add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "This will remove the saved credentials for {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "Save Account",
@@ -86,6 +95,7 @@
"oops": "Oops!", "oops": "Oops!",
"error_message": "Alguna cosa ha anat malament.\nTanqueu la sessió i torneu-la a iniciar.", "error_message": "Alguna cosa ha anat malament.\nTanqueu la sessió i torneu-la a iniciar.",
"continue_watching": "Continua veient", "continue_watching": "Continua veient",
"continue": "Continue",
"next_up": "A continuació", "next_up": "A continuació",
"continue_and_next_up": "Continue & Next Up", "continue_and_next_up": "Continue & Next Up",
"recently_added_in": "Afegit recentment a {{libraryName}}", "recently_added_in": "Afegit recentment a {{libraryName}}",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Configuració", "settings_title": "Configuració",
"log_out_button": "Tanca sessió", "log_out_button": "Tanca sessió",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Categories" "title": "Categories"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Appearance", "title": "Appearance",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up", "merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button" "hide_remote_session_button": "Hide Remote Session Button",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "Network",
@@ -174,6 +199,22 @@
"rewind_length": "Durada del rebobinat", "rewind_length": "Durada del rebobinat",
"seconds_unit": "s" "seconds_unit": "s"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Gesture Controls", "gesture_controls_title": "Gesture Controls",
"horizontal_swipe_skip": "Horizontal Swipe to Skip", "horizontal_swipe_skip": "Horizontal Swipe to Skip",
@@ -256,7 +297,23 @@
"subtitle_font": "Subtitle Font", "subtitle_font": "Subtitle Font",
"ksplayer_title": "KSPlayer Settings", "ksplayer_title": "KSPlayer Settings",
"hardware_decode": "Hardware Decoding", "hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues." "hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "VLC Subtitle Settings",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Music cache cleared", "music_cache_cleared": "Music cache cleared",
"delete_all_downloaded_songs": "Delete All Downloaded Songs", "delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded", "downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "Downloaded songs deleted",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Intro", "title": "Intro",
@@ -430,6 +493,21 @@
"error_deleting_files": "Error en suprimir fitxers", "error_deleting_files": "Error en suprimir fitxers",
"background_downloads_enabled": "Descàrregues en segon pla activades", "background_downloads_enabled": "Descàrregues en segon pla activades",
"background_downloads_disabled": "Descàrregues en segon pla desactivades" "background_downloads_disabled": "Descàrregues en segon pla desactivades"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "L'actualització nova requereix que el contingut es torni a descarregar. Suprimiu tot el contingut descarregat i torneu-ho a provar.", "new_app_version_requires_re_download_description": "L'actualització nova requereix que el contingut es torni a descarregar. Suprimiu tot el contingut descarregat i torneu-ho a provar.",
"back": "Enrere", "back": "Enrere",
"delete": "Suprimeix", "delete": "Suprimeix",
"delete_download": "Delete Download",
"something_went_wrong": "Alguna cosa ha anat malament", "something_went_wrong": "Alguna cosa ha anat malament",
"could_not_get_stream_url_from_jellyfin": "No s'ha pogut obtenir l'URL del flux de Jellyfin", "could_not_get_stream_url_from_jellyfin": "No s'ha pogut obtenir l'URL del flux de Jellyfin",
"eta": "ETA {{eta}}", "eta": "ETA {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Select", "select": "Select",
"no_trailer_available": "No trailer available", "no_trailer_available": "No trailer available",
"video": "Vídeo", "video": "Vídeo",
"audio": "Àudio", "audio": "Àudio",
"subtitle": "Subtítols", "subtitle": "Subtítols",
"play": "Play", "play": "Play",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "None", "none": "None",
"track": "Track", "track": "Track",
"cancel": "Cancel", "cancel": "Cancel",
"stop": "Stop",
"delete": "Delete", "delete": "Delete",
"ok": "OK", "ok": "OK",
"remove": "Remove", "remove": "Remove",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"continue": "Continue", "continue": "Continue",
"verifying": "Verifying..." "verifying": "Verifying...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Cerca...", "search": "Cerca...",
@@ -556,6 +641,7 @@
"movies": "pel·lícules", "movies": "pel·lícules",
"series": "sèries", "series": "sèries",
"boxsets": "col·leccions", "boxsets": "col·leccions",
"playlists": "Playlists",
"items": "elements" "items": "elements"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Cartell", "poster": "Cartell",
"cover": "Coberta", "cover": "Coberta",
"show_titles": "Mostrar títols", "show_titles": "Mostrar títols",
"show_stats": "Mostrar estadístiques" "show_stats": "Mostrar estadístiques",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Gèneres", "genres": "Gèneres",
@@ -574,7 +661,11 @@
"sort_by": "Ordenar per", "sort_by": "Ordenar per",
"filter_by": "Filter By", "filter_by": "Filter By",
"sort_order": "Ordre", "sort_order": "Ordre",
"tags": "Etiquetes" "tags": "Etiquetes",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "No hi ha enllaços" "no_links": "No hi ha enllaços"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Error", "error": "Error",
"failed_to_get_stream_url": "No s'ha pogut obtenir l'URL del flux", "failed_to_get_stream_url": "No s'ha pogut obtenir l'URL del flux",
"an_error_occured_while_playing_the_video": "S'ha produït un error en reproduir el vídeo. Consulteu els registres a la configuració.", "an_error_occured_while_playing_the_video": "S'ha produït un error en reproduir el vídeo. Consulteu els registres a la configuració.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Do you want to play the downloaded file?", "downloaded_file_message": "Do you want to play the downloaded file?",
"downloaded_file_yes": "Yes", "downloaded_file_yes": "Yes",
"downloaded_file_no": "No", "downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel" "downloaded_file_cancel": "Cancel",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "A continuació", "next_up": "A continuació",
@@ -617,6 +738,11 @@
"series": "Sèries", "series": "Sèries",
"seasons": "Temporades", "seasons": "Temporades",
"season": "Temporada", "season": "Temporada",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "No hi ha episodis per a aquesta temporada", "no_episodes_for_this_season": "No hi ha episodis per a aquesta temporada",
"overview": "Descripció general", "overview": "Descripció general",
"more_with": "Més amb {{name}}", "more_with": "Més amb {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Media Options", "media_options": "Media Options",
"quality": "Qualitat", "quality": "Qualitat",
"audio": "Àudio", "audio": "Àudio",
"subtitles": "Subtítols", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Mostra més", "show_more": "Mostra més",
"show_less": "Mostra menys", "show_less": "Mostra menys",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Va aparèixer a", "appeared_in": "Va aparèixer a",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "No s'ha pogut carregar l'element", "could_not_load_item": "No s'ha pogut carregar l'element",
"none": "Cap", "none": "Cap",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Descarrega {{item_count}} elements", "download_x_item": "Descarrega {{item_count}} elements",
"download_unwatched_only": "Unwatched Only", "download_unwatched_only": "Unwatched Only",
"download_button": "Descarrega" "download_button": "Descarrega"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Següent", "next": "Següent",
@@ -652,7 +795,18 @@
"movies": "Pel·lícules", "movies": "Pel·lícules",
"sports": "Esports", "sports": "Esports",
"for_kids": "Infantil", "for_kids": "Infantil",
"news": "Notícies" "news": "Notícies",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Confirma", "confirm": "Confirma",
@@ -697,6 +851,12 @@
"decline": "Decline", "decline": "Decline",
"requested_by": "Requested by {{user}}", "requested_by": "Requested by {{user}}",
"unknown_user": "Unknown User", "unknown_user": "Unknown User",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "El servidor Jellyseerr no compleix els requisits mínims de versió! Actualitzeu-lo almenys a la versió 2.0.0", "jellyseer_does_not_meet_requirements": "El servidor Jellyseerr no compleix els requisits mínims de versió! Actualitzeu-lo almenys a la versió 2.0.0",
"jellyseerr_test_failed": "Ha fallat la prova de Jellyseerr. Torneu-ho a provar.", "jellyseerr_test_failed": "Ha fallat la prova de Jellyseerr. Torneu-ho a provar.",
@@ -716,7 +876,8 @@
"search": "Cercar", "search": "Cercar",
"library": "Biblioteca", "library": "Biblioteca",
"custom_links": "Enllaços personalitzats", "custom_links": "Enllaços personalitzats",
"favorites": "Preferits" "favorites": "Preferits",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Music", "title": "Music",
@@ -841,5 +1002,36 @@
"show": "This show", "show": "This show",
"all": "All media (default)" "all": "All media (default)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Chyba", "error_title": "Chyba",
"login_title": "Přihlásit se", "login_title": "Přihlásit se",
"login_to_title": "Přihlásit se do", "login_to_title": "Přihlásit se do",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Uživatelské jméno", "username_placeholder": "Uživatelské jméno",
"password_placeholder": "Heslo", "password_placeholder": "Heslo",
"login_button": "Přihlásit se", "login_button": "Přihlásit se",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} accounts",
"select_account": "Select Account", "select_account": "Select Account",
"add_account": "Add Account", "add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "This will remove the saved credentials for {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "Save Account",
@@ -86,6 +95,7 @@
"oops": "Jejda!", "oops": "Jejda!",
"error_message": "Něco se pokazilo.\nOdhlaste se a znovu se prosím.", "error_message": "Něco se pokazilo.\nOdhlaste se a znovu se prosím.",
"continue_watching": "Pokračovat ve sledování", "continue_watching": "Pokračovat ve sledování",
"continue": "Continue",
"next_up": "Další nahoru", "next_up": "Další nahoru",
"continue_and_next_up": "Continue & Next Up", "continue_and_next_up": "Continue & Next Up",
"recently_added_in": "Nedávno přidané v {{libraryName}}", "recently_added_in": "Nedávno přidané v {{libraryName}}",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Nastavení", "settings_title": "Nastavení",
"log_out_button": "Odhlásit se", "log_out_button": "Odhlásit se",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Categories" "title": "Categories"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Appearance", "title": "Appearance",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up", "merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button" "hide_remote_session_button": "Hide Remote Session Button",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "Network",
@@ -174,6 +199,22 @@
"rewind_length": "Délka zpětného větru", "rewind_length": "Délka zpětného větru",
"seconds_unit": "s" "seconds_unit": "s"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Ovládání gest", "gesture_controls_title": "Ovládání gest",
"horizontal_swipe_skip": "Horizontální přejetím přeskočit", "horizontal_swipe_skip": "Horizontální přejetím přeskočit",
@@ -256,7 +297,23 @@
"subtitle_font": "Subtitle Font", "subtitle_font": "Subtitle Font",
"ksplayer_title": "KSPlayer Settings", "ksplayer_title": "KSPlayer Settings",
"hardware_decode": "Hardware Decoding", "hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues." "hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "VLC Subtitle Settings",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Music cache cleared", "music_cache_cleared": "Music cache cleared",
"delete_all_downloaded_songs": "Delete All Downloaded Songs", "delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded", "downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "Downloaded songs deleted",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Intro", "title": "Intro",
@@ -430,6 +493,21 @@
"error_deleting_files": "Chyba při mazání souborů", "error_deleting_files": "Chyba při mazání souborů",
"background_downloads_enabled": "Stahování na pozadí povoleno", "background_downloads_enabled": "Stahování na pozadí povoleno",
"background_downloads_disabled": "Stahování na pozadí zakázáno" "background_downloads_disabled": "Stahování na pozadí zakázáno"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "Nová aktualizace vyžaduje opětovné stažení obsahu. Odstraňte prosím veškerý stažený obsah a zkuste to znovu.", "new_app_version_requires_re_download_description": "Nová aktualizace vyžaduje opětovné stažení obsahu. Odstraňte prosím veškerý stažený obsah a zkuste to znovu.",
"back": "Zpět", "back": "Zpět",
"delete": "Vymazat", "delete": "Vymazat",
"delete_download": "Delete Download",
"something_went_wrong": "Něco se pokazilo", "something_went_wrong": "Něco se pokazilo",
"could_not_get_stream_url_from_jellyfin": "Nelze získat URL streamu z Jellyfin", "could_not_get_stream_url_from_jellyfin": "Nelze získat URL streamu z Jellyfin",
"eta": "ETA {{eta}}", "eta": "ETA {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Vybrat", "select": "Vybrat",
"no_trailer_available": "Přípojné vozidlo není k dispozici", "no_trailer_available": "Přípojné vozidlo není k dispozici",
"video": "Video", "video": "Video",
"audio": "Zvuk", "audio": "Zvuk",
"subtitle": "Podtitulek", "subtitle": "Podtitulek",
"play": "Hrát", "play": "Hrát",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "None", "none": "None",
"track": "Track", "track": "Track",
"cancel": "Cancel", "cancel": "Cancel",
"stop": "Stop",
"delete": "Delete", "delete": "Delete",
"ok": "OK", "ok": "OK",
"remove": "Remove", "remove": "Remove",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"continue": "Continue", "continue": "Continue",
"verifying": "Verifying..." "verifying": "Verifying...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Hledat...", "search": "Hledat...",
@@ -556,6 +641,7 @@
"movies": "Filmy", "movies": "Filmy",
"series": "Série", "series": "Série",
"boxsets": "Sada boxů", "boxsets": "Sada boxů",
"playlists": "Playlists",
"items": "Položky" "items": "Položky"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Plakát", "poster": "Plakát",
"cover": "Kryt", "cover": "Kryt",
"show_titles": "Zobrazit názvy", "show_titles": "Zobrazit názvy",
"show_stats": "Zobrazit statistiky" "show_stats": "Zobrazit statistiky",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Genres", "genres": "Genres",
@@ -574,7 +661,11 @@
"sort_by": "Seřadit podle", "sort_by": "Seřadit podle",
"filter_by": "Filter By", "filter_by": "Filter By",
"sort_order": "Řazení", "sort_order": "Řazení",
"tags": "Štítky" "tags": "Štítky",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "Žádné odkazy" "no_links": "Žádné odkazy"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Chyba", "error": "Chyba",
"failed_to_get_stream_url": "Nepodařilo se získat URL streamu", "failed_to_get_stream_url": "Nepodařilo se získat URL streamu",
"an_error_occured_while_playing_the_video": "Při přehrávání videa došlo k chybě. Zkontrolujte logy v nastavení.", "an_error_occured_while_playing_the_video": "Při přehrávání videa došlo k chybě. Zkontrolujte logy v nastavení.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Do you want to play the downloaded file?", "downloaded_file_message": "Do you want to play the downloaded file?",
"downloaded_file_yes": "Yes", "downloaded_file_yes": "Yes",
"downloaded_file_no": "No", "downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel" "downloaded_file_cancel": "Cancel",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "Další nahoru", "next_up": "Další nahoru",
@@ -617,6 +738,11 @@
"series": "Série", "series": "Série",
"seasons": "Série", "seasons": "Série",
"season": "Sezóna", "season": "Sezóna",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "Žádné epizody pro tuto sezónu", "no_episodes_for_this_season": "Žádné epizody pro tuto sezónu",
"overview": "Přehled", "overview": "Přehled",
"more_with": "Více s {{name}}", "more_with": "Více s {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Media Options", "media_options": "Media Options",
"quality": "Kvalita", "quality": "Kvalita",
"audio": "Zvuk", "audio": "Zvuk",
"subtitles": "Podtitulek", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Zobrazit více", "show_more": "Zobrazit více",
"show_less": "Zobrazit méně", "show_less": "Zobrazit méně",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Zobrazeno v", "appeared_in": "Zobrazeno v",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Nelze načíst položku", "could_not_load_item": "Nelze načíst položku",
"none": "Nic", "none": "Nic",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Stáhnout položky {{item_count}}", "download_x_item": "Stáhnout položky {{item_count}}",
"download_unwatched_only": "Pouze nezhlédnuté", "download_unwatched_only": "Pouze nezhlédnuté",
"download_button": "Stáhnout" "download_button": "Stáhnout"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Další", "next": "Další",
@@ -652,7 +795,18 @@
"movies": "Filmy", "movies": "Filmy",
"sports": "Sporty", "sports": "Sporty",
"for_kids": "Pro děti", "for_kids": "Pro děti",
"news": "Novinky" "news": "Novinky",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Potvrdit", "confirm": "Potvrdit",
@@ -697,6 +851,12 @@
"decline": "Decline", "decline": "Decline",
"requested_by": "Requested by {{user}}", "requested_by": "Requested by {{user}}",
"unknown_user": "Unknown User", "unknown_user": "Unknown User",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Seerr server nesplňuje minimální požadavky na verzi! Aktualizujte prosím alespoň na 2.0.0", "jellyseer_does_not_meet_requirements": "Seerr server nesplňuje minimální požadavky na verzi! Aktualizujte prosím alespoň na 2.0.0",
"jellyseerr_test_failed": "Seerr test se nezdařil. Zkuste to prosím znovu.", "jellyseerr_test_failed": "Seerr test se nezdařil. Zkuste to prosím znovu.",
@@ -716,7 +876,8 @@
"search": "Hledat", "search": "Hledat",
"library": "Knihovna", "library": "Knihovna",
"custom_links": "Vlastní odkazy", "custom_links": "Vlastní odkazy",
"favorites": "Oblíbené" "favorites": "Oblíbené",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Music", "title": "Music",
@@ -841,5 +1002,36 @@
"show": "This show", "show": "This show",
"all": "All media (default)" "all": "All media (default)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Fejl", "error_title": "Fejl",
"login_title": "Log ind", "login_title": "Log ind",
"login_to_title": "Log ind på", "login_to_title": "Log ind på",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Brugernavn", "username_placeholder": "Brugernavn",
"password_placeholder": "Adgangskode", "password_placeholder": "Adgangskode",
"login_button": "Log ind", "login_button": "Log ind",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} accounts",
"select_account": "Select Account", "select_account": "Select Account",
"add_account": "Add Account", "add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "This will remove the saved credentials for {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "Save Account",
@@ -86,6 +95,7 @@
"oops": "Ups!", "oops": "Ups!",
"error_message": "Noget gik galt.\nLog venligst ud og ind igen.", "error_message": "Noget gik galt.\nLog venligst ud og ind igen.",
"continue_watching": "Fortsæt med at se", "continue_watching": "Fortsæt med at se",
"continue": "Continue",
"next_up": "Næste", "next_up": "Næste",
"continue_and_next_up": "Continue & Next Up", "continue_and_next_up": "Continue & Next Up",
"recently_added_in": "Senest tilføjet i {{libraryName}}", "recently_added_in": "Senest tilføjet i {{libraryName}}",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Indstillinger", "settings_title": "Indstillinger",
"log_out_button": "Log ud", "log_out_button": "Log ud",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Categories" "title": "Categories"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Appearance", "title": "Appearance",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up", "merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button" "hide_remote_session_button": "Hide Remote Session Button",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "Network",
@@ -174,6 +199,22 @@
"rewind_length": "Spol tilbage længde", "rewind_length": "Spol tilbage længde",
"seconds_unit": "s" "seconds_unit": "s"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Bevægelsesstyring", "gesture_controls_title": "Bevægelsesstyring",
"horizontal_swipe_skip": "Vandret Stryg for at springe over", "horizontal_swipe_skip": "Vandret Stryg for at springe over",
@@ -256,7 +297,23 @@
"subtitle_font": "Subtitle Font", "subtitle_font": "Subtitle Font",
"ksplayer_title": "KSPlayer Settings", "ksplayer_title": "KSPlayer Settings",
"hardware_decode": "Hardware Decoding", "hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues." "hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "VLC Subtitle Settings",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Music cache cleared", "music_cache_cleared": "Music cache cleared",
"delete_all_downloaded_songs": "Delete All Downloaded Songs", "delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded", "downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "Downloaded songs deleted",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Intro", "title": "Intro",
@@ -430,6 +493,21 @@
"error_deleting_files": "Fejl ved sletning af filer", "error_deleting_files": "Fejl ved sletning af filer",
"background_downloads_enabled": "Baggrundsdownloads aktiveret", "background_downloads_enabled": "Baggrundsdownloads aktiveret",
"background_downloads_disabled": "Baggrundsdownloads deaktiveret" "background_downloads_disabled": "Baggrundsdownloads deaktiveret"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "Den nye opdatering kræver, at indhold downloades igen. Fjern venligst alt downloadet indhold og prøv igen.", "new_app_version_requires_re_download_description": "Den nye opdatering kræver, at indhold downloades igen. Fjern venligst alt downloadet indhold og prøv igen.",
"back": "Tilbage", "back": "Tilbage",
"delete": "Slet", "delete": "Slet",
"delete_download": "Delete Download",
"something_went_wrong": "Noget gik galt", "something_went_wrong": "Noget gik galt",
"could_not_get_stream_url_from_jellyfin": "Kunne ikke hente stream URL'en fra Jellyfin", "could_not_get_stream_url_from_jellyfin": "Kunne ikke hente stream URL'en fra Jellyfin",
"eta": "ETA {{eta}}", "eta": "ETA {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Vælg", "select": "Vælg",
"no_trailer_available": "Intet påhængskøretøj tilgængeligt", "no_trailer_available": "Intet påhængskøretøj tilgængeligt",
"video": "Video", "video": "Video",
"audio": "Lyd", "audio": "Lyd",
"subtitle": "Undertekster", "subtitle": "Undertekster",
"play": "Afspil", "play": "Afspil",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "None", "none": "None",
"track": "Track", "track": "Track",
"cancel": "Cancel", "cancel": "Cancel",
"stop": "Stop",
"delete": "Delete", "delete": "Delete",
"ok": "OK", "ok": "OK",
"remove": "Remove", "remove": "Remove",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"continue": "Continue", "continue": "Continue",
"verifying": "Verifying..." "verifying": "Verifying...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Søg...", "search": "Søg...",
@@ -556,6 +641,7 @@
"movies": "film", "movies": "film",
"series": "serier", "series": "serier",
"boxsets": "box sæt", "boxsets": "box sæt",
"playlists": "Playlists",
"items": "elementer" "items": "elementer"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Plakat", "poster": "Plakat",
"cover": "Omslag", "cover": "Omslag",
"show_titles": "Vis titler", "show_titles": "Vis titler",
"show_stats": "Vis statistik" "show_stats": "Vis statistik",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Genrer", "genres": "Genrer",
@@ -574,7 +661,11 @@
"sort_by": "Sortér efter", "sort_by": "Sortér efter",
"filter_by": "Filter By", "filter_by": "Filter By",
"sort_order": "Sorteringsrækkefølge", "sort_order": "Sorteringsrækkefølge",
"tags": "Mærker" "tags": "Mærker",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "Ingen links" "no_links": "Ingen links"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Fejl", "error": "Fejl",
"failed_to_get_stream_url": "Kunne ikke hente stream URL'en", "failed_to_get_stream_url": "Kunne ikke hente stream URL'en",
"an_error_occured_while_playing_the_video": "Der opstod en fejl under afspilning af videoen. Tjek logfilerne i indstillinger.", "an_error_occured_while_playing_the_video": "Der opstod en fejl under afspilning af videoen. Tjek logfilerne i indstillinger.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Do you want to play the downloaded file?", "downloaded_file_message": "Do you want to play the downloaded file?",
"downloaded_file_yes": "Yes", "downloaded_file_yes": "Yes",
"downloaded_file_no": "No", "downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel" "downloaded_file_cancel": "Cancel",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "Næste", "next_up": "Næste",
@@ -617,6 +738,11 @@
"series": "Serier", "series": "Serier",
"seasons": "Sæsoner", "seasons": "Sæsoner",
"season": "Sæson", "season": "Sæson",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "Ingen episoder for denne sæson", "no_episodes_for_this_season": "Ingen episoder for denne sæson",
"overview": "Oversigt", "overview": "Oversigt",
"more_with": "Mere med {{name}}", "more_with": "Mere med {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Media Options", "media_options": "Media Options",
"quality": "Kvalitet", "quality": "Kvalitet",
"audio": "Lyd", "audio": "Lyd",
"subtitles": "Undertekster", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Vis mere", "show_more": "Vis mere",
"show_less": "Vis mindre", "show_less": "Vis mindre",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Medvirket i", "appeared_in": "Medvirket i",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Kunne ikke indlæse elementet", "could_not_load_item": "Kunne ikke indlæse elementet",
"none": "Ingen", "none": "Ingen",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Download {{item_count}} elementer", "download_x_item": "Download {{item_count}} elementer",
"download_unwatched_only": "Kun Usete", "download_unwatched_only": "Kun Usete",
"download_button": "Hent" "download_button": "Hent"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Næste", "next": "Næste",
@@ -652,7 +795,18 @@
"movies": "Film", "movies": "Film",
"sports": "Sport", "sports": "Sport",
"for_kids": "For børn", "for_kids": "For børn",
"news": "Nyheder" "news": "Nyheder",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Bekræft", "confirm": "Bekræft",
@@ -697,6 +851,12 @@
"decline": "Decline", "decline": "Decline",
"requested_by": "Requested by {{user}}", "requested_by": "Requested by {{user}}",
"unknown_user": "Unknown User", "unknown_user": "Unknown User",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Jellyseerr serveren opfylder ikke minimumskravene! Opdater venligst til mindst 2.0.0", "jellyseer_does_not_meet_requirements": "Jellyseerr serveren opfylder ikke minimumskravene! Opdater venligst til mindst 2.0.0",
"jellyseerr_test_failed": "Jellyseerr test mislykkedes. Prøv venligst igen.", "jellyseerr_test_failed": "Jellyseerr test mislykkedes. Prøv venligst igen.",
@@ -716,7 +876,8 @@
"search": "Søg", "search": "Søg",
"library": "Bibliotek", "library": "Bibliotek",
"custom_links": "Tilpassede links", "custom_links": "Tilpassede links",
"favorites": "Favoritter" "favorites": "Favoritter",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Music", "title": "Music",
@@ -841,5 +1002,36 @@
"show": "This show", "show": "This show",
"all": "All media (default)" "all": "All media (default)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Fehler", "error_title": "Fehler",
"login_title": "Anmelden", "login_title": "Anmelden",
"login_to_title": "Anmelden bei", "login_to_title": "Anmelden bei",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Benutzername", "username_placeholder": "Benutzername",
"password_placeholder": "Passwort", "password_placeholder": "Passwort",
"login_button": "Anmelden", "login_button": "Anmelden",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} Konten", "accounts_count": "{{count}} Konten",
"select_account": "Konto auswählen", "select_account": "Konto auswählen",
"add_account": "Konto hinzufügen", "add_account": "Konto hinzufügen",
"remove_account_description": "Hiermit werden die gespeicherten Zugangsdaten für {{username}} entfernt." "remove_account_description": "Hiermit werden die gespeicherten Zugangsdaten für {{username}} entfernt.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Konto speichern", "title": "Konto speichern",
@@ -86,6 +95,7 @@
"oops": "Ups!", "oops": "Ups!",
"error_message": "Etwas ist schiefgelaufen.\nBitte melde dich ab und wieder an.", "error_message": "Etwas ist schiefgelaufen.\nBitte melde dich ab und wieder an.",
"continue_watching": "Weiterschauen", "continue_watching": "Weiterschauen",
"continue": "Continue",
"next_up": "Als nächstes", "next_up": "Als nächstes",
"continue_and_next_up": "\"Weiterschauen\" und \"Als Nächstes\"", "continue_and_next_up": "\"Weiterschauen\" und \"Als Nächstes\"",
"recently_added_in": "Kürzlich hinzugefügt in {{libraryName}}", "recently_added_in": "Kürzlich hinzugefügt in {{libraryName}}",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Einstellungen", "settings_title": "Einstellungen",
"log_out_button": "Abmelden", "log_out_button": "Abmelden",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Kategorien" "title": "Kategorien"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Aussehen", "title": "Aussehen",
"merge_next_up_continue_watching": "\"Weiterschauen\" und \"Als Nächstes\" kombinieren", "merge_next_up_continue_watching": "\"Weiterschauen\" und \"Als Nächstes\" kombinieren",
"hide_remote_session_button": "Button für Remote-Sitzung ausblenden" "hide_remote_session_button": "Button für Remote-Sitzung ausblenden",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Netzwerk", "title": "Netzwerk",
@@ -174,6 +199,22 @@
"rewind_length": "Rückspullänge", "rewind_length": "Rückspullänge",
"seconds_unit": "s" "seconds_unit": "s"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Gestensteuerung", "gesture_controls_title": "Gestensteuerung",
"horizontal_swipe_skip": "Horizontal Wischen zum Überspringen", "horizontal_swipe_skip": "Horizontal Wischen zum Überspringen",
@@ -256,7 +297,23 @@
"subtitle_font": "Untertitel-Schriftart", "subtitle_font": "Untertitel-Schriftart",
"ksplayer_title": "KSPlayer Einstellungen", "ksplayer_title": "KSPlayer Einstellungen",
"hardware_decode": "Hardware Decoding", "hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Hardwarebeschleunigung für Video Decoding verwenden. Deaktivieren wenn Wiedergabeprobleme auftreten." "hardware_decode_description": "Hardwarebeschleunigung für Video Decoding verwenden. Deaktivieren wenn Wiedergabeprobleme auftreten.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Untertitel-Einstellungen", "title": "VLC Untertitel-Einstellungen",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Musik-Cache geleert", "music_cache_cleared": "Musik-Cache geleert",
"delete_all_downloaded_songs": "Alle heruntergeladenen Titel löschen", "delete_all_downloaded_songs": "Alle heruntergeladenen Titel löschen",
"downloaded_songs_size": "{{size}} heruntergeladen", "downloaded_songs_size": "{{size}} heruntergeladen",
"downloaded_songs_deleted": "Heruntergeladene Titel gelöscht" "downloaded_songs_deleted": "Heruntergeladene Titel gelöscht",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Einführung", "title": "Einführung",
@@ -430,6 +493,21 @@
"error_deleting_files": "Fehler beim Löschen von Dateien", "error_deleting_files": "Fehler beim Löschen von Dateien",
"background_downloads_enabled": "Hintergrunddownloads aktiviert", "background_downloads_enabled": "Hintergrunddownloads aktiviert",
"background_downloads_disabled": "Hintergrunddownloads deaktiviert" "background_downloads_disabled": "Hintergrunddownloads deaktiviert"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "Die neue App-Version erfordert das erneute Herunterladen von Filmen und Serien. Bitte lösche alle heruntergeladenen Elemente und starte den Download erneut.", "new_app_version_requires_re_download_description": "Die neue App-Version erfordert das erneute Herunterladen von Filmen und Serien. Bitte lösche alle heruntergeladenen Elemente und starte den Download erneut.",
"back": "Zurück", "back": "Zurück",
"delete": "Löschen", "delete": "Löschen",
"delete_download": "Download löschen",
"something_went_wrong": "Etwas ist schiefgelaufen", "something_went_wrong": "Etwas ist schiefgelaufen",
"could_not_get_stream_url_from_jellyfin": "Konnte keine Stream-URL von Jellyfin erhalten", "could_not_get_stream_url_from_jellyfin": "Konnte keine Stream-URL von Jellyfin erhalten",
"eta": "ETA {{eta}}", "eta": "ETA {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Auswählen", "select": "Auswählen",
"no_trailer_available": "Kein Trailer verfügbar", "no_trailer_available": "Kein Trailer verfügbar",
"video": "Video", "video": "Video",
"audio": "Audio", "audio": "Audio",
"subtitle": "Untertitel", "subtitle": "Untertitel",
"play": "Abspielen", "play": "Abspielen",
"mark_as_played": "Als gesehen markieren",
"mark_as_not_played": "Als ungesehen markieren",
"none": "Keine", "none": "Keine",
"track": "Spur", "track": "Spur",
"cancel": "Abbrechen", "cancel": "Abbrechen",
"stop": "Stop",
"delete": "Löschen", "delete": "Löschen",
"ok": "OK", "ok": "OK",
"remove": "Entfernen", "remove": "Entfernen",
"next": "Weiter", "next": "Weiter",
"back": "Zurück", "back": "Zurück",
"continue": "Fortsetzen", "continue": "Fortsetzen",
"verifying": "Verifiziere..." "verifying": "Verifiziere...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Suchen...", "search": "Suchen...",
@@ -556,6 +641,7 @@
"movies": "Filme", "movies": "Filme",
"series": "Serien", "series": "Serien",
"boxsets": "Boxsets", "boxsets": "Boxsets",
"playlists": "Playlists",
"items": "Elemente" "items": "Elemente"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Poster", "poster": "Poster",
"cover": "Cover", "cover": "Cover",
"show_titles": "Titel anzeigen", "show_titles": "Titel anzeigen",
"show_stats": "Statistiken anzeigen" "show_stats": "Statistiken anzeigen",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Genres", "genres": "Genres",
@@ -574,7 +661,11 @@
"sort_by": "Sortieren nach", "sort_by": "Sortieren nach",
"filter_by": "Filtern nach", "filter_by": "Filtern nach",
"sort_order": "Sortierreihenfolge", "sort_order": "Sortierreihenfolge",
"tags": "Tags" "tags": "Tags",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "Keine Links" "no_links": "Keine Links"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Fehler", "error": "Fehler",
"failed_to_get_stream_url": "Fehler beim Abrufen der Stream-URL", "failed_to_get_stream_url": "Fehler beim Abrufen der Stream-URL",
"an_error_occured_while_playing_the_video": "Ein Fehler ist beim Abspielen des Videos aufgetreten. Logs in den Einstellungen überprüfen.", "an_error_occured_while_playing_the_video": "Ein Fehler ist beim Abspielen des Videos aufgetreten. Logs in den Einstellungen überprüfen.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Heruntergeladene Datei abspielen?", "downloaded_file_message": "Heruntergeladene Datei abspielen?",
"downloaded_file_yes": "Ja", "downloaded_file_yes": "Ja",
"downloaded_file_no": "Nein", "downloaded_file_no": "Nein",
"downloaded_file_cancel": "Abbrechen" "downloaded_file_cancel": "Abbrechen",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Endet um {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "Als Nächstes", "next_up": "Als Nächstes",
@@ -617,6 +738,11 @@
"series": "Serien", "series": "Serien",
"seasons": "Staffeln", "seasons": "Staffeln",
"season": "Staffel", "season": "Staffel",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "Keine Episoden für diese Staffel", "no_episodes_for_this_season": "Keine Episoden für diese Staffel",
"overview": "Überblick", "overview": "Überblick",
"more_with": "Mehr mit {{name}}", "more_with": "Mehr mit {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Medienoptionen", "media_options": "Medienoptionen",
"quality": "Qualität", "quality": "Qualität",
"audio": "Audio", "audio": "Audio",
"subtitles": "Untertitel", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Mehr anzeigen", "show_more": "Mehr anzeigen",
"show_less": "Weniger anzeigen", "show_less": "Weniger anzeigen",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Erschien in", "appeared_in": "Erschien in",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Konnte Element nicht laden", "could_not_load_item": "Konnte Element nicht laden",
"none": "Keine", "none": "Keine",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "{{item_count}} Elemente herunterladen", "download_x_item": "{{item_count}} Elemente herunterladen",
"download_unwatched_only": "Nur Ungesehene", "download_unwatched_only": "Nur Ungesehene",
"download_button": "Herunterladen" "download_button": "Herunterladen"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Nächste", "next": "Nächste",
@@ -652,7 +795,18 @@
"movies": "Filme", "movies": "Filme",
"sports": "Sport", "sports": "Sport",
"for_kids": "Für Kinder", "for_kids": "Für Kinder",
"news": "Nachrichten" "news": "Nachrichten",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Bestätigen", "confirm": "Bestätigen",
@@ -697,6 +851,12 @@
"decline": "Ablehnen", "decline": "Ablehnen",
"requested_by": "Angefragt von {{user}}", "requested_by": "Angefragt von {{user}}",
"unknown_user": "Unbekannter Nutzer", "unknown_user": "Unbekannter Nutzer",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Seerr-Server erfüllt nicht die minimalen Versionsanforderungen. Bitte den Seerr-Server auf mindestens 2.0.0 aktualisieren.", "jellyseer_does_not_meet_requirements": "Seerr-Server erfüllt nicht die minimalen Versionsanforderungen. Bitte den Seerr-Server auf mindestens 2.0.0 aktualisieren.",
"jellyseerr_test_failed": "Seerr-Test fehlgeschlagen. Bitte erneut versuchen.", "jellyseerr_test_failed": "Seerr-Test fehlgeschlagen. Bitte erneut versuchen.",
@@ -716,7 +876,8 @@
"search": "Suche", "search": "Suche",
"library": "Bibliothek", "library": "Bibliothek",
"custom_links": "Links", "custom_links": "Links",
"favorites": "Favoriten" "favorites": "Favoriten",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Musik", "title": "Musik",
@@ -841,5 +1002,36 @@
"show": "Nur diese Serie", "show": "Nur diese Serie",
"all": "Alle (Standard)" "all": "Alle (Standard)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Σφάλμα", "error_title": "Σφάλμα",
"login_title": "Σύνδεση", "login_title": "Σύνδεση",
"login_to_title": "Συνδεθείτε στο", "login_to_title": "Συνδεθείτε στο",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Όνομα Χρήστη", "username_placeholder": "Όνομα Χρήστη",
"password_placeholder": "Κωδικός", "password_placeholder": "Κωδικός",
"login_button": "Σύνδεση", "login_button": "Σύνδεση",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} accounts",
"select_account": "Select Account", "select_account": "Select Account",
"add_account": "Add Account", "add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "This will remove the saved credentials for {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "Save Account",
@@ -86,6 +95,7 @@
"oops": "Ωχ!", "oops": "Ωχ!",
"error_message": "Something went wrong.\nPlease log out and in again.", "error_message": "Something went wrong.\nPlease log out and in again.",
"continue_watching": "Συνέχεια Παρακολούθησης", "continue_watching": "Συνέχεια Παρακολούθησης",
"continue": "Continue",
"next_up": "Επόμενο Επάνω", "next_up": "Επόμενο Επάνω",
"continue_and_next_up": "Continue & Next Up", "continue_and_next_up": "Continue & Next Up",
"recently_added_in": "Προστέθηκε πρόσφατα στο {{libraryName}}", "recently_added_in": "Προστέθηκε πρόσφατα στο {{libraryName}}",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Ρυθμίσεις", "settings_title": "Ρυθμίσεις",
"log_out_button": "Αποσύνδεση", "log_out_button": "Αποσύνδεση",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Categories" "title": "Categories"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Appearance", "title": "Appearance",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up", "merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button" "hide_remote_session_button": "Hide Remote Session Button",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "Network",
@@ -174,6 +199,22 @@
"rewind_length": "Επαναφορά Μήκους", "rewind_length": "Επαναφορά Μήκους",
"seconds_unit": "ίνα" "seconds_unit": "ίνα"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Έλεγχοι Χειρονομιών", "gesture_controls_title": "Έλεγχοι Χειρονομιών",
"horizontal_swipe_skip": "Οριζόντια σάρωση για παράλειψη", "horizontal_swipe_skip": "Οριζόντια σάρωση για παράλειψη",
@@ -256,7 +297,23 @@
"subtitle_font": "Subtitle Font", "subtitle_font": "Subtitle Font",
"ksplayer_title": "KSPlayer Settings", "ksplayer_title": "KSPlayer Settings",
"hardware_decode": "Hardware Decoding", "hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues." "hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "VLC Subtitle Settings",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Music cache cleared", "music_cache_cleared": "Music cache cleared",
"delete_all_downloaded_songs": "Delete All Downloaded Songs", "delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded", "downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "Downloaded songs deleted",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Intro", "title": "Intro",
@@ -430,6 +493,21 @@
"error_deleting_files": "Σφάλμα Διαγραφής Αρχείων", "error_deleting_files": "Σφάλμα Διαγραφής Αρχείων",
"background_downloads_enabled": "Οι λήψεις στο παρασκήνιο ενεργοποιήθηκαν", "background_downloads_enabled": "Οι λήψεις στο παρασκήνιο ενεργοποιήθηκαν",
"background_downloads_disabled": "Οι λήψεις παρασκηνίου απενεργοποιήθηκαν" "background_downloads_disabled": "Οι λήψεις παρασκηνίου απενεργοποιήθηκαν"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "Η νέα ενημέρωση απαιτεί λήψη περιεχομένου ξανά. Καταργήστε όλο το κατεβασμένο περιεχόμενο και προσπαθήστε ξανά.", "new_app_version_requires_re_download_description": "Η νέα ενημέρωση απαιτεί λήψη περιεχομένου ξανά. Καταργήστε όλο το κατεβασμένο περιεχόμενο και προσπαθήστε ξανά.",
"back": "Πίσω", "back": "Πίσω",
"delete": "Διαγραφή", "delete": "Διαγραφή",
"delete_download": "Delete Download",
"something_went_wrong": "Κάτι Πήγε Λάθος", "something_went_wrong": "Κάτι Πήγε Λάθος",
"could_not_get_stream_url_from_jellyfin": "Αδυναμία λήψης του URL ροής από το Jellyfin", "could_not_get_stream_url_from_jellyfin": "Αδυναμία λήψης του URL ροής από το Jellyfin",
"eta": "ETA {{eta}}", "eta": "ETA {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Επιλογή", "select": "Επιλογή",
"no_trailer_available": "Δεν υπάρχει διαθέσιμο ρυμουλκούμενο", "no_trailer_available": "Δεν υπάρχει διαθέσιμο ρυμουλκούμενο",
"video": "Βίντεο", "video": "Βίντεο",
"audio": "Ήχος", "audio": "Ήχος",
"subtitle": "Υπότιτλος", "subtitle": "Υπότιτλος",
"play": "Αναπαραγωγή", "play": "Αναπαραγωγή",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "None", "none": "None",
"track": "Track", "track": "Track",
"cancel": "Cancel", "cancel": "Cancel",
"stop": "Stop",
"delete": "Delete", "delete": "Delete",
"ok": "OK", "ok": "OK",
"remove": "Remove", "remove": "Remove",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"continue": "Continue", "continue": "Continue",
"verifying": "Verifying..." "verifying": "Verifying...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Αναζήτηση...", "search": "Αναζήτηση...",
@@ -556,6 +641,7 @@
"movies": "Ταινίες", "movies": "Ταινίες",
"series": "Σειρά", "series": "Σειρά",
"boxsets": "Σύνολα Πλαισίων", "boxsets": "Σύνολα Πλαισίων",
"playlists": "Playlists",
"items": "Στοιχεία" "items": "Στοιχεία"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Αφίσα", "poster": "Αφίσα",
"cover": "Εξώφυλλο", "cover": "Εξώφυλλο",
"show_titles": "Εμφάνιση Τίτλων", "show_titles": "Εμφάνιση Τίτλων",
"show_stats": "Εμφάνιση Στατιστικών" "show_stats": "Εμφάνιση Στατιστικών",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Genres", "genres": "Genres",
@@ -574,7 +661,11 @@
"sort_by": "Ταξινόμηση Κατά", "sort_by": "Ταξινόμηση Κατά",
"filter_by": "Filter By", "filter_by": "Filter By",
"sort_order": "Σειρά Ταξινόμησης", "sort_order": "Σειρά Ταξινόμησης",
"tags": "Ετικέτες" "tags": "Ετικέτες",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "Δεν Υπάρχουν Σύνδεσμοι" "no_links": "Δεν Υπάρχουν Σύνδεσμοι"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Σφάλμα", "error": "Σφάλμα",
"failed_to_get_stream_url": "Αποτυχία λήψης του URL ροής", "failed_to_get_stream_url": "Αποτυχία λήψης του URL ροής",
"an_error_occured_while_playing_the_video": "Παρουσιάστηκε σφάλμα κατά την αναπαραγωγή του βίντεο. Ελέγξτε τα αρχεία καταγραφής στις ρυθμίσεις.", "an_error_occured_while_playing_the_video": "Παρουσιάστηκε σφάλμα κατά την αναπαραγωγή του βίντεο. Ελέγξτε τα αρχεία καταγραφής στις ρυθμίσεις.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Do you want to play the downloaded file?", "downloaded_file_message": "Do you want to play the downloaded file?",
"downloaded_file_yes": "Yes", "downloaded_file_yes": "Yes",
"downloaded_file_no": "No", "downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel" "downloaded_file_cancel": "Cancel",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "Επόμενο Επάνω", "next_up": "Επόμενο Επάνω",
@@ -617,6 +738,11 @@
"series": "Σειρά", "series": "Σειρά",
"seasons": "Περίοδοι", "seasons": "Περίοδοι",
"season": "Σεζόν", "season": "Σεζόν",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "Δεν υπάρχουν επεισόδια για αυτή τη σεζόν", "no_episodes_for_this_season": "Δεν υπάρχουν επεισόδια για αυτή τη σεζόν",
"overview": "Επισκόπηση", "overview": "Επισκόπηση",
"more_with": "More with {{name}}", "more_with": "More with {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Media Options", "media_options": "Media Options",
"quality": "Ποιότητα", "quality": "Ποιότητα",
"audio": "Ήχος", "audio": "Ήχος",
"subtitles": "Υπότιτλος", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Εμφάνιση Περισσότερων", "show_more": "Εμφάνιση Περισσότερων",
"show_less": "Εμφάνιση Λιγότερων", "show_less": "Εμφάνιση Λιγότερων",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Εμφανίστηκε Σε", "appeared_in": "Εμφανίστηκε Σε",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Αδύνατη Η Φόρτωση Του Στοιχείου", "could_not_load_item": "Αδύνατη Η Φόρτωση Του Στοιχείου",
"none": "Κανένα", "none": "Κανένα",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Λήψη Αντικειμένων {{item_count}}", "download_x_item": "Λήψη Αντικειμένων {{item_count}}",
"download_unwatched_only": "Μόνο Χωρίς Παρακολούθηση", "download_unwatched_only": "Μόνο Χωρίς Παρακολούθηση",
"download_button": "Λήψη" "download_button": "Λήψη"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Επόμενο", "next": "Επόμενο",
@@ -652,7 +795,18 @@
"movies": "Ταινίες", "movies": "Ταινίες",
"sports": "Αθλητισμός", "sports": "Αθλητισμός",
"for_kids": "Για Παιδιά", "for_kids": "Για Παιδιά",
"news": "Νέα" "news": "Νέα",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Επιβεβαίωση", "confirm": "Επιβεβαίωση",
@@ -697,6 +851,12 @@
"decline": "Decline", "decline": "Decline",
"requested_by": "Requested by {{user}}", "requested_by": "Requested by {{user}}",
"unknown_user": "Unknown User", "unknown_user": "Unknown User",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Ο διακομιστής Seerr δεν πληροί τις ελάχιστες απαιτήσεις έκδοσης! Παρακαλούμε ενημερώστε τουλάχιστον σε 2.0.0", "jellyseer_does_not_meet_requirements": "Ο διακομιστής Seerr δεν πληροί τις ελάχιστες απαιτήσεις έκδοσης! Παρακαλούμε ενημερώστε τουλάχιστον σε 2.0.0",
"jellyseerr_test_failed": "Ο έλεγχος Seerr απέτυχε. Παρακαλώ προσπαθήστε ξανά.", "jellyseerr_test_failed": "Ο έλεγχος Seerr απέτυχε. Παρακαλώ προσπαθήστε ξανά.",
@@ -716,7 +876,8 @@
"search": "Αναζήτηση", "search": "Αναζήτηση",
"library": "Βιβλιοθήκη", "library": "Βιβλιοθήκη",
"custom_links": "Προσαρμοσμένοι Σύνδεσμοι", "custom_links": "Προσαρμοσμένοι Σύνδεσμοι",
"favorites": "Αγαπημένα" "favorites": "Αγαπημένα",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Music", "title": "Music",
@@ -841,5 +1002,36 @@
"show": "This show", "show": "This show",
"all": "All media (default)" "all": "All media (default)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -534,6 +534,7 @@
"new_app_version_requires_re_download_description": "The new update requires content to be downloaded again. Please remove all downloaded content and try again.", "new_app_version_requires_re_download_description": "The new update requires content to be downloaded again. Please remove all downloaded content and try again.",
"back": "Back", "back": "Back",
"delete": "Delete", "delete": "Delete",
"delete_download": "Delete Download",
"something_went_wrong": "Something Went Wrong", "something_went_wrong": "Something Went Wrong",
"could_not_get_stream_url_from_jellyfin": "Could not get the stream URL from Jellyfin", "could_not_get_stream_url_from_jellyfin": "Could not get the stream URL from Jellyfin",
"eta": "ETA {{eta}}", "eta": "ETA {{eta}}",
@@ -577,6 +578,8 @@
"audio": "Audio", "audio": "Audio",
"subtitle": "Subtitle", "subtitle": "Subtitle",
"play": "Play", "play": "Play",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "None", "none": "None",
"track": "Track", "track": "Track",
"cancel": "Cancel", "cancel": "Cancel",
@@ -649,7 +652,8 @@
"poster": "Poster", "poster": "Poster",
"cover": "Cover", "cover": "Cover",
"show_titles": "Show Titles", "show_titles": "Show Titles",
"show_stats": "Show Stats" "show_stats": "Show Stats",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Genres", "genres": "Genres",
@@ -679,6 +683,7 @@
}, },
"player": { "player": {
"live": "LIVE", "live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Error", "error": "Error",
"failed_to_get_stream_url": "Failed to get the stream URL", "failed_to_get_stream_url": "Failed to get the stream URL",
"an_error_occured_while_playing_the_video": "An error occurred while playing the video. Check logs in settings.", "an_error_occured_while_playing_the_video": "An error occurred while playing the video. Check logs in settings.",
@@ -698,7 +703,7 @@
"downloaded_file_no": "No", "downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel", "downloaded_file_cancel": "Cancel",
"swipe_down_settings": "Swipe down for settings", "swipe_down_settings": "Swipe down for settings",
"ends_at": "ends at", "ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles", "search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks", "subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download", "subtitle_search": "Search & Download",

View File

@@ -4,6 +4,9 @@
"error_title": "Error", "error_title": "Error",
"login_title": "Iniciar sesión", "login_title": "Iniciar sesión",
"login_to_title": "Iniciar sesión en", "login_to_title": "Iniciar sesión en",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Nombre de usuario", "username_placeholder": "Nombre de usuario",
"password_placeholder": "Contraseña", "password_placeholder": "Contraseña",
"login_button": "Iniciar sesión", "login_button": "Iniciar sesión",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} cuentas", "accounts_count": "{{count}} cuentas",
"select_account": "Seleccione una cuenta", "select_account": "Seleccione una cuenta",
"add_account": "Añadir cuenta", "add_account": "Añadir cuenta",
"remove_account_description": "Esto eliminará las credenciales guardadas para {{username}}." "remove_account_description": "Esto eliminará las credenciales guardadas para {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Guardar Cuenta", "title": "Guardar Cuenta",
@@ -86,6 +95,7 @@
"oops": "¡Vaya!", "oops": "¡Vaya!",
"error_message": "Algo ha salido mal.\nPor favor, cierra la sesión y vuelve a iniciar.", "error_message": "Algo ha salido mal.\nPor favor, cierra la sesión y vuelve a iniciar.",
"continue_watching": "Seguir viendo", "continue_watching": "Seguir viendo",
"continue": "Continue",
"next_up": "A continuación", "next_up": "A continuación",
"continue_and_next_up": "Continuar y siguiente", "continue_and_next_up": "Continuar y siguiente",
"recently_added_in": "Recientemente añadido en {{libraryName}}", "recently_added_in": "Recientemente añadido en {{libraryName}}",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Configuración", "settings_title": "Configuración",
"log_out_button": "Cerrar sesión", "log_out_button": "Cerrar sesión",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Categorías" "title": "Categorías"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Apariencia", "title": "Apariencia",
"merge_next_up_continue_watching": "Fusionar continuar viendo y siguiente", "merge_next_up_continue_watching": "Fusionar continuar viendo y siguiente",
"hide_remote_session_button": "Ocultar botón de sesión remota" "hide_remote_session_button": "Ocultar botón de sesión remota",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Cadena", "title": "Cadena",
@@ -174,6 +199,22 @@
"rewind_length": "Longitud de retroceso", "rewind_length": "Longitud de retroceso",
"seconds_unit": "s" "seconds_unit": "s"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Controles de gestos", "gesture_controls_title": "Controles de gestos",
"horizontal_swipe_skip": "Deslizar horizontal para omitir", "horizontal_swipe_skip": "Deslizar horizontal para omitir",
@@ -256,7 +297,23 @@
"subtitle_font": "Fuente de los subtítulos", "subtitle_font": "Fuente de los subtítulos",
"ksplayer_title": "Ajustes de KSPlayer", "ksplayer_title": "Ajustes de KSPlayer",
"hardware_decode": "Decodificación de hardware", "hardware_decode": "Decodificación de hardware",
"hardware_decode_description": "Utilizar la aceleración de hardware para la decodificación de vídeo. Deshabilite si experimenta problemas de reproducción." "hardware_decode_description": "Utilizar la aceleración de hardware para la decodificación de vídeo. Deshabilite si experimenta problemas de reproducción.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "Configuración de subtítulos VLC", "title": "Configuración de subtítulos VLC",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Caché de música eliminado", "music_cache_cleared": "Caché de música eliminado",
"delete_all_downloaded_songs": "Eliminar todas las descargas", "delete_all_downloaded_songs": "Eliminar todas las descargas",
"downloaded_songs_size": "{{tamaño}} descargado", "downloaded_songs_size": "{{tamaño}} descargado",
"downloaded_songs_deleted": "Canciones descargadas eliminadas" "downloaded_songs_deleted": "Canciones descargadas eliminadas",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Intro", "title": "Intro",
@@ -430,6 +493,21 @@
"error_deleting_files": "Error al eliminar archivos", "error_deleting_files": "Error al eliminar archivos",
"background_downloads_enabled": "Descargas en segundo plano habilitadas", "background_downloads_enabled": "Descargas en segundo plano habilitadas",
"background_downloads_disabled": "Descargas en segundo plano deshabilitadas" "background_downloads_disabled": "Descargas en segundo plano deshabilitadas"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "La nueva actualización requiere volver a descargar el contenido. Por favor, elimina todo el código descargado y vuélvelo a intentar.", "new_app_version_requires_re_download_description": "La nueva actualización requiere volver a descargar el contenido. Por favor, elimina todo el código descargado y vuélvelo a intentar.",
"back": "Atrás", "back": "Atrás",
"delete": "Borrar", "delete": "Borrar",
"delete_download": "Delete Download",
"something_went_wrong": "Algo ha salido mal", "something_went_wrong": "Algo ha salido mal",
"could_not_get_stream_url_from_jellyfin": "No se pudo obtener la URL del stream de Jellyfin", "could_not_get_stream_url_from_jellyfin": "No se pudo obtener la URL del stream de Jellyfin",
"eta": "{{eta}} restante", "eta": "{{eta}} restante",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Seleccionar", "select": "Seleccionar",
"no_trailer_available": "No hay tráiler disponible", "no_trailer_available": "No hay tráiler disponible",
"video": "Vídeo", "video": "Vídeo",
"audio": "Audio", "audio": "Audio",
"subtitle": "Subtítulos", "subtitle": "Subtítulos",
"play": "Jugar", "play": "Jugar",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "Nada", "none": "Nada",
"track": "Pista", "track": "Pista",
"cancel": "Cancelar", "cancel": "Cancelar",
"stop": "Stop",
"delete": "Borrar", "delete": "Borrar",
"ok": "Aceptar", "ok": "Aceptar",
"remove": "Eliminar", "remove": "Eliminar",
"next": "Siguiente", "next": "Siguiente",
"back": "Atrás", "back": "Atrás",
"continue": "Continuar", "continue": "Continuar",
"verifying": "Verificando..." "verifying": "Verificando...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Buscar...", "search": "Buscar...",
@@ -556,6 +641,7 @@
"movies": "Películas", "movies": "Películas",
"series": "Series", "series": "Series",
"boxsets": "Colecciones", "boxsets": "Colecciones",
"playlists": "Playlists",
"items": "Elementos" "items": "Elementos"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Póster", "poster": "Póster",
"cover": "Portada", "cover": "Portada",
"show_titles": "Mostrar títulos", "show_titles": "Mostrar títulos",
"show_stats": "Mostrar estadísticas" "show_stats": "Mostrar estadísticas",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Géneros", "genres": "Géneros",
@@ -574,7 +661,11 @@
"sort_by": "Ordenar por", "sort_by": "Ordenar por",
"filter_by": "Filtrar por", "filter_by": "Filtrar por",
"sort_order": "Ordenar", "sort_order": "Ordenar",
"tags": "Etiquetas" "tags": "Etiquetas",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "Sin enlaces" "no_links": "Sin enlaces"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Error", "error": "Error",
"failed_to_get_stream_url": "Error al obtener la URL del Steam", "failed_to_get_stream_url": "Error al obtener la URL del Steam",
"an_error_occured_while_playing_the_video": "Ha ocurrido un error al reproducir el vídeo. Comprueba los registros en la configuración.", "an_error_occured_while_playing_the_video": "Ha ocurrido un error al reproducir el vídeo. Comprueba los registros en la configuración.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "¿Quieres reproducir el archivo descargado?", "downloaded_file_message": "¿Quieres reproducir el archivo descargado?",
"downloaded_file_yes": "Sí", "downloaded_file_yes": "Sí",
"downloaded_file_no": "No", "downloaded_file_no": "No",
"downloaded_file_cancel": "Cancelar" "downloaded_file_cancel": "Cancelar",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "A continuación", "next_up": "A continuación",
@@ -617,6 +738,11 @@
"series": "Series", "series": "Series",
"seasons": "Temporadas", "seasons": "Temporadas",
"season": "Temporada", "season": "Temporada",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "No hay episodios para esta temporada", "no_episodes_for_this_season": "No hay episodios para esta temporada",
"overview": "Resumen", "overview": "Resumen",
"more_with": "Más con {{name}}", "more_with": "Más con {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Opciones de medios", "media_options": "Opciones de medios",
"quality": "Calidad", "quality": "Calidad",
"audio": "Audio", "audio": "Audio",
"subtitles": "Subtítulos", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Mostrar más", "show_more": "Mostrar más",
"show_less": "Mostrar menos", "show_less": "Mostrar menos",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Apareció en", "appeared_in": "Apareció en",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "No se pudo cargar el ítem", "could_not_load_item": "No se pudo cargar el ítem",
"none": "Ninguno", "none": "Ninguno",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Descargar {{item_count}} ítems", "download_x_item": "Descargar {{item_count}} ítems",
"download_unwatched_only": "No visto", "download_unwatched_only": "No visto",
"download_button": "Descargar" "download_button": "Descargar"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Siguiente", "next": "Siguiente",
@@ -652,7 +795,18 @@
"movies": "Películas", "movies": "Películas",
"sports": "Deportes", "sports": "Deportes",
"for_kids": "Para niños", "for_kids": "Para niños",
"news": "Noticias" "news": "Noticias",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Confirmar", "confirm": "Confirmar",
@@ -697,6 +851,12 @@
"decline": "Rechazar", "decline": "Rechazar",
"requested_by": "Solicitado por {{user}}", "requested_by": "Solicitado por {{user}}",
"unknown_user": "Usuario desconocido", "unknown_user": "Usuario desconocido",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "¡Jellyseer no cumple con los requisitos! Por favor, actualízalo al menos a la versión 2.0.0.", "jellyseer_does_not_meet_requirements": "¡Jellyseer no cumple con los requisitos! Por favor, actualízalo al menos a la versión 2.0.0.",
"jellyseerr_test_failed": "La prueba de Jellyseerr ha fallado. Por favor inténtalo de nuevo.", "jellyseerr_test_failed": "La prueba de Jellyseerr ha fallado. Por favor inténtalo de nuevo.",
@@ -716,7 +876,8 @@
"search": "Buscar", "search": "Buscar",
"library": "Bibliotecas", "library": "Bibliotecas",
"custom_links": "Enlaces personalizados", "custom_links": "Enlaces personalizados",
"favorites": "Favoritos" "favorites": "Favoritos",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Música", "title": "Música",
@@ -841,5 +1002,36 @@
"show": "Este programa", "show": "Este programa",
"all": "Todos los medios (por defecto)" "all": "Todos los medios (por defecto)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Virhe", "error_title": "Virhe",
"login_title": "Kirjaudu sisään", "login_title": "Kirjaudu sisään",
"login_to_title": "Kirjaudu sisään palveluun", "login_to_title": "Kirjaudu sisään palveluun",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Käyttäjätunnus", "username_placeholder": "Käyttäjätunnus",
"password_placeholder": "Salasana", "password_placeholder": "Salasana",
"login_button": "Kirjaudu sisään", "login_button": "Kirjaudu sisään",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} accounts",
"select_account": "Select Account", "select_account": "Select Account",
"add_account": "Add Account", "add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "This will remove the saved credentials for {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "Save Account",
@@ -86,6 +95,7 @@
"oops": "Ups!", "oops": "Ups!",
"error_message": "Jotain meni pieleen.\nKirjaudu ulos ja takaisin sisään.", "error_message": "Jotain meni pieleen.\nKirjaudu ulos ja takaisin sisään.",
"continue_watching": "Jatka katsomista", "continue_watching": "Jatka katsomista",
"continue": "Continue",
"next_up": "Seuraavaksi", "next_up": "Seuraavaksi",
"continue_and_next_up": "Continue & Next Up", "continue_and_next_up": "Continue & Next Up",
"recently_added_in": "Äskettäin lisätty {{libraryName}}-kirjastoon", "recently_added_in": "Äskettäin lisätty {{libraryName}}-kirjastoon",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Asetukset", "settings_title": "Asetukset",
"log_out_button": "Kirjaudu ulos", "log_out_button": "Kirjaudu ulos",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Kategoriat" "title": "Kategoriat"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Ulkoasu", "title": "Ulkoasu",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up", "merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button" "hide_remote_session_button": "Hide Remote Session Button",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "Network",
@@ -174,6 +199,22 @@
"rewind_length": "Taaksepäin hyppäämisen pituus", "rewind_length": "Taaksepäin hyppäämisen pituus",
"seconds_unit": "s" "seconds_unit": "s"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Ele Ohjaus", "gesture_controls_title": "Ele Ohjaus",
"horizontal_swipe_skip": "Ohita vaakatasossa pyyhkäisemällä", "horizontal_swipe_skip": "Ohita vaakatasossa pyyhkäisemällä",
@@ -256,7 +297,23 @@
"subtitle_font": "Subtitle Font", "subtitle_font": "Subtitle Font",
"ksplayer_title": "KSPlayer Settings", "ksplayer_title": "KSPlayer Settings",
"hardware_decode": "Hardware Decoding", "hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues." "hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "VLC Subtitle Settings",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Music cache cleared", "music_cache_cleared": "Music cache cleared",
"delete_all_downloaded_songs": "Delete All Downloaded Songs", "delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded", "downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "Downloaded songs deleted",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Esittely", "title": "Esittely",
@@ -430,6 +493,21 @@
"error_deleting_files": "Virhe tiedostojen poistamisessa", "error_deleting_files": "Virhe tiedostojen poistamisessa",
"background_downloads_enabled": "Taustalataukset käytössä", "background_downloads_enabled": "Taustalataukset käytössä",
"background_downloads_disabled": "Taustalataukset pois käytöstä" "background_downloads_disabled": "Taustalataukset pois käytöstä"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "Uusi päivitys vaatii sisällön lataamista uudelleen. Poista kaikki ladattu sisältö ja yritä uudelleen.", "new_app_version_requires_re_download_description": "Uusi päivitys vaatii sisällön lataamista uudelleen. Poista kaikki ladattu sisältö ja yritä uudelleen.",
"back": "Takaisin", "back": "Takaisin",
"delete": "Poista", "delete": "Poista",
"delete_download": "Delete Download",
"something_went_wrong": "Jotain meni pieleen", "something_went_wrong": "Jotain meni pieleen",
"could_not_get_stream_url_from_jellyfin": "Ei voitu saada suoratoiston URL:ia Jellyfinilta", "could_not_get_stream_url_from_jellyfin": "Ei voitu saada suoratoiston URL:ia Jellyfinilta",
"eta": "Arvio {{eta}}", "eta": "Arvio {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Valitse", "select": "Valitse",
"no_trailer_available": "Perävaunua ei saatavilla", "no_trailer_available": "Perävaunua ei saatavilla",
"video": "Video", "video": "Video",
"audio": "Ääni", "audio": "Ääni",
"subtitle": "Tekstitys", "subtitle": "Tekstitys",
"play": "Toista", "play": "Toista",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "Ei mitään", "none": "Ei mitään",
"track": "Track", "track": "Track",
"cancel": "Cancel", "cancel": "Cancel",
"stop": "Stop",
"delete": "Delete", "delete": "Delete",
"ok": "OK", "ok": "OK",
"remove": "Remove", "remove": "Remove",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"continue": "Continue", "continue": "Continue",
"verifying": "Verifying..." "verifying": "Verifying...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Haku...", "search": "Haku...",
@@ -556,6 +641,7 @@
"movies": "elokuvat", "movies": "elokuvat",
"series": "sarjat", "series": "sarjat",
"boxsets": "bokset", "boxsets": "bokset",
"playlists": "Playlists",
"items": "kohteet" "items": "kohteet"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Juliste", "poster": "Juliste",
"cover": "Kansi", "cover": "Kansi",
"show_titles": "Näytä otsikot", "show_titles": "Näytä otsikot",
"show_stats": "Näytä tilastot" "show_stats": "Näytä tilastot",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Genret", "genres": "Genret",
@@ -574,7 +661,11 @@
"sort_by": "Lajittele", "sort_by": "Lajittele",
"filter_by": "Filter By", "filter_by": "Filter By",
"sort_order": "Lajittelujärjestys", "sort_order": "Lajittelujärjestys",
"tags": "Tunnisteet" "tags": "Tunnisteet",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "Ei Linkkejä" "no_links": "Ei Linkkejä"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Virhe", "error": "Virhe",
"failed_to_get_stream_url": "Lähetyksen URL-osoitteen haku epäonnistui", "failed_to_get_stream_url": "Lähetyksen URL-osoitteen haku epäonnistui",
"an_error_occured_while_playing_the_video": "Videon toiston yhteydessä tapahtui virhe. Tarkista lokit asetuksista.", "an_error_occured_while_playing_the_video": "Videon toiston yhteydessä tapahtui virhe. Tarkista lokit asetuksista.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Haluatko toistaa ladatun tiedoston?", "downloaded_file_message": "Haluatko toistaa ladatun tiedoston?",
"downloaded_file_yes": "Kyllä", "downloaded_file_yes": "Kyllä",
"downloaded_file_no": "Ei", "downloaded_file_no": "Ei",
"downloaded_file_cancel": "Peruuta" "downloaded_file_cancel": "Peruuta",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "Seuraavaksi", "next_up": "Seuraavaksi",
@@ -617,6 +738,11 @@
"series": "Sarjat", "series": "Sarjat",
"seasons": "Kaudet", "seasons": "Kaudet",
"season": "Kausi", "season": "Kausi",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "Ei jaksoja tälle kaudelle", "no_episodes_for_this_season": "Ei jaksoja tälle kaudelle",
"overview": "Yleiskatsaus", "overview": "Yleiskatsaus",
"more_with": "Enemmän {{name}} kanssa", "more_with": "Enemmän {{name}} kanssa",
@@ -627,10 +753,21 @@
"media_options": "Media-asetukset", "media_options": "Media-asetukset",
"quality": "Laatu", "quality": "Laatu",
"audio": "Ääni", "audio": "Ääni",
"subtitles": "Tekstitys", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Näytä Lisää", "show_more": "Näytä Lisää",
"show_less": "Näytä Vähemmän", "show_less": "Näytä Vähemmän",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Esiintyy Sisään", "appeared_in": "Esiintyy Sisään",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Kohdetta Ei Voitu Ladata", "could_not_load_item": "Kohdetta Ei Voitu Ladata",
"none": "Ei mitään", "none": "Ei mitään",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Lataa {{item_count}} Kohteita", "download_x_item": "Lataa {{item_count}} Kohteita",
"download_unwatched_only": "Vain Katsomattomat", "download_unwatched_only": "Vain Katsomattomat",
"download_button": "Lataa" "download_button": "Lataa"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Seuraava", "next": "Seuraava",
@@ -652,7 +795,18 @@
"movies": "Elokuvat", "movies": "Elokuvat",
"sports": "Urheilu", "sports": "Urheilu",
"for_kids": "Lapsille", "for_kids": "Lapsille",
"news": "Uutiset" "news": "Uutiset",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Vahvista", "confirm": "Vahvista",
@@ -697,6 +851,12 @@
"decline": "Hylkää", "decline": "Hylkää",
"requested_by": "Käyttäjän {{user}} pyynnöstä", "requested_by": "Käyttäjän {{user}} pyynnöstä",
"unknown_user": "Tuntematon käyttäjä", "unknown_user": "Tuntematon käyttäjä",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Jellyseerr-palvelin ei täytä vähimmäisversiovaatimuksia! Päivitä vähintään versioon 2.0.0", "jellyseer_does_not_meet_requirements": "Jellyseerr-palvelin ei täytä vähimmäisversiovaatimuksia! Päivitä vähintään versioon 2.0.0",
"jellyseerr_test_failed": "Jellyseerr-testi epäonnistui. Yritä uudelleen.", "jellyseerr_test_failed": "Jellyseerr-testi epäonnistui. Yritä uudelleen.",
@@ -716,7 +876,8 @@
"search": "Haku", "search": "Haku",
"library": "Kirjasto", "library": "Kirjasto",
"custom_links": "Mukautetut linkit", "custom_links": "Mukautetut linkit",
"favorites": "Suosikit" "favorites": "Suosikit",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Music", "title": "Music",
@@ -841,5 +1002,36 @@
"show": "This show", "show": "This show",
"all": "All media (default)" "all": "All media (default)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Erreur", "error_title": "Erreur",
"login_title": "Se connecter", "login_title": "Se connecter",
"login_to_title": "Se connecter à", "login_to_title": "Se connecter à",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Nom d'utilisateur", "username_placeholder": "Nom d'utilisateur",
"password_placeholder": "Mot de passe", "password_placeholder": "Mot de passe",
"login_button": "Se connecter", "login_button": "Se connecter",
@@ -42,7 +45,13 @@
"accounts_count": "Comptes {{count}}", "accounts_count": "Comptes {{count}}",
"select_account": "Sélectionnez un compte", "select_account": "Sélectionnez un compte",
"add_account": "Ajouter un compte", "add_account": "Ajouter un compte",
"remove_account_description": "Cela supprimera les identifiants enregistrés pour {{username}}." "remove_account_description": "Cela supprimera les identifiants enregistrés pour {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Sauvegarder le compte", "title": "Sauvegarder le compte",
@@ -86,6 +95,7 @@
"oops": "Oups!", "oops": "Oups!",
"error_message": "Quelque chose s'est mal passé.\nVeuillez vous reconnecter à nouveau.", "error_message": "Quelque chose s'est mal passé.\nVeuillez vous reconnecter à nouveau.",
"continue_watching": "Continuer à regarder", "continue_watching": "Continuer à regarder",
"continue": "Continue",
"next_up": "À suivre", "next_up": "À suivre",
"continue_and_next_up": "Continuer de regarder et à suivre", "continue_and_next_up": "Continuer de regarder et à suivre",
"recently_added_in": "Ajoutés récemment dans {{libraryName}}", "recently_added_in": "Ajoutés récemment dans {{libraryName}}",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Paramètres", "settings_title": "Paramètres",
"log_out_button": "Déconnexion", "log_out_button": "Déconnexion",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Catégories" "title": "Catégories"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Apparence", "title": "Apparence",
"merge_next_up_continue_watching": "Fusionner, continuer à regarder et à suivre", "merge_next_up_continue_watching": "Fusionner, continuer à regarder et à suivre",
"hide_remote_session_button": "Masquer le bouton de session distante" "hide_remote_session_button": "Masquer le bouton de session distante",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Réseau", "title": "Réseau",
@@ -174,6 +199,22 @@
"rewind_length": "Durée de retour en arrière", "rewind_length": "Durée de retour en arrière",
"seconds_unit": "s" "seconds_unit": "s"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Commandes gestuelles", "gesture_controls_title": "Commandes gestuelles",
"horizontal_swipe_skip": "Glisser horizontalement pour passer", "horizontal_swipe_skip": "Glisser horizontalement pour passer",
@@ -256,7 +297,23 @@
"subtitle_font": "Police des sous-titres", "subtitle_font": "Police des sous-titres",
"ksplayer_title": "Paramètres de KSPlayer", "ksplayer_title": "Paramètres de KSPlayer",
"hardware_decode": "Décodage matériel", "hardware_decode": "Décodage matériel",
"hardware_decode_description": "Utilisez laccélération matérielle pour le décodage vidéo. Désactivez si vous rencontrez des problèmes de lecture." "hardware_decode_description": "Utilisez laccélération matérielle pour le décodage vidéo. Désactivez si vous rencontrez des problèmes de lecture.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "Paramètres des sous-titres VLC", "title": "Paramètres des sous-titres VLC",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Cache de musique effacé", "music_cache_cleared": "Cache de musique effacé",
"delete_all_downloaded_songs": "Supprimer toutes les musiques téléchargées", "delete_all_downloaded_songs": "Supprimer toutes les musiques téléchargées",
"downloaded_songs_size": "{{size}} téléchargé", "downloaded_songs_size": "{{size}} téléchargé",
"downloaded_songs_deleted": "Chansons téléchargées supprimées" "downloaded_songs_deleted": "Chansons téléchargées supprimées",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Introduction", "title": "Introduction",
@@ -430,6 +493,21 @@
"error_deleting_files": "Erreur lors de la suppression des fichiers", "error_deleting_files": "Erreur lors de la suppression des fichiers",
"background_downloads_enabled": "Téléchargements en arrière-plan activés", "background_downloads_enabled": "Téléchargements en arrière-plan activés",
"background_downloads_disabled": "Téléchargements en arrière-plan désactivés" "background_downloads_disabled": "Téléchargements en arrière-plan désactivés"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "La nouvelle mise à jour nécessite que le contenu soit téléchargé à nouveau. Veuillez supprimer tout le contenu téléchargé et réessayer.", "new_app_version_requires_re_download_description": "La nouvelle mise à jour nécessite que le contenu soit téléchargé à nouveau. Veuillez supprimer tout le contenu téléchargé et réessayer.",
"back": "Retour", "back": "Retour",
"delete": "Supprimer", "delete": "Supprimer",
"delete_download": "Delete Download",
"something_went_wrong": "Quelque chose s'est mal passé", "something_went_wrong": "Quelque chose s'est mal passé",
"could_not_get_stream_url_from_jellyfin": "Impossible d'obtenir l'URL du flux depuis Jellyfin", "could_not_get_stream_url_from_jellyfin": "Impossible d'obtenir l'URL du flux depuis Jellyfin",
"eta": "ETA {{eta}}", "eta": "ETA {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Sélectionner", "select": "Sélectionner",
"no_trailer_available": "Aucune bande-annonce disponible", "no_trailer_available": "Aucune bande-annonce disponible",
"video": "Vidéo", "video": "Vidéo",
"audio": "Audio", "audio": "Audio",
"subtitle": "Sous-titres", "subtitle": "Sous-titres",
"play": "Lecture", "play": "Lecture",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "Aucun", "none": "Aucun",
"track": "Suivre", "track": "Suivre",
"cancel": "Annuler", "cancel": "Annuler",
"stop": "Stop",
"delete": "Supprimer", "delete": "Supprimer",
"ok": "Ok", "ok": "Ok",
"remove": "Retirer", "remove": "Retirer",
"next": "Suivant", "next": "Suivant",
"back": "Précédent", "back": "Précédent",
"continue": "Continuer", "continue": "Continuer",
"verifying": "Vérification..." "verifying": "Vérification...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Rechercher...", "search": "Rechercher...",
@@ -556,6 +641,7 @@
"movies": "Films", "movies": "Films",
"series": "Séries", "series": "Séries",
"boxsets": "Coffrets ", "boxsets": "Coffrets ",
"playlists": "Playlists",
"items": "Médias" "items": "Médias"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Affiche", "poster": "Affiche",
"cover": "Couverture", "cover": "Couverture",
"show_titles": "Afficher les titres", "show_titles": "Afficher les titres",
"show_stats": "Afficher les statistiques" "show_stats": "Afficher les statistiques",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Genres", "genres": "Genres",
@@ -574,7 +661,11 @@
"sort_by": "Trier par", "sort_by": "Trier par",
"filter_by": "Filtrer par", "filter_by": "Filtrer par",
"sort_order": "Ordre de tri", "sort_order": "Ordre de tri",
"tags": "Tags" "tags": "Tags",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "Aucuns liens" "no_links": "Aucuns liens"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Erreur", "error": "Erreur",
"failed_to_get_stream_url": "Échec de l'obtention de l'URL du flux", "failed_to_get_stream_url": "Échec de l'obtention de l'URL du flux",
"an_error_occured_while_playing_the_video": "Une erreur sest produite lors de la lecture de la vidéo. Vérifiez les journaux dans les paramètres.", "an_error_occured_while_playing_the_video": "Une erreur sest produite lors de la lecture de la vidéo. Vérifiez les journaux dans les paramètres.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Voulez-vous lire le fichier téléchargé ?", "downloaded_file_message": "Voulez-vous lire le fichier téléchargé ?",
"downloaded_file_yes": "Oui", "downloaded_file_yes": "Oui",
"downloaded_file_no": "Non", "downloaded_file_no": "Non",
"downloaded_file_cancel": "Annuler" "downloaded_file_cancel": "Annuler",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "À suivre", "next_up": "À suivre",
@@ -617,6 +738,11 @@
"series": "Séries", "series": "Séries",
"seasons": "Saisons", "seasons": "Saisons",
"season": "Saison", "season": "Saison",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "Aucun épisode pour cette saison", "no_episodes_for_this_season": "Aucun épisode pour cette saison",
"overview": "Aperçu", "overview": "Aperçu",
"more_with": "Plus avec {{name}}", "more_with": "Plus avec {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Options média", "media_options": "Options média",
"quality": "Qualité", "quality": "Qualité",
"audio": "Audio", "audio": "Audio",
"subtitles": "Sous-titres", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Afficher plus", "show_more": "Afficher plus",
"show_less": "Afficher moins", "show_less": "Afficher moins",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Apparu dans", "appeared_in": "Apparu dans",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Impossible de charger le média", "could_not_load_item": "Impossible de charger le média",
"none": "Aucun", "none": "Aucun",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Télécharger {{item_count}} médias", "download_x_item": "Télécharger {{item_count}} médias",
"download_unwatched_only": "Non visionné uniquement", "download_unwatched_only": "Non visionné uniquement",
"download_button": "Télécharger" "download_button": "Télécharger"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Suivant", "next": "Suivant",
@@ -652,7 +795,18 @@
"movies": "Films", "movies": "Films",
"sports": "Sports", "sports": "Sports",
"for_kids": "Pour enfants", "for_kids": "Pour enfants",
"news": "Actualités" "news": "Actualités",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Confirmer", "confirm": "Confirmer",
@@ -697,6 +851,12 @@
"decline": "Refuser", "decline": "Refuser",
"requested_by": "Demandé par {{user}}", "requested_by": "Demandé par {{user}}",
"unknown_user": "Utilisateur inconnu", "unknown_user": "Utilisateur inconnu",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Seerr ne répond pas aux exigences! Veuillez mettre à jour au moins vers la version 2.0.0.", "jellyseer_does_not_meet_requirements": "Seerr ne répond pas aux exigences! Veuillez mettre à jour au moins vers la version 2.0.0.",
"jellyseerr_test_failed": "Le test Seerr a échoué. Veuillez réessayer.", "jellyseerr_test_failed": "Le test Seerr a échoué. Veuillez réessayer.",
@@ -716,7 +876,8 @@
"search": "Recherche", "search": "Recherche",
"library": "Bibliothèque", "library": "Bibliothèque",
"custom_links": "Liens personnalisés", "custom_links": "Liens personnalisés",
"favorites": "Favoris" "favorites": "Favoris",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Musique", "title": "Musique",
@@ -788,8 +949,8 @@
} }
}, },
"watchlists": { "watchlists": {
"title": "Watchlists", "title": "Listes de lecture",
"my_watchlists": "My Watchlists", "my_watchlists": "Mes listes de lecture",
"public_watchlists": "Watchlist publique", "public_watchlists": "Watchlist publique",
"create_title": "Créer une Watchlist", "create_title": "Créer une Watchlist",
"edit_title": "Modifier la Watchlist", "edit_title": "Modifier la Watchlist",
@@ -802,7 +963,7 @@
"name_placeholder": "Entrer le nom de la playlist", "name_placeholder": "Entrer le nom de la playlist",
"description_label": "Description", "description_label": "Description",
"description_placeholder": "Entrez la description (facultatif)", "description_placeholder": "Entrez la description (facultatif)",
"is_public_label": "Public Watchlist", "is_public_label": "Liste de lecture Publique",
"is_public_description": "Autoriser d'autres personnes à voir cette liste de suivi", "is_public_description": "Autoriser d'autres personnes à voir cette liste de suivi",
"allowed_type_label": "Type de contenu", "allowed_type_label": "Type de contenu",
"sort_order_label": "Ordre de tri par défaut", "sort_order_label": "Ordre de tri par défaut",
@@ -841,5 +1002,36 @@
"show": "Cette série", "show": "Cette série",
"all": "Tous les médias (par défaut)" "all": "Tous les médias (par défaut)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "שגיאה", "error_title": "שגיאה",
"login_title": "התחבר", "login_title": "התחבר",
"login_to_title": "התחבר אל", "login_to_title": "התחבר אל",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "שם משתמש", "username_placeholder": "שם משתמש",
"password_placeholder": "סיסמה", "password_placeholder": "סיסמה",
"login_button": "התחבר", "login_button": "התחבר",
@@ -39,10 +42,16 @@
"please_login_again": "Your saved session has expired. Please log in again.", "please_login_again": "Your saved session has expired. Please log in again.",
"remove_saved_login": "Remove Saved Login", "remove_saved_login": "Remove Saved Login",
"remove_saved_login_description": "This will remove your saved credentials for this server. You'll need to enter your username and password again next time.", "remove_saved_login_description": "This will remove your saved credentials for this server. You'll need to enter your username and password again next time.",
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} חשבונות",
"select_account": "Select Account", "select_account": "Select Account",
"add_account": "Add Account", "add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "This will remove the saved credentials for {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "Save Account",
@@ -86,6 +95,7 @@
"oops": "אופס!", "oops": "אופס!",
"error_message": "קרתה תקלה. אנא התנתק והתחבר מחדש.", "error_message": "קרתה תקלה. אנא התנתק והתחבר מחדש.",
"continue_watching": "המשך לצפות", "continue_watching": "המשך לצפות",
"continue": "Continue",
"next_up": "הבא בתור", "next_up": "הבא בתור",
"continue_and_next_up": "Continue & Next Up", "continue_and_next_up": "Continue & Next Up",
"recently_added_in": "התווסף לאחרונה ב-{{libraryName}}", "recently_added_in": "התווסף לאחרונה ב-{{libraryName}}",
@@ -109,19 +119,34 @@
"settings": { "settings": {
"settings_title": "הגדרות", "settings_title": "הגדרות",
"log_out_button": "התנתק", "log_out_button": "התנתק",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Categories" "title": "קטגוריות"
}, },
"playback_controls": { "playback_controls": {
"title": "Playback & Controls" "title": "Playback & Controls"
}, },
"audio_subtitles": { "audio_subtitles": {
"title": "Audio & Subtitles" "title": "שמע וכתוביות"
}, },
"appearance": { "appearance": {
"title": "Appearance", "title": "מראה",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up", "merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button" "hide_remote_session_button": "Hide Remote Session Button",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "Network",
@@ -174,6 +199,22 @@
"rewind_length": "אורך הזזה אחורה", "rewind_length": "אורך הזזה אחורה",
"seconds_unit": "שנ'" "seconds_unit": "שנ'"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "פקדי מחוות", "gesture_controls_title": "פקדי מחוות",
"horizontal_swipe_skip": "החלקה אופקית לדילוג", "horizontal_swipe_skip": "החלקה אופקית לדילוג",
@@ -188,7 +229,7 @@
"hide_brightness_slider_description": "Hide the brightness slider in the video player" "hide_brightness_slider_description": "Hide the brightness slider in the video player"
}, },
"audio": { "audio": {
"audio_title": "אודיו", "audio_title": "שמע",
"set_audio_track": "בחר רצועת שמע מהפריט הקודם", "set_audio_track": "בחר רצועת שמע מהפריט הקודם",
"audio_language": "שפת שמע", "audio_language": "שפת שמע",
"audio_hint": "בחר שפת שמע אוטומטית.", "audio_hint": "בחר שפת שמע אוטומטית.",
@@ -256,7 +297,23 @@
"subtitle_font": "Subtitle Font", "subtitle_font": "Subtitle Font",
"ksplayer_title": "KSPlayer Settings", "ksplayer_title": "KSPlayer Settings",
"hardware_decode": "Hardware Decoding", "hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues." "hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "VLC Subtitle Settings",
@@ -271,8 +328,8 @@
"margin": "Bottom Margin" "margin": "Bottom Margin"
}, },
"video_player": { "video_player": {
"title": "Video Player", "title": "נגן וידאו",
"video_player": "Video Player", "video_player": "נגן וידאו",
"video_player_description": "Choose which video player to use on iOS.", "video_player_description": "Choose which video player to use on iOS.",
"ksplayer": "KSPlayer", "ksplayer": "KSPlayer",
"vlc": "VLC" "vlc": "VLC"
@@ -314,7 +371,7 @@
"downloads_title": "הורדות" "downloads_title": "הורדות"
}, },
"music": { "music": {
"title": "Music", "title": "מוזיקה",
"playback_title": "Playback", "playback_title": "Playback",
"playback_description": "Configure how music is played.", "playback_description": "Configure how music is played.",
"prefer_downloaded": "Prefer Downloaded Songs", "prefer_downloaded": "Prefer Downloaded Songs",
@@ -406,10 +463,16 @@
"music_cache_cleared": "Music cache cleared", "music_cache_cleared": "Music cache cleared",
"delete_all_downloaded_songs": "Delete All Downloaded Songs", "delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded", "downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "Downloaded songs deleted",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Intro", "title": "הקדמה",
"show_intro": "הצג פתיח", "show_intro": "הצג פתיח",
"reset_intro": "אפס פתיח" "reset_intro": "אפס פתיח"
}, },
@@ -430,6 +493,21 @@
"error_deleting_files": "שגיאה במחיקת קבצים", "error_deleting_files": "שגיאה במחיקת קבצים",
"background_downloads_enabled": "הורדה ברקע מופעלת", "background_downloads_enabled": "הורדה ברקע מופעלת",
"background_downloads_disabled": "הורדה ברקע כבויה" "background_downloads_disabled": "הורדה ברקע כבויה"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "הגרסה החדשה דורשת לתוכן לרדת מחדש. אנא מחק את כל התוכן שכבר הורדת ונסה שוב.", "new_app_version_requires_re_download_description": "הגרסה החדשה דורשת לתוכן לרדת מחדש. אנא מחק את כל התוכן שכבר הורדת ונסה שוב.",
"back": "חזרה", "back": "חזרה",
"delete": "מחק", "delete": "מחק",
"delete_download": "Delete Download",
"something_went_wrong": "משהו השתבש", "something_went_wrong": "משהו השתבש",
"could_not_get_stream_url_from_jellyfin": "לא היה ניתן להגיע לקישור הזרם מהשרת Jellyfin", "could_not_get_stream_url_from_jellyfin": "לא היה ניתן להגיע לקישור הזרם מהשרת Jellyfin",
"eta": "זמן משוער {{eta}}", "eta": "זמן משוער {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "בחר", "select": "בחר",
"no_trailer_available": "אין טריילר זמין", "no_trailer_available": "אין טריילר זמין",
"video": "וידאו", "video": "וידאו",
"audio": "אודיו", "audio": "שמע",
"subtitle": "כתובית", "subtitle": "כתובית",
"play": "נגן", "play": "נגן",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "ללא", "none": "ללא",
"track": "Track", "track": "Track",
"cancel": "Cancel", "cancel": "Cancel",
"stop": "Stop",
"delete": "Delete", "delete": "Delete",
"ok": "OK", "ok": "OK",
"remove": "Remove", "remove": "Remove",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"continue": "Continue", "continue": "Continue",
"verifying": "Verifying..." "verifying": "Verifying...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "חפש...", "search": "חפש...",
@@ -521,9 +606,9 @@
"episodes": "פרקים", "episodes": "פרקים",
"collections": "אוספים", "collections": "אוספים",
"actors": "שחקנים", "actors": "שחקנים",
"artists": "Artists", "artists": "אומנים",
"albums": "Albums", "albums": "אלבומים",
"songs": "Songs", "songs": "שירים",
"playlists": "Playlists", "playlists": "Playlists",
"request_movies": "סרטים מבוקשים", "request_movies": "סרטים מבוקשים",
"request_series": "סדרות מבוקשים", "request_series": "סדרות מבוקשים",
@@ -556,6 +641,7 @@
"movies": "סרטים", "movies": "סרטים",
"series": "סדרות", "series": "סדרות",
"boxsets": "אוסף", "boxsets": "אוסף",
"playlists": "Playlists",
"items": "פריטים" "items": "פריטים"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "פוסטר", "poster": "פוסטר",
"cover": "עטיפה", "cover": "עטיפה",
"show_titles": "הצג כותרות", "show_titles": "הצג כותרות",
"show_stats": "הצג סטטיסטיקה" "show_stats": "הצג סטטיסטיקה",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "סגנונות", "genres": "סגנונות",
@@ -574,7 +661,11 @@
"sort_by": "מיין לפי", "sort_by": "מיין לפי",
"filter_by": "Filter By", "filter_by": "Filter By",
"sort_order": "סדר מיון", "sort_order": "סדר מיון",
"tags": "תגים" "tags": "תגים",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "אין קישורים" "no_links": "אין קישורים"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "שגיאה", "error": "שגיאה",
"failed_to_get_stream_url": "נכשל בהשגת קישור הזרם", "failed_to_get_stream_url": "נכשל בהשגת קישור הזרם",
"an_error_occured_while_playing_the_video": "קרתה תקלה במהלך הניגון של הקובץ. בדוק את הלוגים בהגדרות.", "an_error_occured_while_playing_the_video": "קרתה תקלה במהלך הניגון של הקובץ. בדוק את הלוגים בהגדרות.",
@@ -606,9 +699,37 @@
"go_back": "חזור", "go_back": "חזור",
"downloaded_file_title": "You have this file downloaded", "downloaded_file_title": "You have this file downloaded",
"downloaded_file_message": "Do you want to play the downloaded file?", "downloaded_file_message": "Do you want to play the downloaded file?",
"downloaded_file_yes": "Yes", "downloaded_file_yes": "כן",
"downloaded_file_no": "No", "downloaded_file_no": "לא",
"downloaded_file_cancel": "Cancel" "downloaded_file_cancel": "Cancel",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "הבא בתור", "next_up": "הבא בתור",
@@ -617,6 +738,11 @@
"series": "סדרות", "series": "סדרות",
"seasons": "עונות", "seasons": "עונות",
"season": "עונה", "season": "עונה",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "אין פרקים בעונה זו", "no_episodes_for_this_season": "אין פרקים בעונה זו",
"overview": "סקירה", "overview": "סקירה",
"more_with": "עוד עם {{name}}", "more_with": "עוד עם {{name}}",
@@ -626,11 +752,22 @@
"more_details": "פרטים נוספים", "more_details": "פרטים נוספים",
"media_options": "Media Options", "media_options": "Media Options",
"quality": "איכות", "quality": "איכות",
"audio": "אודיו", "audio": "שמע",
"subtitles": "כתובית", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "הצג עוד", "show_more": "הצג עוד",
"show_less": "הצג פחות", "show_less": "הצג פחות",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "הופיע ב-", "appeared_in": "הופיע ב-",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "נכשל בטעינת פריט", "could_not_load_item": "נכשל בטעינת פריט",
"none": "ללא", "none": "ללא",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "הורד {{item_count}} פריטים", "download_x_item": "הורד {{item_count}} פריטים",
"download_unwatched_only": "רק שלא נצפו", "download_unwatched_only": "רק שלא נצפו",
"download_button": "הורד" "download_button": "הורד"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "הבא", "next": "הבא",
@@ -652,7 +795,18 @@
"movies": "סרטים", "movies": "סרטים",
"sports": "ספורט", "sports": "ספורט",
"for_kids": "לילדים", "for_kids": "לילדים",
"news": "חדשות" "news": "חדשות",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "אשר", "confirm": "אשר",
@@ -697,6 +851,12 @@
"decline": "Decline", "decline": "Decline",
"requested_by": "Requested by {{user}}", "requested_by": "Requested by {{user}}",
"unknown_user": "Unknown User", "unknown_user": "Unknown User",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "שרת ה-Seerr לא תואם את הגרסה המינימלית הנרדת! אנא עדכן לפחות לגרסה 2.0.0", "jellyseer_does_not_meet_requirements": "שרת ה-Seerr לא תואם את הגרסה המינימלית הנרדת! אנא עדכן לפחות לגרסה 2.0.0",
"jellyseerr_test_failed": "בדיקת ה-Seerr נכשלה. אנא נסה שוב.", "jellyseerr_test_failed": "בדיקת ה-Seerr נכשלה. אנא נסה שוב.",
@@ -716,13 +876,14 @@
"search": "חיפוש", "search": "חיפוש",
"library": "ספריה", "library": "ספריה",
"custom_links": "קישורים מותאמים אישית", "custom_links": "קישורים מותאמים אישית",
"favorites": "מועדפים" "favorites": "מועדפים",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Music", "title": "מוזיקה",
"tabs": { "tabs": {
"suggestions": "Suggestions", "suggestions": "Suggestions",
"albums": "Albums", "albums": "אלבומים",
"artists": "Artists", "artists": "Artists",
"playlists": "Playlists", "playlists": "Playlists",
"tracks": "tracks" "tracks": "tracks"
@@ -798,9 +959,9 @@
"delete_button": "Delete", "delete_button": "Delete",
"remove_button": "Remove", "remove_button": "Remove",
"cancel_button": "Cancel", "cancel_button": "Cancel",
"name_label": "Name", "name_label": "שם",
"name_placeholder": "Enter watchlist name", "name_placeholder": "Enter watchlist name",
"description_label": "Description", "description_label": "תיאור",
"description_placeholder": "Enter description (optional)", "description_placeholder": "Enter description (optional)",
"is_public_label": "Public Watchlist", "is_public_label": "Public Watchlist",
"is_public_description": "Allow others to view this watchlist", "is_public_description": "Allow others to view this watchlist",
@@ -817,10 +978,10 @@
"remove_from_watchlist": "Remove from Watchlist", "remove_from_watchlist": "Remove from Watchlist",
"select_watchlist": "Select Watchlist", "select_watchlist": "Select Watchlist",
"create_new": "Create New Watchlist", "create_new": "Create New Watchlist",
"item": "item", "item": "פריט",
"items": "items", "items": "פריטים",
"public": "Public", "public": "ציבורי",
"private": "Private", "private": "פרטי",
"you": "You", "you": "You",
"by_owner": "By another user", "by_owner": "By another user",
"not_found": "Watchlist not found", "not_found": "Watchlist not found",
@@ -835,11 +996,42 @@
"playback_speed": { "playback_speed": {
"title": "Playback Speed", "title": "Playback Speed",
"apply_to": "Apply To", "apply_to": "Apply To",
"speed": "Speed", "speed": "מהירות",
"scope": { "scope": {
"media": "This media only", "media": "This media only",
"show": "This show", "show": "This show",
"all": "All media (default)" "all": "All media (default)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Hiba", "error_title": "Hiba",
"login_title": "Bejelentkezés", "login_title": "Bejelentkezés",
"login_to_title": "Bejelentkezés ide", "login_to_title": "Bejelentkezés ide",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Felhasználónév", "username_placeholder": "Felhasználónév",
"password_placeholder": "Jelszó", "password_placeholder": "Jelszó",
"login_button": "Bejelentkezés", "login_button": "Bejelentkezés",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} accounts",
"select_account": "Select Account", "select_account": "Select Account",
"add_account": "Add Account", "add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "This will remove the saved credentials for {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "Save Account",
@@ -86,6 +95,7 @@
"oops": "Hoppá!", "oops": "Hoppá!",
"error_message": "Valami nem stimmel.\nKérjük, jelentkezz ki, majd újra be.", "error_message": "Valami nem stimmel.\nKérjük, jelentkezz ki, majd újra be.",
"continue_watching": "Nézd Tovább", "continue_watching": "Nézd Tovább",
"continue": "Continue",
"next_up": "Következő", "next_up": "Következő",
"continue_and_next_up": "Continue & Next Up", "continue_and_next_up": "Continue & Next Up",
"recently_added_in": "Új a(z) {{libraryName}} könyvtárban", "recently_added_in": "Új a(z) {{libraryName}} könyvtárban",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Beállítások", "settings_title": "Beállítások",
"log_out_button": "Kijelentkezés", "log_out_button": "Kijelentkezés",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Categories" "title": "Categories"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Appearance", "title": "Appearance",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up", "merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button" "hide_remote_session_button": "Hide Remote Session Button",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "Network",
@@ -174,6 +199,22 @@
"rewind_length": "Visszatekerés Hossza", "rewind_length": "Visszatekerés Hossza",
"seconds_unit": "mp" "seconds_unit": "mp"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Gesztusvezérlés", "gesture_controls_title": "Gesztusvezérlés",
"horizontal_swipe_skip": "Vízszintes Húzás Ugráshoz", "horizontal_swipe_skip": "Vízszintes Húzás Ugráshoz",
@@ -256,7 +297,23 @@
"subtitle_font": "Subtitle Font", "subtitle_font": "Subtitle Font",
"ksplayer_title": "KSPlayer Settings", "ksplayer_title": "KSPlayer Settings",
"hardware_decode": "Hardware Decoding", "hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues." "hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "VLC Subtitle Settings",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Music cache cleared", "music_cache_cleared": "Music cache cleared",
"delete_all_downloaded_songs": "Delete All Downloaded Songs", "delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded", "downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "Downloaded songs deleted",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Intro", "title": "Intro",
@@ -430,6 +493,21 @@
"error_deleting_files": "Hiba a Fájlok Törlésekor", "error_deleting_files": "Hiba a Fájlok Törlésekor",
"background_downloads_enabled": "Background downloads enabled", "background_downloads_enabled": "Background downloads enabled",
"background_downloads_disabled": "Background downloads disabled" "background_downloads_disabled": "Background downloads disabled"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "Az új frissítéshez az összes tartalmat újra le kell tölteni. Kérjük, töröld az összes letöltött tartalmat, majd próbáld újra.", "new_app_version_requires_re_download_description": "Az új frissítéshez az összes tartalmat újra le kell tölteni. Kérjük, töröld az összes letöltött tartalmat, majd próbáld újra.",
"back": "Vissza", "back": "Vissza",
"delete": "Törlés", "delete": "Törlés",
"delete_download": "Delete Download",
"something_went_wrong": "Hiba Történt", "something_went_wrong": "Hiba Történt",
"could_not_get_stream_url_from_jellyfin": "Nem sikerült lekérni a stream URL-t a Jellyfinből", "could_not_get_stream_url_from_jellyfin": "Nem sikerült lekérni a stream URL-t a Jellyfinből",
"eta": "Várható Idő: {{eta}}", "eta": "Várható Idő: {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Select", "select": "Select",
"no_trailer_available": "No trailer available", "no_trailer_available": "No trailer available",
"video": "Videó", "video": "Videó",
"audio": "Hang", "audio": "Hang",
"subtitle": "Felirat", "subtitle": "Felirat",
"play": "Play", "play": "Play",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "None", "none": "None",
"track": "Track", "track": "Track",
"cancel": "Cancel", "cancel": "Cancel",
"stop": "Stop",
"delete": "Delete", "delete": "Delete",
"ok": "OK", "ok": "OK",
"remove": "Remove", "remove": "Remove",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"continue": "Continue", "continue": "Continue",
"verifying": "Verifying..." "verifying": "Verifying...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Keresés...", "search": "Keresés...",
@@ -556,6 +641,7 @@
"movies": "Filmek", "movies": "Filmek",
"series": "Sorozatok", "series": "Sorozatok",
"boxsets": "Gyűjtemények", "boxsets": "Gyűjtemények",
"playlists": "Playlists",
"items": "Elemek" "items": "Elemek"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Poszter", "poster": "Poszter",
"cover": "Borító", "cover": "Borító",
"show_titles": "Címek Megjelenítése", "show_titles": "Címek Megjelenítése",
"show_stats": "Statisztikák Megjelenítése" "show_stats": "Statisztikák Megjelenítése",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Műfajok", "genres": "Műfajok",
@@ -574,7 +661,11 @@
"sort_by": "Rendezés", "sort_by": "Rendezés",
"filter_by": "Filter By", "filter_by": "Filter By",
"sort_order": "Rendezés Iránya", "sort_order": "Rendezés Iránya",
"tags": "Címkék" "tags": "Címkék",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "Nincsenek Linkek" "no_links": "Nincsenek Linkek"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Hiba", "error": "Hiba",
"failed_to_get_stream_url": "Nem sikerült lekérni a stream URL-t", "failed_to_get_stream_url": "Nem sikerült lekérni a stream URL-t",
"an_error_occured_while_playing_the_video": "Hiba történt a videó lejátszása közben. Ellenőrizd a naplókat a beállításokban.", "an_error_occured_while_playing_the_video": "Hiba történt a videó lejátszása közben. Ellenőrizd a naplókat a beállításokban.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Do you want to play the downloaded file?", "downloaded_file_message": "Do you want to play the downloaded file?",
"downloaded_file_yes": "Yes", "downloaded_file_yes": "Yes",
"downloaded_file_no": "No", "downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel" "downloaded_file_cancel": "Cancel",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "Következő", "next_up": "Következő",
@@ -617,6 +738,11 @@
"series": "Sorozat", "series": "Sorozat",
"seasons": "Évadok", "seasons": "Évadok",
"season": "Évad", "season": "Évad",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "Ehhez az évadhoz nincs epizód", "no_episodes_for_this_season": "Ehhez az évadhoz nincs epizód",
"overview": "Áttekintés", "overview": "Áttekintés",
"more_with": "További {{name}} Alkotások", "more_with": "További {{name}} Alkotások",
@@ -627,10 +753,21 @@
"media_options": "Media Options", "media_options": "Media Options",
"quality": "Minőség", "quality": "Minőség",
"audio": "Hang", "audio": "Hang",
"subtitles": "Felirat", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Több Megjelenítése", "show_more": "Több Megjelenítése",
"show_less": "Kevesebb Megjelenítése", "show_less": "Kevesebb Megjelenítése",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Megjelent:", "appeared_in": "Megjelent:",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Nem Sikerült Betölteni az Elemet", "could_not_load_item": "Nem Sikerült Betölteni az Elemet",
"none": "Nincs", "none": "Nincs",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "{{item_count}} Elem Letöltése", "download_x_item": "{{item_count}} Elem Letöltése",
"download_unwatched_only": "Csak Nem Megtekintett", "download_unwatched_only": "Csak Nem Megtekintett",
"download_button": "Letöltés" "download_button": "Letöltés"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Következő", "next": "Következő",
@@ -652,7 +795,18 @@
"movies": "Filmek", "movies": "Filmek",
"sports": "Sport", "sports": "Sport",
"for_kids": "Gyerekeknek", "for_kids": "Gyerekeknek",
"news": "Hírek" "news": "Hírek",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Megerősítés", "confirm": "Megerősítés",
@@ -697,6 +851,12 @@
"decline": "Decline", "decline": "Decline",
"requested_by": "Requested by {{user}}", "requested_by": "Requested by {{user}}",
"unknown_user": "Unknown User", "unknown_user": "Unknown User",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "A Jellyseerr szerver nem felel meg a minimum verziókövetelményeknek! Kérlek frissítsd legalább 2.0.0-ra.", "jellyseer_does_not_meet_requirements": "A Jellyseerr szerver nem felel meg a minimum verziókövetelményeknek! Kérlek frissítsd legalább 2.0.0-ra.",
"jellyseerr_test_failed": "A Jellyseerr teszt sikertelen. Próbáld újra.", "jellyseerr_test_failed": "A Jellyseerr teszt sikertelen. Próbáld újra.",
@@ -716,7 +876,8 @@
"search": "Keresés", "search": "Keresés",
"library": "Könyvtár", "library": "Könyvtár",
"custom_links": "Egyéni Linkek", "custom_links": "Egyéni Linkek",
"favorites": "Kedvencek" "favorites": "Kedvencek",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Music", "title": "Music",
@@ -841,5 +1002,36 @@
"show": "This show", "show": "This show",
"all": "All media (default)" "all": "All media (default)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Errore", "error_title": "Errore",
"login_title": "Accesso", "login_title": "Accesso",
"login_to_title": "Accedi a", "login_to_title": "Accedi a",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Nome utente", "username_placeholder": "Nome utente",
"password_placeholder": "Password", "password_placeholder": "Password",
"login_button": "Accedi", "login_button": "Accedi",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} accounts",
"select_account": "Select Account", "select_account": "Select Account",
"add_account": "Add Account", "add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "This will remove the saved credentials for {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "Save Account",
@@ -86,6 +95,7 @@
"oops": "Ops!", "oops": "Ops!",
"error_message": "Qualcosa è andato storto. \nEffetturare il logout e riaccedere.", "error_message": "Qualcosa è andato storto. \nEffetturare il logout e riaccedere.",
"continue_watching": "Continua a guardare", "continue_watching": "Continua a guardare",
"continue": "Continue",
"next_up": "Prossimo", "next_up": "Prossimo",
"continue_and_next_up": "Continue & Next Up", "continue_and_next_up": "Continue & Next Up",
"recently_added_in": "Aggiunti di recente a {{libraryName}}", "recently_added_in": "Aggiunti di recente a {{libraryName}}",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Impostazioni", "settings_title": "Impostazioni",
"log_out_button": "Esci", "log_out_button": "Esci",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Categorie" "title": "Categorie"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Aspetto", "title": "Aspetto",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up", "merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button" "hide_remote_session_button": "Hide Remote Session Button",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "Network",
@@ -136,7 +161,7 @@
"not_connected_to_wifi": "Not connected to WiFi", "not_connected_to_wifi": "Not connected to WiFi",
"no_networks_configured": "No networks configured", "no_networks_configured": "No networks configured",
"add_network_hint": "Add your home WiFi network to enable auto-switching", "add_network_hint": "Add your home WiFi network to enable auto-switching",
"current_wifi": "Current WiFi", "current_wifi": "WiFi Attuale",
"using_url": "Sta utilizzando", "using_url": "Sta utilizzando",
"local": "Local URL", "local": "Local URL",
"remote": "Remote URL", "remote": "Remote URL",
@@ -174,6 +199,22 @@
"rewind_length": "Lunghezza del riavvolgimento", "rewind_length": "Lunghezza del riavvolgimento",
"seconds_unit": "secondi" "seconds_unit": "secondi"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Controlli Gesture", "gesture_controls_title": "Controlli Gesture",
"horizontal_swipe_skip": "Scorrimento orizzontale per saltare", "horizontal_swipe_skip": "Scorrimento orizzontale per saltare",
@@ -256,7 +297,23 @@
"subtitle_font": "Subtitle Font", "subtitle_font": "Subtitle Font",
"ksplayer_title": "KSPlayer Settings", "ksplayer_title": "KSPlayer Settings",
"hardware_decode": "Hardware Decoding", "hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues." "hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "VLC Subtitle Settings",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Music cache cleared", "music_cache_cleared": "Music cache cleared",
"delete_all_downloaded_songs": "Delete All Downloaded Songs", "delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded", "downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "Downloaded songs deleted",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Intro", "title": "Intro",
@@ -430,6 +493,21 @@
"error_deleting_files": "Errore nella cancellazione dei file", "error_deleting_files": "Errore nella cancellazione dei file",
"background_downloads_enabled": "Scaricamento in background abilitato", "background_downloads_enabled": "Scaricamento in background abilitato",
"background_downloads_disabled": "Scaricamento in background disabilitato" "background_downloads_disabled": "Scaricamento in background disabilitato"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "Il nuovo aggiornamento richiede di scaricare nuovamente i contenuti. Rimuovere tutti i contenuti scaricati e riprovare.", "new_app_version_requires_re_download_description": "Il nuovo aggiornamento richiede di scaricare nuovamente i contenuti. Rimuovere tutti i contenuti scaricati e riprovare.",
"back": "Indietro", "back": "Indietro",
"delete": "Cancella", "delete": "Cancella",
"delete_download": "Delete Download",
"something_went_wrong": "Qualcosa è andato storto", "something_went_wrong": "Qualcosa è andato storto",
"could_not_get_stream_url_from_jellyfin": "Impossibile ottenere l'URL del flusso da Jellyfin", "could_not_get_stream_url_from_jellyfin": "Impossibile ottenere l'URL del flusso da Jellyfin",
"eta": "Tempo stimato di completamento {{eta}}", "eta": "Tempo stimato di completamento {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Seleziona", "select": "Seleziona",
"no_trailer_available": "Nessun trailer disponibile", "no_trailer_available": "Nessun trailer disponibile",
"video": "Video", "video": "Video",
"audio": "Audio", "audio": "Audio",
"subtitle": "Sottotitoli", "subtitle": "Sottotitoli",
"play": "Gioca", "play": "Gioca",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "Nulla", "none": "Nulla",
"track": "Traccia", "track": "Traccia",
"cancel": "Cancel", "cancel": "Cancel",
"stop": "Stop",
"delete": "Delete", "delete": "Delete",
"ok": "OK", "ok": "OK",
"remove": "Remove", "remove": "Remove",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"continue": "Continue", "continue": "Continue",
"verifying": "Verifying..." "verifying": "Verifying...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Cerca...", "search": "Cerca...",
@@ -556,6 +641,7 @@
"movies": "film", "movies": "film",
"series": "serie TV", "series": "serie TV",
"boxsets": "cofanetti", "boxsets": "cofanetti",
"playlists": "Playlists",
"items": "elementi" "items": "elementi"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Poster", "poster": "Poster",
"cover": "Copertina", "cover": "Copertina",
"show_titles": "Mostra titoli", "show_titles": "Mostra titoli",
"show_stats": "Mostra statistiche" "show_stats": "Mostra statistiche",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Generi", "genres": "Generi",
@@ -574,7 +661,11 @@
"sort_by": "Ordina per", "sort_by": "Ordina per",
"filter_by": "Filter By", "filter_by": "Filter By",
"sort_order": "Criterio di ordinamento", "sort_order": "Criterio di ordinamento",
"tags": "Tag" "tags": "Tag",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "Nessun link" "no_links": "Nessun link"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Errore", "error": "Errore",
"failed_to_get_stream_url": "Impossibile ottenere l'URL dello stream", "failed_to_get_stream_url": "Impossibile ottenere l'URL dello stream",
"an_error_occured_while_playing_the_video": "Si è verificato un errore durante la riproduzione del video. Controllare i log nelle impostazioni.", "an_error_occured_while_playing_the_video": "Si è verificato un errore durante la riproduzione del video. Controllare i log nelle impostazioni.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Do you want to play the downloaded file?", "downloaded_file_message": "Do you want to play the downloaded file?",
"downloaded_file_yes": "Yes", "downloaded_file_yes": "Yes",
"downloaded_file_no": "No", "downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel" "downloaded_file_cancel": "Cancel",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "Il prossimo", "next_up": "Il prossimo",
@@ -617,6 +738,11 @@
"series": "Serie", "series": "Serie",
"seasons": "Stagioni", "seasons": "Stagioni",
"season": "Stagione", "season": "Stagione",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "Nessun episodio per questa stagione", "no_episodes_for_this_season": "Nessun episodio per questa stagione",
"overview": "Panoramica", "overview": "Panoramica",
"more_with": "Altri con {{name}}", "more_with": "Altri con {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Opzioni Media", "media_options": "Opzioni Media",
"quality": "Qualità", "quality": "Qualità",
"audio": "Audio", "audio": "Audio",
"subtitles": "Sottotitoli", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Mostra di più", "show_more": "Mostra di più",
"show_less": "Mostra di meno", "show_less": "Mostra di meno",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Apparso in", "appeared_in": "Apparso in",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Impossibile caricare l'elemento", "could_not_load_item": "Impossibile caricare l'elemento",
"none": "Nessuno", "none": "Nessuno",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Scarica {{item_count}} elementi", "download_x_item": "Scarica {{item_count}} elementi",
"download_unwatched_only": "Solo Non Visti", "download_unwatched_only": "Solo Non Visti",
"download_button": "Scarica" "download_button": "Scarica"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Prossimo", "next": "Prossimo",
@@ -652,7 +795,18 @@
"movies": "Film", "movies": "Film",
"sports": "Sport", "sports": "Sport",
"for_kids": "Per Bambini", "for_kids": "Per Bambini",
"news": "Notiziari" "news": "Notiziari",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Conferma", "confirm": "Conferma",
@@ -697,6 +851,12 @@
"decline": "Rifiuta", "decline": "Rifiuta",
"requested_by": "Richiesto da {{user}}", "requested_by": "Richiesto da {{user}}",
"unknown_user": "Utente Sconosciuto", "unknown_user": "Utente Sconosciuto",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Il server Jellyseerr non soddisfa i requisiti minimi di versione! Aggiornare almeno alla versione 2.0.0.", "jellyseer_does_not_meet_requirements": "Il server Jellyseerr non soddisfa i requisiti minimi di versione! Aggiornare almeno alla versione 2.0.0.",
"jellyseerr_test_failed": "Il test di Jellyseerr non è riuscito. Riprovare.", "jellyseerr_test_failed": "Il test di Jellyseerr non è riuscito. Riprovare.",
@@ -716,7 +876,8 @@
"search": "Cerca", "search": "Cerca",
"library": "Libreria", "library": "Libreria",
"custom_links": "Collegamenti personalizzati", "custom_links": "Collegamenti personalizzati",
"favorites": "Preferiti" "favorites": "Preferiti",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Music", "title": "Music",
@@ -841,5 +1002,36 @@
"show": "This show", "show": "This show",
"all": "All media (default)" "all": "All media (default)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "エラー", "error_title": "エラー",
"login_title": "ログイン", "login_title": "ログイン",
"login_to_title": "ログイン先", "login_to_title": "ログイン先",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "ユーザー名", "username_placeholder": "ユーザー名",
"password_placeholder": "パスワード", "password_placeholder": "パスワード",
"login_button": "ログイン", "login_button": "ログイン",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} accounts",
"select_account": "Select Account", "select_account": "Select Account",
"add_account": "Add Account", "add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "This will remove the saved credentials for {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "Save Account",
@@ -86,6 +95,7 @@
"oops": "おっと!", "oops": "おっと!",
"error_message": "何か問題が発生しました。\nログアウトして再度ログインしてください。", "error_message": "何か問題が発生しました。\nログアウトして再度ログインしてください。",
"continue_watching": "続きを見る", "continue_watching": "続きを見る",
"continue": "Continue",
"next_up": "次の動画", "next_up": "次の動画",
"continue_and_next_up": "Continue & Next Up", "continue_and_next_up": "Continue & Next Up",
"recently_added_in": "{{libraryName}}に最近追加された", "recently_added_in": "{{libraryName}}に最近追加された",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "設定", "settings_title": "設定",
"log_out_button": "ログアウト", "log_out_button": "ログアウト",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "カテゴリ" "title": "カテゴリ"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Appearance", "title": "Appearance",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up", "merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button" "hide_remote_session_button": "Hide Remote Session Button",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "Network",
@@ -174,6 +199,22 @@
"rewind_length": "巻き戻しの長さ", "rewind_length": "巻き戻しの長さ",
"seconds_unit": "s" "seconds_unit": "s"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "ジェスチャーコントロール", "gesture_controls_title": "ジェスチャーコントロール",
"horizontal_swipe_skip": "水平方向にスワイプしてスキップ", "horizontal_swipe_skip": "水平方向にスワイプしてスキップ",
@@ -256,7 +297,23 @@
"subtitle_font": "Subtitle Font", "subtitle_font": "Subtitle Font",
"ksplayer_title": "KSPlayer Settings", "ksplayer_title": "KSPlayer Settings",
"hardware_decode": "Hardware Decoding", "hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues." "hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "VLC Subtitle Settings",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Music cache cleared", "music_cache_cleared": "Music cache cleared",
"delete_all_downloaded_songs": "Delete All Downloaded Songs", "delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded", "downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "Downloaded songs deleted",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "イントロ", "title": "イントロ",
@@ -430,6 +493,21 @@
"error_deleting_files": "ファイルの削除エラー", "error_deleting_files": "ファイルの削除エラー",
"background_downloads_enabled": "バックグラウンドでのダウンロードは有効です", "background_downloads_enabled": "バックグラウンドでのダウンロードは有効です",
"background_downloads_disabled": "バックグラウンドでのダウンロードは無効です" "background_downloads_disabled": "バックグラウンドでのダウンロードは無効です"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "新しいアップデートではコンテンツを再度ダウンロードする必要があります。ダウンロードしたコンテンツをすべて削除してもう一度お試しください。", "new_app_version_requires_re_download_description": "新しいアップデートではコンテンツを再度ダウンロードする必要があります。ダウンロードしたコンテンツをすべて削除してもう一度お試しください。",
"back": "戻る", "back": "戻る",
"delete": "削除", "delete": "削除",
"delete_download": "Delete Download",
"something_went_wrong": "問題が発生しました", "something_went_wrong": "問題が発生しました",
"could_not_get_stream_url_from_jellyfin": "JellyfinからストリームURLを取得できませんでした", "could_not_get_stream_url_from_jellyfin": "JellyfinからストリームURLを取得できませんでした",
"eta": "ETA {{eta}}", "eta": "ETA {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "選択", "select": "選択",
"no_trailer_available": "トレーラーがありません", "no_trailer_available": "トレーラーがありません",
"video": "映像", "video": "映像",
"audio": "音声", "audio": "音声",
"subtitle": "字幕", "subtitle": "字幕",
"play": "再生", "play": "再生",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "None", "none": "None",
"track": "Track", "track": "Track",
"cancel": "Cancel", "cancel": "Cancel",
"stop": "Stop",
"delete": "Delete", "delete": "Delete",
"ok": "OK", "ok": "OK",
"remove": "Remove", "remove": "Remove",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"continue": "Continue", "continue": "Continue",
"verifying": "Verifying..." "verifying": "Verifying...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "検索...", "search": "検索...",
@@ -556,6 +641,7 @@
"movies": "映画", "movies": "映画",
"series": "シリーズ", "series": "シリーズ",
"boxsets": "ボックスセット", "boxsets": "ボックスセット",
"playlists": "Playlists",
"items": "アイテム" "items": "アイテム"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "ポスター", "poster": "ポスター",
"cover": "カバー", "cover": "カバー",
"show_titles": "タイトルの表示", "show_titles": "タイトルの表示",
"show_stats": "統計を表示" "show_stats": "統計を表示",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "ジャンル", "genres": "ジャンル",
@@ -574,7 +661,11 @@
"sort_by": "ソート", "sort_by": "ソート",
"filter_by": "Filter By", "filter_by": "Filter By",
"sort_order": "ソート順", "sort_order": "ソート順",
"tags": "タグ" "tags": "タグ",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "リンクがありません" "no_links": "リンクがありません"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "エラー", "error": "エラー",
"failed_to_get_stream_url": "ストリームURLを取得できませんでした", "failed_to_get_stream_url": "ストリームURLを取得できませんでした",
"an_error_occured_while_playing_the_video": "動画の再生中にエラーが発生しました。設定でログを確認してください。", "an_error_occured_while_playing_the_video": "動画の再生中にエラーが発生しました。設定でログを確認してください。",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Do you want to play the downloaded file?", "downloaded_file_message": "Do you want to play the downloaded file?",
"downloaded_file_yes": "Yes", "downloaded_file_yes": "Yes",
"downloaded_file_no": "No", "downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel" "downloaded_file_cancel": "Cancel",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "次", "next_up": "次",
@@ -617,6 +738,11 @@
"series": "シリーズ", "series": "シリーズ",
"seasons": "シーズン", "seasons": "シーズン",
"season": "シーズン", "season": "シーズン",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "このシーズンのエピソードはありません", "no_episodes_for_this_season": "このシーズンのエピソードはありません",
"overview": "ストーリー", "overview": "ストーリー",
"more_with": "{{name}}の詳細", "more_with": "{{name}}の詳細",
@@ -627,10 +753,21 @@
"media_options": "Media Options", "media_options": "Media Options",
"quality": "画質", "quality": "画質",
"audio": "音声", "audio": "音声",
"subtitles": "字幕", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "もっと見る", "show_more": "もっと見る",
"show_less": "少なく表示", "show_less": "少なく表示",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "出演作品", "appeared_in": "出演作品",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "アイテムを読み込めませんでした", "could_not_load_item": "アイテムを読み込めませんでした",
"none": "なし", "none": "なし",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "{{item_count}}のアイテムをダウンロード", "download_x_item": "{{item_count}}のアイテムをダウンロード",
"download_unwatched_only": "未視聴のみ", "download_unwatched_only": "未視聴のみ",
"download_button": "ダウンロード" "download_button": "ダウンロード"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "次", "next": "次",
@@ -652,7 +795,18 @@
"movies": "映画", "movies": "映画",
"sports": "スポーツ", "sports": "スポーツ",
"for_kids": "子供向け", "for_kids": "子供向け",
"news": "ニュース" "news": "ニュース",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "確認", "confirm": "確認",
@@ -697,6 +851,12 @@
"decline": "Decline", "decline": "Decline",
"requested_by": "Requested by {{user}}", "requested_by": "Requested by {{user}}",
"unknown_user": "Unknown User", "unknown_user": "Unknown User",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Jellyseerrサーバーは最小バージョン要件を満たしていません。少なくとも 2.0.0 に更新してください。", "jellyseer_does_not_meet_requirements": "Jellyseerrサーバーは最小バージョン要件を満たしていません。少なくとも 2.0.0 に更新してください。",
"jellyseerr_test_failed": "Jellyseerrテストに失敗しました。もう一度お試しください。", "jellyseerr_test_failed": "Jellyseerrテストに失敗しました。もう一度お試しください。",
@@ -716,7 +876,8 @@
"search": "検索", "search": "検索",
"library": "ライブラリ", "library": "ライブラリ",
"custom_links": "カスタムリンク", "custom_links": "カスタムリンク",
"favorites": "お気に入り" "favorites": "お気に入り",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Music", "title": "Music",
@@ -841,5 +1002,36 @@
"show": "This show", "show": "This show",
"all": "All media (default)" "all": "All media (default)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -1,187 +1,228 @@
{ {
"login": { "login": {
"username_required": "Username Is Required", "username_required": "사용자 이름이 필요합니다",
"error_title": "Error", "error_title": "오류",
"login_title": "Log In", "login_title": "로그인",
"login_to_title": "Log in to", "login_to_title": "다음 서비스에 연결 중",
"username_placeholder": "Username", "select_user": "Select a user to log in",
"password_placeholder": "Password", "add_user_to_login": "Add a user to log in",
"login_button": "Log In", "add_user": "Add User",
"quick_connect": "Quick Connect", "username_placeholder": "사용자 이름",
"enter_code_to_login": "Enter code {{code}} to login", "password_placeholder": "비밀번호",
"failed_to_initiate_quick_connect": "Failed to initiate Quick Connect", "login_button": "로그인",
"got_it": "Got It", "quick_connect": "퀵 커넥트",
"connection_failed": "Connection Failed", "enter_code_to_login": "로그인 하기 위해 코드{{code}}를 입력하세요",
"could_not_connect_to_server": "Could not connect to the server. Please check the URL and your network connection.", "failed_to_initiate_quick_connect": "Quick Connect 연결을 시작하는 데 실패했습니다",
"an_unexpected_error_occured": "An Unexpected Error Occurred", "got_it": "성공",
"change_server": "Change Server", "connection_failed": "연결 실패",
"invalid_username_or_password": "Invalid Username or Password", "could_not_connect_to_server": "서버에 연결되지 않았습니다. URL과 네트워크 상태를 확인하세요.",
"user_does_not_have_permission_to_log_in": "User does not have permission to log in", "an_unexpected_error_occured": "예기치 않은 오류가 발생했습니다",
"server_is_taking_too_long_to_respond_try_again_later": "Server is taking too long to respond, try again later", "change_server": "서버 변경",
"server_received_too_many_requests_try_again_later": "Server received too many requests, try again later.", "invalid_username_or_password": "잘못된 아이디 혹은 비밀번호입니다",
"there_is_a_server_error": "There is a server error", "user_does_not_have_permission_to_log_in": "로그인 하기 위한 권한이 없습니다",
"an_unexpected_error_occured_did_you_enter_the_correct_url": "An unexpected error occurred. Did you enter the server URL correctly?", "server_is_taking_too_long_to_respond_try_again_later": "서버 응답이 너무 느립니다. 나중에 다시 시도하세요",
"server_received_too_many_requests_try_again_later": "서버가 너무 많은 요청을 받았습니다. 나중에 다시 시도하세요.",
"there_is_a_server_error": "서버 에러",
"an_unexpected_error_occured_did_you_enter_the_correct_url": "예기치 않은 오류가 발생했습니다. 서버 URL을 올바르게 입력하셨습니까?",
"too_old_server_text": "Unsupported Jellyfin Server Discovered", "too_old_server_text": "Unsupported Jellyfin Server Discovered",
"too_old_server_description": "Please update Jellyfin to the latest version" "too_old_server_description": "Please update Jellyfin to the latest version"
}, },
"server": { "server": {
"enter_url_to_jellyfin_server": "Enter the URL to your Jellyfin server", "enter_url_to_jellyfin_server": "Enter the URL to your Jellyfin server",
"server_url_placeholder": "http(s)://your-server.com", "server_url_placeholder": "http(s)://your-server.com",
"connect_button": "Connect", "connect_button": "연결",
"previous_servers": "Previous Servers", "previous_servers": "이전 서버",
"clear_button": "Clear all", "clear_button": "모두 지우기",
"swipe_to_remove": "Swipe to remove", "swipe_to_remove": "스와이프해서 지우기",
"search_for_local_servers": "Search for Local Servers", "search_for_local_servers": "로컬 서버 찾기",
"searching": "Searching...", "searching": "찾는 중...",
"servers": "Servers", "servers": "서버",
"saved": "Saved", "saved": "저장됨",
"session_expired": "Session Expired", "session_expired": "세션 만료됨",
"please_login_again": "Your saved session has expired. Please log in again.", "please_login_again": "사용자 세션이 만료되었습니다. 다시 로그인하십시오.",
"remove_saved_login": "Remove Saved Login", "remove_saved_login": "저장된 로그인 정보 삭제",
"remove_saved_login_description": "This will remove your saved credentials for this server. You'll need to enter your username and password again next time.", "remove_saved_login_description": "해당 서버에 저장된 자격 증명이 삭제됩니다. 다음에 접속할 때는 사용자 이름과 비밀번호를 다시 입력해야 합니다.",
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} 계정",
"select_account": "Select Account", "select_account": "계정 선택",
"add_account": "Add Account", "add_account": "계정 추가",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "{{username}}에 저장된 자격 증명이 삭제됩니다.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "계정 저장",
"save_for_later": "Save this account", "save_for_later": "이 계정 저장",
"security_option": "Security Option", "security_option": "보안 설정",
"no_protection": "No protection", "no_protection": "보안 없음",
"no_protection_desc": "Quick login without authentication", "no_protection_desc": "인증 없이 빠른 로그인",
"pin_code": "PIN code", "pin_code": "PIN 코드",
"pin_code_desc": "4-digit PIN required when switching", "pin_code_desc": "전환하려면 4자리 PIN 필요함",
"password": "Re-enter password", "password": "암호 확인",
"password_desc": "Password required when switching", "password_desc": "전환하려면 비밀번호 필요함",
"save_button": "Save", "save_button": "저장",
"cancel_button": "Cancel" "cancel_button": "취소"
}, },
"pin": { "pin": {
"enter_pin": "Enter PIN", "enter_pin": "PIN 입력",
"enter_pin_for": "Enter PIN for {{username}}", "enter_pin_for": "{{username}} PIN 입력",
"enter_4_digits": "Enter 4 digits", "enter_4_digits": "4자리 입력",
"invalid_pin": "Invalid PIN", "invalid_pin": "잘못된 PIN",
"setup_pin": "Set Up PIN", "setup_pin": "PIN 설정",
"confirm_pin": "Confirm PIN", "confirm_pin": "PIN 확인",
"pins_dont_match": "PINs don't match", "pins_dont_match": "PIN이 일치하지 않습니다",
"forgot_pin": "Forgot PIN?", "forgot_pin": "PIN을 잊으셨나요?",
"forgot_pin_desc": "Your saved credentials will be removed" "forgot_pin_desc": "저장된 계정 정보가 삭제됩니다"
}, },
"password": { "password": {
"enter_password": "Enter Password", "enter_password": "비밀번호 입력",
"enter_password_for": "Enter password for {{username}}", "enter_password_for": "{{username}}의 비밀번호 입력",
"invalid_password": "Invalid password" "invalid_password": "잘못된 비밀번호"
}, },
"home": { "home": {
"checking_server_connection": "Checking server connection...", "checking_server_connection": "서버 연결 체크중...",
"no_internet": "No Internet", "no_internet": "인터넷에 연결되지 않음",
"no_items": "No Items", "no_items": "항목 없음",
"no_internet_message": "No worries, you can still watch\ndownloaded content.", "no_internet_message": "걱정마세요. 다운로드 된 컨텐츠는 여전히 볼 수 있습니다.",
"checking_server_connection_message": "Checking connection to server", "checking_server_connection_message": "Checking connection to server",
"go_to_downloads": "Go to Downloads", "go_to_downloads": "Go to Downloads",
"retry": "Retry", "retry": "재시도",
"server_unreachable": "Server Unreachable", "server_unreachable": "서버에 연결할 수 없음",
"server_unreachable_message": "Could not reach the server.\nPlease check your network connection.", "server_unreachable_message": "서버에 연결할 수 없습니다. 네트워크 상태를 체크하세요.",
"oops": "Oops!", "oops": "이런!",
"error_message": "Something went wrong.\nPlease log out and in again.", "error_message": "문제가 발생했습니다.\n로그아웃 후 다시 로그인해 주세요.",
"continue_watching": "Continue Watching", "continue_watching": "이어서 보기",
"next_up": "Next Up", "continue": "Continue",
"continue_and_next_up": "Continue & Next Up", "next_up": "다음 시청",
"recently_added_in": "Recently Added in {{libraryName}}", "continue_and_next_up": "이어서 보기 & 다음 시청",
"suggested_movies": "Suggested Movies", "recently_added_in": "최근에 추가된 {{libraryName}}",
"suggested_episodes": "Suggested Episodes", "suggested_movies": "추천 영화",
"suggested_episodes": "추천 에피소드",
"intro": { "intro": {
"welcome_to_streamyfin": "Welcome to Streamyfin", "welcome_to_streamyfin": "스트리미핀에 오신 것을 환영합니다",
"a_free_and_open_source_client_for_jellyfin": "A Free and Open-Source Client for Jellyfin.", "a_free_and_open_source_client_for_jellyfin": "젤리핀을 위한 무료 오픈소스 클라이언트입니다.",
"features_title": "Features", "features_title": "기능",
"features_description": "Streamyfin has a bunch of features and integrates with a wide array of software which you can find in the settings menu, these include:", "features_description": "스트리미핀은 다양한 기능을 제공하며 설정 메뉴에서 확인할 수 있는 여러 소프트웨어와 통합됩니다. 이러한 소프트웨어에는 다음이 포함됩니다:",
"jellyseerr_feature_description": "Connect to your Seerr instance and request movies directly in the app.", "jellyseerr_feature_description": "Seerr 인스턴스에 연결하여 앱에서 직접 영화를 요청할 수 있습니다.",
"downloads_feature_title": "Downloads", "downloads_feature_title": "다운로드된 컨텐츠",
"downloads_feature_description": "Download movies and tv-shows to view offline. Use either the default method or install the optimize server to download files in the background.", "downloads_feature_description": "오프라인으로 보기위해 다운로드 하세요. 기본 다운로드 방식을 사용하거나, 백그라운드에서 파일을 다운로드하는 최적화 서버를 설치할 수 있습니다.",
"chromecast_feature_description": "Cast movies and tv-shows to your Chromecast devices.", "chromecast_feature_description": "영화와 TV 프로그램을 Chromecast 기기로 전송하기",
"centralised_settings_plugin_title": "Centralised Settings Plugin", "centralised_settings_plugin_title": "중앙 설정 플러그인",
"centralised_settings_plugin_description": "Configure settings from a centralised location on your Jellyfin server. All client settings for all users will be synced automatically.", "centralised_settings_plugin_description": "Jellyfin 서버의 중앙 집중식 위치에서 설정을 구성합니다. 모든 사용자의 모든 클라이언트 설정이 자동으로 동기화됩니다.",
"done_button": "Done", "done_button": "확인",
"go_to_settings_button": "Go to Settings", "go_to_settings_button": "설정으로 이동",
"read_more": "Read More" "read_more": "자세히 보기"
}, },
"settings": { "settings": {
"settings_title": "Settings", "settings_title": "설정",
"log_out_button": "Log Out", "log_out_button": "로그아웃",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Categories" "title": "카테고리"
}, },
"playback_controls": { "playback_controls": {
"title": "Playback & Controls" "title": "재생 & 컨트롤"
}, },
"audio_subtitles": { "audio_subtitles": {
"title": "Audio & Subtitles" "title": "오디오 & 자막"
}, },
"appearance": { "appearance": {
"title": "Appearance", "title": "화면 스타일",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up", "merge_next_up_continue_watching": "[이어보기]와 [다음 보기] 합치기",
"hide_remote_session_button": "Hide Remote Session Button" "hide_remote_session_button": "원격 세션 버튼 숨기기",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "네트워크",
"local_network": "Local Network", "local_network": "로컬 네트워크",
"auto_switch_enabled": "Auto-switch when at home", "auto_switch_enabled": "홈 네트워크 자동 전환",
"auto_switch_description": "Automatically switch to local URL when connected to home WiFi", "auto_switch_description": "홈 WiFi에 연결되었을 때 로컬 URL로 자동 전환",
"local_url": "Local URL", "local_url": "로컬 URL",
"local_url_hint": "Enter your local server address (e.g., http://192.168.1.100:8096)", "local_url_hint": "로컬 서버 주소를 입력하세요 (e.g., http://192.168.1.100:8096)",
"local_url_placeholder": "http://192.168.1.100:8096", "local_url_placeholder": "http://192.168.1.100:8096",
"home_wifi_networks": "Home WiFi Networks", "home_wifi_networks": " WiFi 네트워크",
"add_current_network": "Add \"{{ssid}}\"", "add_current_network": "\"{{ssid}}\" 추가",
"not_connected_to_wifi": "Not connected to WiFi", "not_connected_to_wifi": "WiFi에 연결되지 않음",
"no_networks_configured": "No networks configured", "no_networks_configured": "구성된 네트워크가 없습니다",
"add_network_hint": "Add your home WiFi network to enable auto-switching", "add_network_hint": "자동 전환을 위한 홈 WiFi 추가",
"current_wifi": "Current WiFi", "current_wifi": "현재 WiFi",
"using_url": "Using", "using_url": "사용중",
"local": "Local URL", "local": "로컬 URL",
"remote": "Remote URL", "remote": "원격 URL",
"not_connected": "Not connected", "not_connected": "연결되지 않았습니다",
"current_server": "Current Server", "current_server": "현재 서버",
"remote_url": "Remote URL", "remote_url": "원격 URL",
"active_url": "Active URL", "active_url": "현재 사용 중인 URL",
"not_configured": "Not configured", "not_configured": "설정되지 않음",
"network_added": "Network added", "network_added": "네트워크 추가됨",
"network_already_added": "Network already added", "network_already_added": "네트워크 이미 추가됨",
"no_wifi_connected": "Not connected to WiFi", "no_wifi_connected": "WiFi에 연결되지 않음",
"permission_denied": "Location permission denied", "permission_denied": "위치 권한이 거부되었습니다",
"permission_denied_explanation": "Location permission is required to detect WiFi network for auto-switching. Please enable it in Settings." "permission_denied_explanation": "자동 전환 Wi-Fi 네트워크를 감지하려면 위치 권한이 필요합니다. 설정에서 위치 권한을 활성화해 주세요."
}, },
"user_info": { "user_info": {
"user_info_title": "User Info", "user_info_title": "사용자 정보",
"user": "User", "user": "사용자",
"server": "Server", "server": "서버",
"token": "Token", "token": "토큰",
"app_version": "App Version" "app_version": "앱 버전"
}, },
"quick_connect": { "quick_connect": {
"quick_connect_title": "Quick Connect", "quick_connect_title": "퀵 커넥트",
"authorize_button": "Authorize Quick Connect", "authorize_button": "퀵 커넥트 승인",
"enter_the_quick_connect_code": "Enter the quick connect code...", "enter_the_quick_connect_code": "퀵 커넥트 코드 입력...",
"success": "Success", "success": "성공",
"quick_connect_autorized": "Quick Connect Authorized", "quick_connect_autorized": "퀵 커넥트 승인됨",
"error": "Error", "error": "오류",
"invalid_code": "Invalid Code", "invalid_code": "유효하지 않은 코드",
"authorize": "Authorize" "authorize": "승인"
}, },
"media_controls": { "media_controls": {
"media_controls_title": "Media Controls", "media_controls_title": "미디어 컨트롤",
"forward_skip_length": "Forward Skip Length", "forward_skip_length": "앞으로 건너뛸 시간",
"rewind_length": "Rewind Length", "rewind_length": "뒤로 되감을 시간",
"seconds_unit": "s" "seconds_unit": ""
},
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
}, },
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Gesture Controls", "gesture_controls_title": "제스처 제어",
"horizontal_swipe_skip": "Horizontal Swipe to Skip", "horizontal_swipe_skip": "좌/우로 스와이프하여 건너뛰기",
"horizontal_swipe_skip_description": "Swipe left/right when controls are hidden to skip", "horizontal_swipe_skip_description": "컨트롤 숨김상태에서 좌/우로 스와이프하여 건너뛰기",
"left_side_brightness": "Left Side Brightness Control", "left_side_brightness": "왼쪽 영역 밝기 조정 컨트롤",
"left_side_brightness_description": "Swipe up/down on left side to adjust brightness", "left_side_brightness_description": "왼쪽 영역을 위/아래 스와이프하여 밝기 조절",
"right_side_volume": "Right Side Volume Control", "right_side_volume": "오른쪽 영역 볼륨 컨트롤",
"right_side_volume_description": "Swipe up/down on right side to adjust volume", "right_side_volume_description": "오른족 영역을 위/아래로 스와이프 하여 볼륨 조절",
"hide_volume_slider": "Hide Volume Slider", "hide_volume_slider": "Hide Volume Slider",
"hide_volume_slider_description": "Hide the volume slider in the video player", "hide_volume_slider_description": "Hide the volume slider in the video player",
"hide_brightness_slider": "Hide Brightness Slider", "hide_brightness_slider": "Hide Brightness Slider",
@@ -196,7 +237,7 @@
"language": "Language", "language": "Language",
"transcode_mode": { "transcode_mode": {
"title": "Audio Transcoding", "title": "Audio Transcoding",
"description": "Controls how surround audio (7.1, TrueHD, DTS-HD) is handled", "description": "서라운드 오디오(7.1, TrueHD, DTS-HD)를 어떻게 처리할지 설정합니다",
"auto": "Auto", "auto": "Auto",
"stereo": "Force Stereo", "stereo": "Force Stereo",
"5_1": "Allow 5.1", "5_1": "Allow 5.1",
@@ -228,52 +269,68 @@
"outline_opacity": "Outline Opacity", "outline_opacity": "Outline Opacity",
"bold_text": "Bold Text", "bold_text": "Bold Text",
"colors": { "colors": {
"Black": "Black", "Black": "검정색",
"Gray": "Gray", "Gray": "회색",
"Silver": "Silver", "Silver": "은색",
"White": "White", "White": "흰색",
"Maroon": "Maroon", "Maroon": "밤색",
"Red": "Red", "Red": "빨간색",
"Fuchsia": "Fuchsia", "Fuchsia": "분홍색",
"Yellow": "Yellow", "Yellow": "노란색",
"Olive": "Olive", "Olive": "올리브 색",
"Green": "Green", "Green": "녹색",
"Teal": "Teal", "Teal": "청록색",
"Lime": "Lime", "Lime": "라임색",
"Purple": "Purple", "Purple": "보라색",
"Navy": "Navy", "Navy": "남색",
"Blue": "Blue", "Blue": "파란색",
"Aqua": "Aqua" "Aqua": "아쿠아색"
}, },
"thickness": { "thickness": {
"None": "None", "None": "없음",
"Thin": "Thin", "Thin": "얇게",
"Normal": "Normal", "Normal": "보통",
"Thick": "Thick" "Thick": "굵게"
}, },
"subtitle_color": "Subtitle Color", "subtitle_color": "자막 색상",
"subtitle_background_color": "Background Color", "subtitle_background_color": "배경 색상",
"subtitle_font": "Subtitle Font", "subtitle_font": "자막 폰트",
"ksplayer_title": "KSPlayer Settings", "ksplayer_title": "KSPlayer 설정",
"hardware_decode": "Hardware Decoding", "hardware_decode": "하드웨어 디코딩",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues." "hardware_decode_description": "비디오 디코딩에 하드웨어 가속을 사용하십시오. 재생 문제가 발생하는 경우 비활성화하십시오.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "VLC 자막 설정",
"hint": "Customize subtitle appearance for VLC player. Changes take effect on next playback.", "hint": "VLC 플레이어의 자막 표시 방식을 설정하세요. 변경 사항은 다음 재생 시 적용됩니다.",
"text_color": "Text Color", "text_color": "글자색",
"background_color": "Background Color", "background_color": "배경 색상",
"background_opacity": "Background Opacity", "background_opacity": "배경 투명도",
"outline_color": "Outline Color", "outline_color": "외곽선 색상",
"outline_opacity": "Outline Opacity", "outline_opacity": "외곽선 투명도",
"outline_thickness": "Outline Thickness", "outline_thickness": "외곽선 굵기",
"bold": "Bold Text", "bold": "굵은 글씨",
"margin": "Bottom Margin" "margin": "아래쪽 여백"
}, },
"video_player": { "video_player": {
"title": "Video Player", "title": "비디오 플레이어",
"video_player": "Video Player", "video_player": "비디오 플레이어",
"video_player_description": "Choose which video player to use on iOS.", "video_player_description": "iOS 사용자는 비디오 플레이어를 선택하세요.",
"ksplayer": "KSPlayer", "ksplayer": "KSPlayer",
"vlc": "VLC" "vlc": "VLC"
}, },
@@ -288,20 +345,20 @@
"PORTRAIT_UP": "Portrait Up", "PORTRAIT_UP": "Portrait Up",
"PORTRAIT_DOWN": "Portrait Down", "PORTRAIT_DOWN": "Portrait Down",
"LANDSCAPE": "Landscape", "LANDSCAPE": "Landscape",
"LANDSCAPE_LEFT": "Landscape Left", "LANDSCAPE_LEFT": "왼쪽 가로 모드",
"LANDSCAPE_RIGHT": "Landscape Right", "LANDSCAPE_RIGHT": "오른쪽 가로 모드",
"OTHER": "Other", "OTHER": "Other",
"UNKNOWN": "Unknown" "UNKNOWN": "Unknown"
}, },
"safe_area_in_controls": "Safe Area in Controls", "safe_area_in_controls": "컨트롤 안전 영역",
"video_player": "Video Player", "video_player": "Video Player",
"video_players": { "video_players": {
"VLC_3": "VLC 3", "VLC_3": "VLC 3",
"VLC_4": "VLC 4 (Experimental + PiP)" "VLC_4": "VLC 4 (Experimental + PiP)"
}, },
"show_custom_menu_links": "Show Custom Menu Links", "show_custom_menu_links": "사용자 지정 메뉴 링크 표시",
"show_large_home_carousel": "Show Large Home Carousel (beta)", "show_large_home_carousel": "대형 홈 슬라이드 배너 표시 (베타)",
"hide_libraries": "Hide Libraries", "hide_libraries": "라이브러리 숨기기",
"select_liraries_you_want_to_hide": "Select the libraries you want to hide from the Library tab and home page sections.", "select_liraries_you_want_to_hide": "Select the libraries you want to hide from the Library tab and home page sections.",
"disable_haptic_feedback": "Disable Haptic Feedback", "disable_haptic_feedback": "Disable Haptic Feedback",
"default_quality": "Default Quality", "default_quality": "Default Quality",
@@ -334,24 +391,24 @@
"password": "Password", "password": "Password",
"password_placeholder": "Enter password for Jellyfin user {{username}}", "password_placeholder": "Enter password for Jellyfin user {{username}}",
"login_button": "Login", "login_button": "Login",
"total_media_requests": "Total Media Requests", "total_media_requests": "전체 미디어 요청 수",
"movie_quota_limit": "Movie Quota Limit", "movie_quota_limit": "영화 요청 한도",
"movie_quota_days": "Movie Quota Days", "movie_quota_days": "영화 요청 제한 기간",
"tv_quota_limit": "TV Quota Limit", "tv_quota_limit": "TV Quota Limit",
"tv_quota_days": "TV Quota Days", "tv_quota_days": "TV 요청 제한 기간",
"reset_jellyseerr_config_button": "Reset Seerr Config", "reset_jellyseerr_config_button": "Seerr 설정 초기화",
"unlimited": "Unlimited", "unlimited": "Unlimited",
"plus_n_more": "+{{n}} More", "plus_n_more": "+{{n}}개 더",
"order_by": { "order_by": {
"DEFAULT": "Default", "DEFAULT": "Default",
"VOTE_COUNT_AND_AVERAGE": "Vote count and average", "VOTE_COUNT_AND_AVERAGE": "평균 평점 및 투표 수",
"POPULARITY": "Popularity" "POPULARITY": "Popularity"
} }
}, },
"marlin_search": { "marlin_search": {
"enable_marlin_search": "Enable Marlin Search", "enable_marlin_search": "Marlin 검색 활성화",
"url": "URL", "url": "URL",
"server_url_placeholder": "http(s)://domain.org:port", "server_url_placeholder": "http(s)://도메인:포트",
"marlin_search_hint": "Enter the URL for the Marlin server. The URL should include http or https and optionally the port.", "marlin_search_hint": "Enter the URL for the Marlin server. The URL should include http or https and optionally the port.",
"read_more_about_marlin": "Read More About Marlin.", "read_more_about_marlin": "Read More About Marlin.",
"save_button": "Save", "save_button": "Save",
@@ -374,28 +431,28 @@
"features_title": "Features", "features_title": "Features",
"home_sections_title": "Home Sections", "home_sections_title": "Home Sections",
"enable_movie_recommendations": "Movie Recommendations", "enable_movie_recommendations": "Movie Recommendations",
"enable_series_recommendations": "Series Recommendations", "enable_series_recommendations": "시리즈 추천",
"enable_promoted_watchlists": "Promoted Watchlists", "enable_promoted_watchlists": "추천 관심 목록",
"hide_watchlists_tab": "Hide Watchlists Tab", "hide_watchlists_tab": "관심 목록 탭 숨기기",
"home_sections_hint": "Show personalized recommendations and promoted watchlists from Streamystats on the home page.", "home_sections_hint": "홈 페이지에서 Streamystats의 개인 맞춤 추천 및 추천 관심 목록을 표시합니다.",
"recommended_movies": "Recommended Movies", "recommended_movies": "Recommended Movies",
"recommended_series": "Recommended Series", "recommended_series": "추천 시리즈",
"toasts": { "toasts": {
"saved": "Saved", "saved": "Saved",
"refreshed": "Settings refreshed from server", "refreshed": "서버에서 설정을 새로고침했습니다",
"disabled": "Streamystats disabled" "disabled": "Streamystats 비활성화됨"
}, },
"refresh_from_server": "Refresh Settings from Server" "refresh_from_server": "서버에서 설정 새로고침"
}, },
"kefinTweaks": { "kefinTweaks": {
"watchlist_enabler": "Enable our Watchlist integration", "watchlist_enabler": "관심 목록 통합 기능 활성화",
"watchlist_button": "Toggle Watchlist integration" "watchlist_button": "관심 목록 연동 켜기/끄기"
} }
}, },
"storage": { "storage": {
"storage_title": "Storage", "storage_title": "Storage",
"app_usage": "App {{usedSpace}}%", "app_usage": " {{usedSpace}}",
"device_usage": "Device {{availableSpace}}%", "device_usage": "디바이스 {{availableSpace}}%",
"size_used": "{{used}} of {{total}} Used", "size_used": "{{used}} of {{total}} Used",
"delete_all_downloaded_files": "Delete All Downloaded Files", "delete_all_downloaded_files": "Delete All Downloaded Files",
"music_cache_title": "Music Cache", "music_cache_title": "Music Cache",
@@ -403,10 +460,16 @@
"enable_music_cache": "Enable Music Cache", "enable_music_cache": "Enable Music Cache",
"clear_music_cache": "Clear Music Cache", "clear_music_cache": "Clear Music Cache",
"music_cache_size": "{{size}} cached", "music_cache_size": "{{size}} cached",
"music_cache_cleared": "Music cache cleared", "music_cache_cleared": "음악 캐시가 삭제되었습니다",
"delete_all_downloaded_songs": "Delete All Downloaded Songs", "delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded", "downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "다운로드한 노래가 삭제되었습니다",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Intro", "title": "Intro",
@@ -430,11 +493,26 @@
"error_deleting_files": "Error Deleting Files", "error_deleting_files": "Error Deleting Files",
"background_downloads_enabled": "Background downloads enabled", "background_downloads_enabled": "Background downloads enabled",
"background_downloads_disabled": "Background downloads disabled" "background_downloads_disabled": "Background downloads disabled"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
"title": "Sessions", "title": "Sessions",
"no_active_sessions": "No Active Sessions" "no_active_sessions": "세션 비활성화"
}, },
"downloads": { "downloads": {
"downloads_title": "Downloads", "downloads_title": "Downloads",
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "The new update requires content to be downloaded again. Please remove all downloaded content and try again.", "new_app_version_requires_re_download_description": "The new update requires content to be downloaded again. Please remove all downloaded content and try again.",
"back": "Back", "back": "Back",
"delete": "Delete", "delete": "Delete",
"delete_download": "Delete Download",
"something_went_wrong": "Something Went Wrong", "something_went_wrong": "Something Went Wrong",
"could_not_get_stream_url_from_jellyfin": "Could not get the stream URL from Jellyfin", "could_not_get_stream_url_from_jellyfin": "Could not get the stream URL from Jellyfin",
"eta": "ETA {{eta}}", "eta": "ETA {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Select", "select": "Select",
"no_trailer_available": "No trailer available", "no_trailer_available": "No trailer available",
"video": "Video", "video": "Video",
"audio": "Audio", "audio": "Audio",
"subtitle": "Subtitle", "subtitle": "Subtitle",
"play": "Play", "play": "Play",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "None", "none": "None",
"track": "Track", "track": "Track",
"cancel": "Cancel", "cancel": "Cancel",
"stop": "Stop",
"delete": "Delete", "delete": "Delete",
"ok": "OK", "ok": "OK",
"remove": "Remove", "remove": "Remove",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"continue": "Continue", "continue": "Continue",
"verifying": "Verifying..." "verifying": "Verifying...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Search...", "search": "Search...",
@@ -556,6 +641,7 @@
"movies": "Movies", "movies": "Movies",
"series": "Series", "series": "Series",
"boxsets": "Box Sets", "boxsets": "Box Sets",
"playlists": "Playlists",
"items": "Items" "items": "Items"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Poster", "poster": "Poster",
"cover": "Cover", "cover": "Cover",
"show_titles": "Show Titles", "show_titles": "Show Titles",
"show_stats": "Show Stats" "show_stats": "Show Stats",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Genres", "genres": "Genres",
@@ -574,7 +661,11 @@
"sort_by": "Sort By", "sort_by": "Sort By",
"filter_by": "Filter By", "filter_by": "Filter By",
"sort_order": "Sort Order", "sort_order": "Sort Order",
"tags": "Tags" "tags": "Tags",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "No Links" "no_links": "No Links"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Error", "error": "Error",
"failed_to_get_stream_url": "Failed to get the stream URL", "failed_to_get_stream_url": "Failed to get the stream URL",
"an_error_occured_while_playing_the_video": "An error occurred while playing the video. Check logs in settings.", "an_error_occured_while_playing_the_video": "An error occurred while playing the video. Check logs in settings.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Do you want to play the downloaded file?", "downloaded_file_message": "Do you want to play the downloaded file?",
"downloaded_file_yes": "Yes", "downloaded_file_yes": "Yes",
"downloaded_file_no": "No", "downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel" "downloaded_file_cancel": "Cancel",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "Next Up", "next_up": "Next Up",
@@ -617,6 +738,11 @@
"series": "Series", "series": "Series",
"seasons": "Seasons", "seasons": "Seasons",
"season": "Season", "season": "Season",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "No episodes for this season", "no_episodes_for_this_season": "No episodes for this season",
"overview": "Overview", "overview": "Overview",
"more_with": "More with {{name}}", "more_with": "More with {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Media Options", "media_options": "Media Options",
"quality": "Quality", "quality": "Quality",
"audio": "Audio", "audio": "Audio",
"subtitles": "Subtitle", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Show More", "show_more": "Show More",
"show_less": "Show Less", "show_less": "Show Less",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Appeared In", "appeared_in": "Appeared In",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Could Not Load Item", "could_not_load_item": "Could Not Load Item",
"none": "None", "none": "None",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Download {{item_count}} Items", "download_x_item": "Download {{item_count}} Items",
"download_unwatched_only": "Unwatched Only", "download_unwatched_only": "Unwatched Only",
"download_button": "Download" "download_button": "Download"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Next", "next": "Next",
@@ -652,7 +795,18 @@
"movies": "Movies", "movies": "Movies",
"sports": "Sports", "sports": "Sports",
"for_kids": "For Kids", "for_kids": "For Kids",
"news": "News" "news": "News",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Confirm", "confirm": "Confirm",
@@ -697,6 +851,12 @@
"decline": "Decline", "decline": "Decline",
"requested_by": "Requested by {{user}}", "requested_by": "Requested by {{user}}",
"unknown_user": "Unknown User", "unknown_user": "Unknown User",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Seerr server does not meet minimum version requirements! Please update to at least 2.0.0", "jellyseer_does_not_meet_requirements": "Seerr server does not meet minimum version requirements! Please update to at least 2.0.0",
"jellyseerr_test_failed": "Seerr test failed. Please try again.", "jellyseerr_test_failed": "Seerr test failed. Please try again.",
@@ -716,7 +876,8 @@
"search": "Search", "search": "Search",
"library": "Library", "library": "Library",
"custom_links": "Custom Links", "custom_links": "Custom Links",
"favorites": "Favorites" "favorites": "Favorites",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Music", "title": "Music",
@@ -841,5 +1002,36 @@
"show": "This show", "show": "This show",
"all": "All media (default)" "all": "All media (default)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Fout", "error_title": "Fout",
"login_title": "Aanmelden", "login_title": "Aanmelden",
"login_to_title": "Aanmelden bij", "login_to_title": "Aanmelden bij",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Gebruikersnaam", "username_placeholder": "Gebruikersnaam",
"password_placeholder": "Wachtwoord", "password_placeholder": "Wachtwoord",
"login_button": "Aanmelden", "login_button": "Aanmelden",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} accounts",
"select_account": "Account selecteren", "select_account": "Account selecteren",
"add_account": "Account toevoegen", "add_account": "Account toevoegen",
"remove_account_description": "Hiermee worden de opgeslagen inloggegevens voor {{username}} verwijderd." "remove_account_description": "Hiermee worden de opgeslagen inloggegevens voor {{username}} verwijderd.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Account opslaan", "title": "Account opslaan",
@@ -86,6 +95,7 @@
"oops": "Oeps!", "oops": "Oeps!",
"error_message": "Er ging iets fout\nProbeer opnieuw in te loggen.", "error_message": "Er ging iets fout\nProbeer opnieuw in te loggen.",
"continue_watching": "Verder Kijken", "continue_watching": "Verder Kijken",
"continue": "Continue",
"next_up": "Volgende", "next_up": "Volgende",
"continue_and_next_up": "Doorgaan & Volgende", "continue_and_next_up": "Doorgaan & Volgende",
"recently_added_in": "Recent toegevoegd in {{libraryName}}", "recently_added_in": "Recent toegevoegd in {{libraryName}}",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Instellingen", "settings_title": "Instellingen",
"log_out_button": "Afmelden", "log_out_button": "Afmelden",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Categorieën" "title": "Categorieën"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Weergave", "title": "Weergave",
"merge_next_up_continue_watching": "Doorgaan met kijken & Volgende samenvoegen", "merge_next_up_continue_watching": "Doorgaan met kijken & Volgende samenvoegen",
"hide_remote_session_button": "Verberg Knop voor Externe Sessie" "hide_remote_session_button": "Verberg Knop voor Externe Sessie",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Netwerk", "title": "Netwerk",
@@ -174,6 +199,22 @@
"rewind_length": "Duur terugspoelen", "rewind_length": "Duur terugspoelen",
"seconds_unit": "s" "seconds_unit": "s"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Gebaar Bediening", "gesture_controls_title": "Gebaar Bediening",
"horizontal_swipe_skip": "Horizontale Swipe om over te slaan", "horizontal_swipe_skip": "Horizontale Swipe om over te slaan",
@@ -256,7 +297,23 @@
"subtitle_font": "Lettertype ondertitels", "subtitle_font": "Lettertype ondertitels",
"ksplayer_title": "KSPlayer Instellingen", "ksplayer_title": "KSPlayer Instellingen",
"hardware_decode": "Hardware Acceleratie", "hardware_decode": "Hardware Acceleratie",
"hardware_decode_description": "Gebruik hardware acceleratie voor video-decodering. Uitschakelen als u problemen met afspelen ondervindt." "hardware_decode_description": "Gebruik hardware acceleratie voor video-decodering. Uitschakelen als u problemen met afspelen ondervindt.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC ondertitel instellingen", "title": "VLC ondertitel instellingen",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Muziek cache gewist", "music_cache_cleared": "Muziek cache gewist",
"delete_all_downloaded_songs": "Verwijder alle gedownloade liedjes", "delete_all_downloaded_songs": "Verwijder alle gedownloade liedjes",
"downloaded_songs_size": "{{size}} gedownload", "downloaded_songs_size": "{{size}} gedownload",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "Downloaded songs deleted",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Intro", "title": "Intro",
@@ -430,6 +493,21 @@
"error_deleting_files": "Fout bij het verwijderen van bestanden", "error_deleting_files": "Fout bij het verwijderen van bestanden",
"background_downloads_enabled": "Downloads op de achtergrond ingeschakeld", "background_downloads_enabled": "Downloads op de achtergrond ingeschakeld",
"background_downloads_disabled": "Downloads op de achtergrond uitgeschakeld" "background_downloads_disabled": "Downloads op de achtergrond uitgeschakeld"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "Voor de nieuwe update moet de content opnieuw worden gedownload. Verwijder alle gedownloade content en probeer het opnieuw.", "new_app_version_requires_re_download_description": "Voor de nieuwe update moet de content opnieuw worden gedownload. Verwijder alle gedownloade content en probeer het opnieuw.",
"back": "Terug", "back": "Terug",
"delete": "Verwijder", "delete": "Verwijder",
"delete_download": "Delete Download",
"something_went_wrong": "Er ging iets mis", "something_went_wrong": "Er ging iets mis",
"could_not_get_stream_url_from_jellyfin": "Kon de URL van de stream niet krijgen van Jellyfin", "could_not_get_stream_url_from_jellyfin": "Kon de URL van de stream niet krijgen van Jellyfin",
"eta": "ETA {{eta}}", "eta": "ETA {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Selecteren", "select": "Selecteren",
"no_trailer_available": "Geen trailer beschikbaar", "no_trailer_available": "Geen trailer beschikbaar",
"video": "Video", "video": "Video",
"audio": "Audio", "audio": "Audio",
"subtitle": "Ondertitel", "subtitle": "Ondertitel",
"play": "Afspelen", "play": "Afspelen",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "Geen", "none": "Geen",
"track": "Spoor", "track": "Spoor",
"cancel": "Annuleren", "cancel": "Annuleren",
"stop": "Stop",
"delete": "Verwijderen", "delete": "Verwijderen",
"ok": "Oké", "ok": "Oké",
"remove": "Verwijderen", "remove": "Verwijderen",
"next": "Volgende", "next": "Volgende",
"back": "Terug", "back": "Terug",
"continue": "Doorgaan", "continue": "Doorgaan",
"verifying": "Verifiëren..." "verifying": "Verifiëren...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Zoek...", "search": "Zoek...",
@@ -556,6 +641,7 @@
"movies": "Films", "movies": "Films",
"series": "Series", "series": "Series",
"boxsets": "Boxsets", "boxsets": "Boxsets",
"playlists": "Playlists",
"items": "items" "items": "items"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Poster", "poster": "Poster",
"cover": "Omslag", "cover": "Omslag",
"show_titles": "Toon titels", "show_titles": "Toon titels",
"show_stats": "Toon statistieken" "show_stats": "Toon statistieken",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Genres", "genres": "Genres",
@@ -574,7 +661,11 @@
"sort_by": "Sorteren op", "sort_by": "Sorteren op",
"filter_by": "Filteren op", "filter_by": "Filteren op",
"sort_order": "Sorteer volgorde", "sort_order": "Sorteer volgorde",
"tags": "Labels" "tags": "Labels",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "Geen links" "no_links": "Geen links"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Fout", "error": "Fout",
"failed_to_get_stream_url": "De stream-URL kon niet worden verkregen", "failed_to_get_stream_url": "De stream-URL kon niet worden verkregen",
"an_error_occured_while_playing_the_video": "Er is een fout opgetreden tijdens het afspelen van de video. Controleer de logs in de instellingen.", "an_error_occured_while_playing_the_video": "Er is een fout opgetreden tijdens het afspelen van de video. Controleer de logs in de instellingen.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Wil je het gedownloade bestand afspelen?", "downloaded_file_message": "Wil je het gedownloade bestand afspelen?",
"downloaded_file_yes": "Ja", "downloaded_file_yes": "Ja",
"downloaded_file_no": "Nee", "downloaded_file_no": "Nee",
"downloaded_file_cancel": "Annuleren" "downloaded_file_cancel": "Annuleren",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "Volgende", "next_up": "Volgende",
@@ -617,6 +738,11 @@
"series": "Series", "series": "Series",
"seasons": "Seizoenen", "seasons": "Seizoenen",
"season": "Seizoen", "season": "Seizoen",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "Geen afleveringen voor dit seizoen", "no_episodes_for_this_season": "Geen afleveringen voor dit seizoen",
"overview": "Overzicht", "overview": "Overzicht",
"more_with": "Meer met {{name}}", "more_with": "Meer met {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Media opties", "media_options": "Media opties",
"quality": "Kwaliteit", "quality": "Kwaliteit",
"audio": "Audio", "audio": "Audio",
"subtitles": "Ondertitel", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Toon meer", "show_more": "Toon meer",
"show_less": "Toon minder", "show_less": "Toon minder",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Verschenen in", "appeared_in": "Verschenen in",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Kon item niet laden", "could_not_load_item": "Kon item niet laden",
"none": "Geen", "none": "Geen",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Download {{item_count}} items", "download_x_item": "Download {{item_count}} items",
"download_unwatched_only": "Alleen niet bekeken", "download_unwatched_only": "Alleen niet bekeken",
"download_button": "Downloaden" "download_button": "Downloaden"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Volgende ", "next": "Volgende ",
@@ -652,7 +795,18 @@
"movies": "Films", "movies": "Films",
"sports": "Sport", "sports": "Sport",
"for_kids": "Voor kinderen", "for_kids": "Voor kinderen",
"news": "Nieuws" "news": "Nieuws",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Bevestig", "confirm": "Bevestig",
@@ -697,6 +851,12 @@
"decline": "Weigeren", "decline": "Weigeren",
"requested_by": "Aangevraagd door {{user}}", "requested_by": "Aangevraagd door {{user}}",
"unknown_user": "Onbekende gebruiker", "unknown_user": "Onbekende gebruiker",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Jellyseerr server voldoet niet aan de minimale versievereisten! Update naar minimaal 2.0.0", "jellyseer_does_not_meet_requirements": "Jellyseerr server voldoet niet aan de minimale versievereisten! Update naar minimaal 2.0.0",
"jellyseerr_test_failed": "Jellyseerr test mislukt. Probeer opnieuw.", "jellyseerr_test_failed": "Jellyseerr test mislukt. Probeer opnieuw.",
@@ -716,7 +876,8 @@
"search": "Zoeken", "search": "Zoeken",
"library": "Bibliotheek", "library": "Bibliotheek",
"custom_links": "Aangepaste links", "custom_links": "Aangepaste links",
"favorites": "Favorieten" "favorites": "Favorieten",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Muziek", "title": "Muziek",
@@ -841,5 +1002,36 @@
"show": "Deze serie", "show": "Deze serie",
"all": "Alle media (standaard)" "all": "Alle media (standaard)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Feil", "error_title": "Feil",
"login_title": "Logg inn", "login_title": "Logg inn",
"login_to_title": "Logg inn i", "login_to_title": "Logg inn i",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Brukernavn", "username_placeholder": "Brukernavn",
"password_placeholder": "Passord", "password_placeholder": "Passord",
"login_button": "Logg inn", "login_button": "Logg inn",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} accounts",
"select_account": "Select Account", "select_account": "Select Account",
"add_account": "Add Account", "add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "This will remove the saved credentials for {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "Save Account",
@@ -86,6 +95,7 @@
"oops": "Oisann!", "oops": "Oisann!",
"error_message": "Noe gikk galt.\nVennligst logg ut og inn igjen.", "error_message": "Noe gikk galt.\nVennligst logg ut og inn igjen.",
"continue_watching": "Fortsett å se", "continue_watching": "Fortsett å se",
"continue": "Continue",
"next_up": "Neste opp", "next_up": "Neste opp",
"continue_and_next_up": "Continue & Next Up", "continue_and_next_up": "Continue & Next Up",
"recently_added_in": "Nylig lagt til i {{libraryName}}", "recently_added_in": "Nylig lagt til i {{libraryName}}",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Innstillinger", "settings_title": "Innstillinger",
"log_out_button": "Logg ut", "log_out_button": "Logg ut",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Categories" "title": "Categories"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Appearance", "title": "Appearance",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up", "merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button" "hide_remote_session_button": "Hide Remote Session Button",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "Network",
@@ -174,6 +199,22 @@
"rewind_length": "Omspar lengde", "rewind_length": "Omspar lengde",
"seconds_unit": "S" "seconds_unit": "S"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Gest kontroller", "gesture_controls_title": "Gest kontroller",
"horizontal_swipe_skip": "Vannrett sveip for å hoppe over", "horizontal_swipe_skip": "Vannrett sveip for å hoppe over",
@@ -256,7 +297,23 @@
"subtitle_font": "Subtitle Font", "subtitle_font": "Subtitle Font",
"ksplayer_title": "KSPlayer Settings", "ksplayer_title": "KSPlayer Settings",
"hardware_decode": "Hardware Decoding", "hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues." "hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "VLC Subtitle Settings",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Music cache cleared", "music_cache_cleared": "Music cache cleared",
"delete_all_downloaded_songs": "Delete All Downloaded Songs", "delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded", "downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "Downloaded songs deleted",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Intro", "title": "Intro",
@@ -430,6 +493,21 @@
"error_deleting_files": "Feil ved sletting av filer", "error_deleting_files": "Feil ved sletting av filer",
"background_downloads_enabled": "Nedlastinger av bakgrunn aktivert", "background_downloads_enabled": "Nedlastinger av bakgrunn aktivert",
"background_downloads_disabled": "Bakgrunnsnedlastinger deaktivert" "background_downloads_disabled": "Bakgrunnsnedlastinger deaktivert"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "Den nye oppdateringen krever at innholdet lastes ned på nytt. Fjern alt nedlastet innhold og prøv på nytt.", "new_app_version_requires_re_download_description": "Den nye oppdateringen krever at innholdet lastes ned på nytt. Fjern alt nedlastet innhold og prøv på nytt.",
"back": "Tilbake", "back": "Tilbake",
"delete": "Slett", "delete": "Slett",
"delete_download": "Delete Download",
"something_went_wrong": "Noe gikk galt", "something_went_wrong": "Noe gikk galt",
"could_not_get_stream_url_from_jellyfin": "Kunne ikke hente stream-URL fra Jellyfin", "could_not_get_stream_url_from_jellyfin": "Kunne ikke hente stream-URL fra Jellyfin",
"eta": "ETA {{eta}}", "eta": "ETA {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Velg", "select": "Velg",
"no_trailer_available": "Ingen trailer tilgjengelig", "no_trailer_available": "Ingen trailer tilgjengelig",
"video": "Video", "video": "Video",
"audio": "Lyd", "audio": "Lyd",
"subtitle": "Undertittel", "subtitle": "Undertittel",
"play": "Spill", "play": "Spill",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "None", "none": "None",
"track": "Track", "track": "Track",
"cancel": "Cancel", "cancel": "Cancel",
"stop": "Stop",
"delete": "Delete", "delete": "Delete",
"ok": "OK", "ok": "OK",
"remove": "Remove", "remove": "Remove",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"continue": "Continue", "continue": "Continue",
"verifying": "Verifying..." "verifying": "Verifying...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Søk...", "search": "Søk...",
@@ -556,6 +641,7 @@
"movies": "Filmer", "movies": "Filmer",
"series": "Serier", "series": "Serier",
"boxsets": "Boks sett", "boxsets": "Boks sett",
"playlists": "Playlists",
"items": "Elementer" "items": "Elementer"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Plakat", "poster": "Plakat",
"cover": "Omslag", "cover": "Omslag",
"show_titles": "Vis titler", "show_titles": "Vis titler",
"show_stats": "Vis statistikk" "show_stats": "Vis statistikk",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Genres", "genres": "Genres",
@@ -574,7 +661,11 @@
"sort_by": "Sorter etter", "sort_by": "Sorter etter",
"filter_by": "Filter By", "filter_by": "Filter By",
"sort_order": "Sorter etter", "sort_order": "Sorter etter",
"tags": "Tagger" "tags": "Tagger",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "Ingen lenke" "no_links": "Ingen lenke"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Feil", "error": "Feil",
"failed_to_get_stream_url": "Kan ikke hente nettadressen for stream", "failed_to_get_stream_url": "Kan ikke hente nettadressen for stream",
"an_error_occured_while_playing_the_video": "En feil oppstod under video. Sjekk loggene i innstillingene.", "an_error_occured_while_playing_the_video": "En feil oppstod under video. Sjekk loggene i innstillingene.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Do you want to play the downloaded file?", "downloaded_file_message": "Do you want to play the downloaded file?",
"downloaded_file_yes": "Yes", "downloaded_file_yes": "Yes",
"downloaded_file_no": "No", "downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel" "downloaded_file_cancel": "Cancel",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "Neste opp", "next_up": "Neste opp",
@@ -617,6 +738,11 @@
"series": "Serier", "series": "Serier",
"seasons": "Sesonger", "seasons": "Sesonger",
"season": "Sesong", "season": "Sesong",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "Ingen episoder for denne sesongen", "no_episodes_for_this_season": "Ingen episoder for denne sesongen",
"overview": "Oversikt", "overview": "Oversikt",
"more_with": "Mer med {{name}}", "more_with": "Mer med {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Media Options", "media_options": "Media Options",
"quality": "Kvalitet", "quality": "Kvalitet",
"audio": "Lyd", "audio": "Lyd",
"subtitles": "Undertittel", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Vis mer", "show_more": "Vis mer",
"show_less": "Vis mindre", "show_less": "Vis mindre",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Ble brukt i", "appeared_in": "Ble brukt i",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Kan ikke laste inn produkt", "could_not_load_item": "Kan ikke laste inn produkt",
"none": "Ingen", "none": "Ingen",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Last ned {{item_count}} Objekter", "download_x_item": "Last ned {{item_count}} Objekter",
"download_unwatched_only": "Bare usette", "download_unwatched_only": "Bare usette",
"download_button": "Nedlasting" "download_button": "Nedlasting"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Neste", "next": "Neste",
@@ -652,7 +795,18 @@
"movies": "Filmer", "movies": "Filmer",
"sports": "Sport", "sports": "Sport",
"for_kids": "For barn", "for_kids": "For barn",
"news": "Nyheter" "news": "Nyheter",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Bekreft", "confirm": "Bekreft",
@@ -697,6 +851,12 @@
"decline": "Decline", "decline": "Decline",
"requested_by": "Requested by {{user}}", "requested_by": "Requested by {{user}}",
"unknown_user": "Unknown User", "unknown_user": "Unknown User",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Seerr server oppfyller ikke minimumskravene til versjoner! Vennligst oppdater til minst 2.0.0", "jellyseer_does_not_meet_requirements": "Seerr server oppfyller ikke minimumskravene til versjoner! Vennligst oppdater til minst 2.0.0",
"jellyseerr_test_failed": "Seerr-test mislyktes. Vennligst prøv på nytt.", "jellyseerr_test_failed": "Seerr-test mislyktes. Vennligst prøv på nytt.",
@@ -716,7 +876,8 @@
"search": "Søk", "search": "Søk",
"library": "Bibliotek", "library": "Bibliotek",
"custom_links": "Egendefinerte lenker", "custom_links": "Egendefinerte lenker",
"favorites": "Favoritter" "favorites": "Favoritter",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Music", "title": "Music",
@@ -841,5 +1002,36 @@
"show": "This show", "show": "This show",
"all": "All media (default)" "all": "All media (default)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Błąd", "error_title": "Błąd",
"login_title": "Zaloguj się", "login_title": "Zaloguj się",
"login_to_title": "Zaloguj się do", "login_to_title": "Zaloguj się do",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Nazwa użytkownika", "username_placeholder": "Nazwa użytkownika",
"password_placeholder": "Hasło", "password_placeholder": "Hasło",
"login_button": "Zaloguj się", "login_button": "Zaloguj się",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} kont", "accounts_count": "{{count}} kont",
"select_account": "Wybierz konto", "select_account": "Wybierz konto",
"add_account": "Dodaj konto", "add_account": "Dodaj konto",
"remove_account_description": "Spowoduje to usunięcie zapisanych danych logowania dla {{username}}." "remove_account_description": "Spowoduje to usunięcie zapisanych danych logowania dla {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Zapisz konto", "title": "Zapisz konto",
@@ -86,6 +95,7 @@
"oops": "Ups!", "oops": "Ups!",
"error_message": "Coś poszło nie tak.\nWyloguj się i zaloguj ponownie.", "error_message": "Coś poszło nie tak.\nWyloguj się i zaloguj ponownie.",
"continue_watching": "Kontynuuj oglądanie", "continue_watching": "Kontynuuj oglądanie",
"continue": "Continue",
"next_up": "Następne w kolejce", "next_up": "Następne w kolejce",
"continue_and_next_up": "Oglądaj dalej i Następne", "continue_and_next_up": "Oglądaj dalej i Następne",
"recently_added_in": "Ostatnio dodano w {{libraryName}}", "recently_added_in": "Ostatnio dodano w {{libraryName}}",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Ustawienia", "settings_title": "Ustawienia",
"log_out_button": "Wyloguj się", "log_out_button": "Wyloguj się",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Kategorie" "title": "Kategorie"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Wygląd", "title": "Wygląd",
"merge_next_up_continue_watching": "Połącz Oglądaj dalej i Następne", "merge_next_up_continue_watching": "Połącz Oglądaj dalej i Następne",
"hide_remote_session_button": "Ukryj przycisk Zdalnej Sesji" "hide_remote_session_button": "Ukryj przycisk Zdalnej Sesji",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "Network",
@@ -174,6 +199,22 @@
"rewind_length": "Długość przewijania do tyłu", "rewind_length": "Długość przewijania do tyłu",
"seconds_unit": "s" "seconds_unit": "s"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Sterowanie gestami", "gesture_controls_title": "Sterowanie gestami",
"horizontal_swipe_skip": "Przesuń w poziomie, aby pominąć", "horizontal_swipe_skip": "Przesuń w poziomie, aby pominąć",
@@ -256,7 +297,23 @@
"subtitle_font": "Czcionka napisów", "subtitle_font": "Czcionka napisów",
"ksplayer_title": "Ustawienia KSPlayer", "ksplayer_title": "Ustawienia KSPlayer",
"hardware_decode": "Dekodowanie sprzętowe", "hardware_decode": "Dekodowanie sprzętowe",
"hardware_decode_description": "Używaj akceleracji sprzętowej dla dekodowania wideo. Wyłącz, jeśli doświadczasz problemów z odtwarzaniem." "hardware_decode_description": "Używaj akceleracji sprzętowej dla dekodowania wideo. Wyłącz, jeśli doświadczasz problemów z odtwarzaniem.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "Ustawienia napisów VLC", "title": "Ustawienia napisów VLC",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Wyczyszczono bufor muzyki", "music_cache_cleared": "Wyczyszczono bufor muzyki",
"delete_all_downloaded_songs": "Usuń wszystkie pobrane piosenki", "delete_all_downloaded_songs": "Usuń wszystkie pobrane piosenki",
"downloaded_songs_size": "Pobrano {{size}}", "downloaded_songs_size": "Pobrano {{size}}",
"downloaded_songs_deleted": "Usunięto pobrane piosenki" "downloaded_songs_deleted": "Usunięto pobrane piosenki",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Wstęp", "title": "Wstęp",
@@ -430,6 +493,21 @@
"error_deleting_files": "Błąd podczas usuwania plików", "error_deleting_files": "Błąd podczas usuwania plików",
"background_downloads_enabled": "Pobieranie w tle włączone", "background_downloads_enabled": "Pobieranie w tle włączone",
"background_downloads_disabled": "Pobieranie w tle wyłączone" "background_downloads_disabled": "Pobieranie w tle wyłączone"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "Nowa aktualizacja wymaga ponownego pobrania treści. Usuń wszystkie pobrane materiały i spróbuj ponownie.", "new_app_version_requires_re_download_description": "Nowa aktualizacja wymaga ponownego pobrania treści. Usuń wszystkie pobrane materiały i spróbuj ponownie.",
"back": "Wstecz", "back": "Wstecz",
"delete": "Usuń", "delete": "Usuń",
"delete_download": "Delete Download",
"something_went_wrong": "Coś poszło nie tak", "something_went_wrong": "Coś poszło nie tak",
"could_not_get_stream_url_from_jellyfin": "Nie udało się pobrać adresu URL transmisji z Jellyfin", "could_not_get_stream_url_from_jellyfin": "Nie udało się pobrać adresu URL transmisji z Jellyfin",
"eta": "Szacowany czas: {{eta}}", "eta": "Szacowany czas: {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Wybierz", "select": "Wybierz",
"no_trailer_available": "Brak dostępnego zwiastunu", "no_trailer_available": "Brak dostępnego zwiastunu",
"video": "Wideo", "video": "Wideo",
"audio": "Dźwięk", "audio": "Dźwięk",
"subtitle": "Napisy", "subtitle": "Napisy",
"play": "Odtwórz", "play": "Odtwórz",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "Nic", "none": "Nic",
"track": "Utwór", "track": "Utwór",
"cancel": "Anuluj", "cancel": "Anuluj",
"stop": "Stop",
"delete": "Usuń", "delete": "Usuń",
"ok": "OK", "ok": "OK",
"remove": "Usuń", "remove": "Usuń",
"next": "Następne", "next": "Następne",
"back": "Poprzednie", "back": "Poprzednie",
"continue": "Kontynuuj", "continue": "Kontynuuj",
"verifying": "Weryfikacja..." "verifying": "Weryfikacja...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Szukaj...", "search": "Szukaj...",
@@ -556,6 +641,7 @@
"movies": "filmy", "movies": "filmy",
"series": "seriale", "series": "seriale",
"boxsets": "zestawy", "boxsets": "zestawy",
"playlists": "Playlists",
"items": "elementy" "items": "elementy"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Plakat", "poster": "Plakat",
"cover": "Okładka", "cover": "Okładka",
"show_titles": "Pokaż tytuły", "show_titles": "Pokaż tytuły",
"show_stats": "Pokaż statystyki" "show_stats": "Pokaż statystyki",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Gatunki", "genres": "Gatunki",
@@ -574,7 +661,11 @@
"sort_by": "Sortuj według", "sort_by": "Sortuj według",
"filter_by": "Filtruj po", "filter_by": "Filtruj po",
"sort_order": "Kolejność sortowania", "sort_order": "Kolejność sortowania",
"tags": "Tagi" "tags": "Tagi",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "Brak odnośników" "no_links": "Brak odnośników"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Błąd", "error": "Błąd",
"failed_to_get_stream_url": "Nie udało się pobrać adresu strumienia", "failed_to_get_stream_url": "Nie udało się pobrać adresu strumienia",
"an_error_occured_while_playing_the_video": "Wystąpił błąd podczas odtwarzania wideo. Sprawdź logi w ustawieniach.", "an_error_occured_while_playing_the_video": "Wystąpił błąd podczas odtwarzania wideo. Sprawdź logi w ustawieniach.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Chcesz odtworzyć pobrany plik?", "downloaded_file_message": "Chcesz odtworzyć pobrany plik?",
"downloaded_file_yes": "Tak", "downloaded_file_yes": "Tak",
"downloaded_file_no": "Nie", "downloaded_file_no": "Nie",
"downloaded_file_cancel": "Anuluj" "downloaded_file_cancel": "Anuluj",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "Następne", "next_up": "Następne",
@@ -617,6 +738,11 @@
"series": "Serial", "series": "Serial",
"seasons": "Sezony", "seasons": "Sezony",
"season": "Sezon", "season": "Sezon",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "Brak odcinków w tym sezonie", "no_episodes_for_this_season": "Brak odcinków w tym sezonie",
"overview": "Opis", "overview": "Opis",
"more_with": "Więcej z {{name}}", "more_with": "Więcej z {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Ustawienia mediów", "media_options": "Ustawienia mediów",
"quality": "Jakość", "quality": "Jakość",
"audio": "Dźwięk", "audio": "Dźwięk",
"subtitles": "Napisy", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Pokaż więcej", "show_more": "Pokaż więcej",
"show_less": "Pokaż mniej", "show_less": "Pokaż mniej",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Wystąpił w", "appeared_in": "Wystąpił w",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Nie udało się wczytać elementu", "could_not_load_item": "Nie udało się wczytać elementu",
"none": "Brak", "none": "Brak",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Pobierz {{item_count}} elementów", "download_x_item": "Pobierz {{item_count}} elementów",
"download_unwatched_only": "Tylko nieobejrzane", "download_unwatched_only": "Tylko nieobejrzane",
"download_button": "Pobierz" "download_button": "Pobierz"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Następny", "next": "Następny",
@@ -652,7 +795,18 @@
"movies": "Filmy", "movies": "Filmy",
"sports": "Sport", "sports": "Sport",
"for_kids": "Dla dzieci", "for_kids": "Dla dzieci",
"news": "Wiadomości" "news": "Wiadomości",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Potwierdź", "confirm": "Potwierdź",
@@ -697,6 +851,12 @@
"decline": "Odrzuć", "decline": "Odrzuć",
"requested_by": "Poproszone przez {{user}}", "requested_by": "Poproszone przez {{user}}",
"unknown_user": "Nieznany użytkownik", "unknown_user": "Nieznany użytkownik",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Serwer Jellyseerr nie spełnia minimalnych wymagań wersji! Zaktualizuj go co najmniej do wersji 2.0.0", "jellyseer_does_not_meet_requirements": "Serwer Jellyseerr nie spełnia minimalnych wymagań wersji! Zaktualizuj go co najmniej do wersji 2.0.0",
"jellyseerr_test_failed": "Test Jellyseerr nie powiódł się. Spróbuj ponownie.", "jellyseerr_test_failed": "Test Jellyseerr nie powiódł się. Spróbuj ponownie.",
@@ -716,7 +876,8 @@
"search": "Szukaj", "search": "Szukaj",
"library": "Biblioteka", "library": "Biblioteka",
"custom_links": "Niestandardowe odnośniki", "custom_links": "Niestandardowe odnośniki",
"favorites": "Ulubione" "favorites": "Ulubione",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Muzyka", "title": "Muzyka",
@@ -841,5 +1002,36 @@
"show": "Ten odcinek", "show": "Ten odcinek",
"all": "Wszystkie media (domyślne)" "all": "Wszystkie media (domyślne)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Erro", "error_title": "Erro",
"login_title": "Iniciar sessão", "login_title": "Iniciar sessão",
"login_to_title": "Iniciar sessão em", "login_to_title": "Iniciar sessão em",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Usuário", "username_placeholder": "Usuário",
"password_placeholder": "Palavra-passe", "password_placeholder": "Palavra-passe",
"login_button": "Iniciar sessão", "login_button": "Iniciar sessão",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} accounts",
"select_account": "Select Account", "select_account": "Select Account",
"add_account": "Add Account", "add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "This will remove the saved credentials for {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "Save Account",
@@ -86,6 +95,7 @@
"oops": "Opa!", "oops": "Opa!",
"error_message": "Algo deu errado.\nPor favor, saia e entre novamente.", "error_message": "Algo deu errado.\nPor favor, saia e entre novamente.",
"continue_watching": "Continuar assistindo", "continue_watching": "Continuar assistindo",
"continue": "Continue",
"next_up": "A Seguir", "next_up": "A Seguir",
"continue_and_next_up": "Continuar e Próximo", "continue_and_next_up": "Continuar e Próximo",
"recently_added_in": "Adicionado recentemente em {{libraryName}}", "recently_added_in": "Adicionado recentemente em {{libraryName}}",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Confirgurações", "settings_title": "Confirgurações",
"log_out_button": "Encerrar Sessão", "log_out_button": "Encerrar Sessão",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Categorias" "title": "Categorias"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Aparência", "title": "Aparência",
"merge_next_up_continue_watching": "Mesclar Continuar Assistindo e Próximo", "merge_next_up_continue_watching": "Mesclar Continuar Assistindo e Próximo",
"hide_remote_session_button": "Esconder botão de sessão remota" "hide_remote_session_button": "Esconder botão de sessão remota",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "Network",
@@ -174,6 +199,22 @@
"rewind_length": "Comprimento de Retroceder", "rewind_length": "Comprimento de Retroceder",
"seconds_unit": "s" "seconds_unit": "s"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Controles de Gestos", "gesture_controls_title": "Controles de Gestos",
"horizontal_swipe_skip": "Deslizar horizontalmente para pular", "horizontal_swipe_skip": "Deslizar horizontalmente para pular",
@@ -256,7 +297,23 @@
"subtitle_font": "Fonte da legenda", "subtitle_font": "Fonte da legenda",
"ksplayer_title": "Configurações do KSPlayer", "ksplayer_title": "Configurações do KSPlayer",
"hardware_decode": "Decodificação por hardware", "hardware_decode": "Decodificação por hardware",
"hardware_decode_description": "Use aceleração de hardware para decodificação de vídeo. Desative se você tiver problemas de reprodução." "hardware_decode_description": "Use aceleração de hardware para decodificação de vídeo. Desative se você tiver problemas de reprodução.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "VLC Subtitle Settings",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Cache de música limpo", "music_cache_cleared": "Cache de música limpo",
"delete_all_downloaded_songs": "Excluir todas as músicas baixadas", "delete_all_downloaded_songs": "Excluir todas as músicas baixadas",
"downloaded_songs_size": "{{size}} baixado", "downloaded_songs_size": "{{size}} baixado",
"downloaded_songs_deleted": "Músicas baixadas excluídas" "downloaded_songs_deleted": "Músicas baixadas excluídas",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Intro", "title": "Intro",
@@ -430,6 +493,21 @@
"error_deleting_files": "Erro ao excluir arquivos", "error_deleting_files": "Erro ao excluir arquivos",
"background_downloads_enabled": "Downloads em segundo plano ativados", "background_downloads_enabled": "Downloads em segundo plano ativados",
"background_downloads_disabled": "Downloads em segundo plano desativados" "background_downloads_disabled": "Downloads em segundo plano desativados"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "A nova atualização requer que o conteúdo seja baixado novamente. Por favor, remova todo o conteúdo baixado e tente novamente.", "new_app_version_requires_re_download_description": "A nova atualização requer que o conteúdo seja baixado novamente. Por favor, remova todo o conteúdo baixado e tente novamente.",
"back": "Anterior", "back": "Anterior",
"delete": "excluir", "delete": "excluir",
"delete_download": "Delete Download",
"something_went_wrong": "Ocorreu Um Erro", "something_went_wrong": "Ocorreu Um Erro",
"could_not_get_stream_url_from_jellyfin": "Não foi possível obter o URL de transmissão do Jellyfin", "could_not_get_stream_url_from_jellyfin": "Não foi possível obter o URL de transmissão do Jellyfin",
"eta": "ETA {{eta}}", "eta": "ETA {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Selecionar", "select": "Selecionar",
"no_trailer_available": "Nenhum trailer disponível", "no_trailer_available": "Nenhum trailer disponível",
"video": "Vídeo", "video": "Vídeo",
"audio": "Áudio", "audio": "Áudio",
"subtitle": "Legenda", "subtitle": "Legenda",
"play": "Reproduzir", "play": "Reproduzir",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "Nenhum", "none": "Nenhum",
"track": "Faixa", "track": "Faixa",
"cancel": "Cancelar", "cancel": "Cancelar",
"stop": "Stop",
"delete": "Apagar", "delete": "Apagar",
"ok": "OK", "ok": "OK",
"remove": "Remover", "remove": "Remover",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"continue": "Continue", "continue": "Continue",
"verifying": "Verifying..." "verifying": "Verifying...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Buscar...", "search": "Buscar...",
@@ -556,6 +641,7 @@
"movies": "Filmes", "movies": "Filmes",
"series": "Série", "series": "Série",
"boxsets": "Conjuntos de caixas", "boxsets": "Conjuntos de caixas",
"playlists": "Playlists",
"items": "itens" "items": "itens"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Cartaz", "poster": "Cartaz",
"cover": "Capa", "cover": "Capa",
"show_titles": "Mostrar Títulos", "show_titles": "Mostrar Títulos",
"show_stats": "Mostrar estatísticas" "show_stats": "Mostrar estatísticas",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Genres", "genres": "Genres",
@@ -574,7 +661,11 @@
"sort_by": "Classificar por", "sort_by": "Classificar por",
"filter_by": "Filtrar Por", "filter_by": "Filtrar Por",
"sort_order": "Ordem de classificação", "sort_order": "Ordem de classificação",
"tags": "Etiquetas" "tags": "Etiquetas",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "Sem links" "no_links": "Sem links"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "ERRO", "error": "ERRO",
"failed_to_get_stream_url": "Falha ao obter a URL de transmissão", "failed_to_get_stream_url": "Falha ao obter a URL de transmissão",
"an_error_occured_while_playing_the_video": "Ocorreu um erro ao reproduzir o vídeo. Verifique os logs nas configurações.", "an_error_occured_while_playing_the_video": "Ocorreu um erro ao reproduzir o vídeo. Verifique os logs nas configurações.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Você quer reproduzir o arquivo baixado?", "downloaded_file_message": "Você quer reproduzir o arquivo baixado?",
"downloaded_file_yes": "SIm", "downloaded_file_yes": "SIm",
"downloaded_file_no": "Não", "downloaded_file_no": "Não",
"downloaded_file_cancel": "Cancelar" "downloaded_file_cancel": "Cancelar",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "A Seguir", "next_up": "A Seguir",
@@ -617,6 +738,11 @@
"series": "Série", "series": "Série",
"seasons": "Estações", "seasons": "Estações",
"season": "Temporada", "season": "Temporada",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "Não há episódios para esta temporada", "no_episodes_for_this_season": "Não há episódios para esta temporada",
"overview": "Geral", "overview": "Geral",
"more_with": "Mais com {{name}}", "more_with": "Mais com {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Opções de Mídia", "media_options": "Opções de Mídia",
"quality": "Qualidade", "quality": "Qualidade",
"audio": "Áudio", "audio": "Áudio",
"subtitles": "Legenda", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Mostrar mais", "show_more": "Mostrar mais",
"show_less": "Mostrar menos", "show_less": "Mostrar menos",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Aparece em", "appeared_in": "Aparece em",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Não foi possível carregar o item", "could_not_load_item": "Não foi possível carregar o item",
"none": "Nenhuma", "none": "Nenhuma",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Baixar itens de {{item_count}}", "download_x_item": "Baixar itens de {{item_count}}",
"download_unwatched_only": "Apenas não assistidos", "download_unwatched_only": "Apenas não assistidos",
"download_button": "BAIXAR" "download_button": "BAIXAR"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Próximo", "next": "Próximo",
@@ -652,7 +795,18 @@
"movies": "Filmes", "movies": "Filmes",
"sports": "Esportes", "sports": "Esportes",
"for_kids": "Para crianças", "for_kids": "Para crianças",
"news": "Notícias" "news": "Notícias",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Confirmar", "confirm": "Confirmar",
@@ -697,6 +851,12 @@
"decline": "Declinar", "decline": "Declinar",
"requested_by": "Solicitado por {{user}}", "requested_by": "Solicitado por {{user}}",
"unknown_user": "Usuário desconhecido", "unknown_user": "Usuário desconhecido",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "O servidor do Seerr não atende ao mínimo aos requisitos de versão! Por favor, atualize para pelo menos 2.0.0", "jellyseer_does_not_meet_requirements": "O servidor do Seerr não atende ao mínimo aos requisitos de versão! Por favor, atualize para pelo menos 2.0.0",
"jellyseerr_test_failed": "Falha no teste do senhor. Por favor, tente novamente.", "jellyseerr_test_failed": "Falha no teste do senhor. Por favor, tente novamente.",
@@ -716,7 +876,8 @@
"search": "Pesquisa", "search": "Pesquisa",
"library": "Biblioteca", "library": "Biblioteca",
"custom_links": "Links personalizados", "custom_links": "Links personalizados",
"favorites": "Atalhos" "favorites": "Atalhos",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Música", "title": "Música",
@@ -841,5 +1002,36 @@
"show": "Esta série", "show": "Esta série",
"all": "Todas as mídias (Padrão)" "all": "Todas as mídias (Padrão)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Eroare", "error_title": "Eroare",
"login_title": "Conectare", "login_title": "Conectare",
"login_to_title": "Conectare la", "login_to_title": "Conectare la",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Utilizator", "username_placeholder": "Utilizator",
"password_placeholder": "Parola", "password_placeholder": "Parola",
"login_button": "Conectare", "login_button": "Conectare",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} accounts",
"select_account": "Select Account", "select_account": "Select Account",
"add_account": "Add Account", "add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "This will remove the saved credentials for {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "Save Account",
@@ -86,6 +95,7 @@
"oops": "Ups!", "oops": "Ups!",
"error_message": "Ceva nu e bine.\nAutentificați-vă din nou.", "error_message": "Ceva nu e bine.\nAutentificați-vă din nou.",
"continue_watching": "Continuă vizionarea", "continue_watching": "Continuă vizionarea",
"continue": "Continue",
"next_up": "Urmează", "next_up": "Urmează",
"continue_and_next_up": "Continue & Next Up", "continue_and_next_up": "Continue & Next Up",
"recently_added_in": "Adăugat recent în {{libraryName}}", "recently_added_in": "Adăugat recent în {{libraryName}}",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Setări", "settings_title": "Setări",
"log_out_button": "Deconectare", "log_out_button": "Deconectare",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Categorii" "title": "Categorii"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Aspect", "title": "Aspect",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up", "merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button" "hide_remote_session_button": "Hide Remote Session Button",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "Network",
@@ -174,6 +199,22 @@
"rewind_length": "Durata saltului înapoi", "rewind_length": "Durata saltului înapoi",
"seconds_unit": "S" "seconds_unit": "S"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Controale gesturi", "gesture_controls_title": "Controale gesturi",
"horizontal_swipe_skip": "Glisați orizontal pentru a sări", "horizontal_swipe_skip": "Glisați orizontal pentru a sări",
@@ -256,7 +297,23 @@
"subtitle_font": "Subtitle Font", "subtitle_font": "Subtitle Font",
"ksplayer_title": "KSPlayer Settings", "ksplayer_title": "KSPlayer Settings",
"hardware_decode": "Hardware Decoding", "hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues." "hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "VLC Subtitle Settings",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Music cache cleared", "music_cache_cleared": "Music cache cleared",
"delete_all_downloaded_songs": "Delete All Downloaded Songs", "delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded", "downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "Downloaded songs deleted",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Introducere", "title": "Introducere",
@@ -430,6 +493,21 @@
"error_deleting_files": "Eroare la ștergerea fișierelor", "error_deleting_files": "Eroare la ștergerea fișierelor",
"background_downloads_enabled": "Descărcări în fundal activate", "background_downloads_enabled": "Descărcări în fundal activate",
"background_downloads_disabled": "Descărcări în fundal dezactivate" "background_downloads_disabled": "Descărcări în fundal dezactivate"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "Noua actualizare necesită descărcarea din nou a conținutului. Vă rugăm să eliminați tot conținutul descărcat și să încercați din nou.", "new_app_version_requires_re_download_description": "Noua actualizare necesită descărcarea din nou a conținutului. Vă rugăm să eliminați tot conținutul descărcat și să încercați din nou.",
"back": "Înapoi", "back": "Înapoi",
"delete": "Șterge", "delete": "Șterge",
"delete_download": "Delete Download",
"something_went_wrong": "Ceva nu a mers bine.", "something_went_wrong": "Ceva nu a mers bine.",
"could_not_get_stream_url_from_jellyfin": "Nu s-a putut obține adresa URL a fluxului de la Jellyfin", "could_not_get_stream_url_from_jellyfin": "Nu s-a putut obține adresa URL a fluxului de la Jellyfin",
"eta": "Estimat {{eta}}", "eta": "Estimat {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Selectare", "select": "Selectare",
"no_trailer_available": "Nicio remorcă disponibilă", "no_trailer_available": "Nicio remorcă disponibilă",
"video": "Video", "video": "Video",
"audio": "Audio", "audio": "Audio",
"subtitle": "Subtitrare", "subtitle": "Subtitrare",
"play": "Redare", "play": "Redare",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "Nimic", "none": "Nimic",
"track": "Limbă audio", "track": "Limbă audio",
"cancel": "Cancel", "cancel": "Cancel",
"stop": "Stop",
"delete": "Delete", "delete": "Delete",
"ok": "OK", "ok": "OK",
"remove": "Remove", "remove": "Remove",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"continue": "Continue", "continue": "Continue",
"verifying": "Verifying..." "verifying": "Verifying...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Caută...", "search": "Caută...",
@@ -556,6 +641,7 @@
"movies": "filme", "movies": "filme",
"series": "seriale", "series": "seriale",
"boxsets": "box sets", "boxsets": "box sets",
"playlists": "Playlists",
"items": "articole" "items": "articole"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Poster", "poster": "Poster",
"cover": "Copertă", "cover": "Copertă",
"show_titles": "Afișează titlurile", "show_titles": "Afișează titlurile",
"show_stats": "Afișează statisticile" "show_stats": "Afișează statisticile",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Genuri", "genres": "Genuri",
@@ -574,7 +661,11 @@
"sort_by": "Sortează după", "sort_by": "Sortează după",
"filter_by": "Filter By", "filter_by": "Filter By",
"sort_order": "Ordine de sortare", "sort_order": "Ordine de sortare",
"tags": "Taguri" "tags": "Taguri",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "Niciun link" "no_links": "Niciun link"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Eroare", "error": "Eroare",
"failed_to_get_stream_url": "Nu s-a putut obține adresa URL a fluxului", "failed_to_get_stream_url": "Nu s-a putut obține adresa URL a fluxului",
"an_error_occured_while_playing_the_video": "A apărut o eroare la redarea videoclipului. Verificați jurnalele în setări.", "an_error_occured_while_playing_the_video": "A apărut o eroare la redarea videoclipului. Verificați jurnalele în setări.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Doriți să redați fișierul descărcat?", "downloaded_file_message": "Doriți să redați fișierul descărcat?",
"downloaded_file_yes": "Da", "downloaded_file_yes": "Da",
"downloaded_file_no": "Nu", "downloaded_file_no": "Nu",
"downloaded_file_cancel": "Anulează" "downloaded_file_cancel": "Anulează",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "Urmează", "next_up": "Urmează",
@@ -617,6 +738,11 @@
"series": "Seriale", "series": "Seriale",
"seasons": "Sezoane", "seasons": "Sezoane",
"season": "Sezon", "season": "Sezon",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "Niciun episod pt acest sezon", "no_episodes_for_this_season": "Niciun episod pt acest sezon",
"overview": "Prezentare generală", "overview": "Prezentare generală",
"more_with": "Mai multe cu {{name}}", "more_with": "Mai multe cu {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Opțiuni Media", "media_options": "Opțiuni Media",
"quality": "Calitate", "quality": "Calitate",
"audio": "Audio", "audio": "Audio",
"subtitles": "Subtitrare", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Arată mai mult", "show_more": "Arată mai mult",
"show_less": "Arată mai puțin", "show_less": "Arată mai puțin",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Apare în", "appeared_in": "Apare în",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Nu s-a putut încărca elementul", "could_not_load_item": "Nu s-a putut încărca elementul",
"none": "Nimic", "none": "Nimic",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Descărcați {{item_count}} articole", "download_x_item": "Descărcați {{item_count}} articole",
"download_unwatched_only": "Numai nevizionate", "download_unwatched_only": "Numai nevizionate",
"download_button": "Descarcă" "download_button": "Descarcă"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Următorul", "next": "Următorul",
@@ -652,7 +795,18 @@
"movies": "Filme", "movies": "Filme",
"sports": "Sport", "sports": "Sport",
"for_kids": "Pt copii", "for_kids": "Pt copii",
"news": "Știri" "news": "Știri",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Confirmă", "confirm": "Confirmă",
@@ -697,6 +851,12 @@
"decline": "Respinge", "decline": "Respinge",
"requested_by": "Solicitat de {{user}}", "requested_by": "Solicitat de {{user}}",
"unknown_user": "Utilizator necunoscut", "unknown_user": "Utilizator necunoscut",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Serverul Jellyseerr nu îndeplinește cerințele minime de versiune! Vă rugăm să actualizați cel puțin la versiunea 2.0.0", "jellyseer_does_not_meet_requirements": "Serverul Jellyseerr nu îndeplinește cerințele minime de versiune! Vă rugăm să actualizați cel puțin la versiunea 2.0.0",
"jellyseerr_test_failed": "Testul Jellyseerr a eșuat. Vă rugăm să încercați din nou.", "jellyseerr_test_failed": "Testul Jellyseerr a eșuat. Vă rugăm să încercați din nou.",
@@ -716,7 +876,8 @@
"search": "Caută", "search": "Caută",
"library": "Bibiliotecă", "library": "Bibiliotecă",
"custom_links": "Linkuri personalizate", "custom_links": "Linkuri personalizate",
"favorites": "Favorite" "favorites": "Favorite",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Music", "title": "Music",
@@ -841,5 +1002,36 @@
"show": "This show", "show": "This show",
"all": "All media (default)" "all": "All media (default)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Ошибка", "error_title": "Ошибка",
"login_title": "Вход", "login_title": "Вход",
"login_to_title": "Вход в", "login_to_title": "Вход в",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Имя пользователя", "username_placeholder": "Имя пользователя",
"password_placeholder": "Пароль", "password_placeholder": "Пароль",
"login_button": "Войти", "login_button": "Войти",
@@ -12,25 +15,25 @@
"failed_to_initiate_quick_connect": "Не удалось инициировать быстрое подключение", "failed_to_initiate_quick_connect": "Не удалось инициировать быстрое подключение",
"got_it": "Принято", "got_it": "Принято",
"connection_failed": "Соединение не удалось", "connection_failed": "Соединение не удалось",
"could_not_connect_to_server": "Не удалось подключиться к серверу. Пожалуйста проверьте URL и ваше интернет соединение.", "could_not_connect_to_server": "Не удалось подключиться к серверу. Пожалуйста, проверьте URL и ваше интернет-соединение.",
"an_unexpected_error_occured": "Возникла непредвиденная ошибка", "an_unexpected_error_occured": "Возникла непредвиденная ошибка",
"change_server": "Поменять сервер", "change_server": "Поменять сервер",
"invalid_username_or_password": "Неправильное имя пользователя или пароль", "invalid_username_or_password": "Неправильное имя пользователя или пароль",
"user_does_not_have_permission_to_log_in": "Пользователь не имеет прав на вход", "user_does_not_have_permission_to_log_in": "Пользователь не имеет прав на вход",
"server_is_taking_too_long_to_respond_try_again_later": "Сервер долго не отвечает, попробуйте позже.", "server_is_taking_too_long_to_respond_try_again_later": "Сервер долго не отвечает, попробуйте позже",
"server_received_too_many_requests_try_again_later": "Сервер получил слишком много запросов, попробуйте позже.", "server_received_too_many_requests_try_again_later": "Сервер получил слишком много запросов, попробуйте позже.",
"there_is_a_server_error": "Возникла ошибка сервера", "there_is_a_server_error": "Возникла ошибка сервера",
"an_unexpected_error_occured_did_you_enter_the_correct_url": "Возникла непредвиденная ошибка. Вы правильно ввели URL?", "an_unexpected_error_occured_did_you_enter_the_correct_url": "Возникла непредвиденная ошибка. Вы правильно ввели URL?",
"too_old_server_text": "Неподдерживаемый сервер Jellyfin обнаружен", "too_old_server_text": "Обнаружен неподдерживаемый сервер Jellyfin",
"too_old_server_description": "Пожалуйста, обновите Jellyfin до последней версии" "too_old_server_description": "Пожалуйста, обновите Jellyfin до последней версии"
}, },
"server": { "server": {
"enter_url_to_jellyfin_server": "Укажите URL на ваш Jellyfin сервер", "enter_url_to_jellyfin_server": "Укажите URL на ваш Jellyfin сервер",
"server_url_placeholder": "http(s)://your-server.com", "server_url_placeholder": "http(s)://your-server.com",
"connect_button": "Подключиться", "connect_button": "Подключиться",
"previous_servers": "предыдущие серверы", "previous_servers": "Предыдущие серверы",
"clear_button": "Очистить", "clear_button": "Очистить",
"swipe_to_remove": "Swipe to remove", "swipe_to_remove": "Смахните для удаления",
"search_for_local_servers": "Поиск локальных серверов", "search_for_local_servers": "Поиск локальных серверов",
"searching": "Поиск...", "searching": "Поиск...",
"servers": "Сервера", "servers": "Сервера",
@@ -39,10 +42,16 @@
"please_login_again": "Ваша сессия истекла. Пожалуйста, войдите снова.", "please_login_again": "Ваша сессия истекла. Пожалуйста, войдите снова.",
"remove_saved_login": "Удалить сохраненный аккаунт", "remove_saved_login": "Удалить сохраненный аккаунт",
"remove_saved_login_description": "Ваши сохранённые данные для входа от этого сервера будут удалены. Вам придётся ввести ваши логин и пароль ещё раз.", "remove_saved_login_description": "Ваши сохранённые данные для входа от этого сервера будут удалены. Вам придётся ввести ваши логин и пароль ещё раз.",
"accounts_count": "{{count}} аккаунтов", "accounts_count": "Аккаунтов: {{count}}",
"select_account": "Выбрать аккаунт", "select_account": "Выбрать аккаунт",
"add_account": "Добавить аккаунт", "add_account": "Добавить аккаунт",
"remove_account_description": "Данные для входа {{username}} будут удалены." "remove_account_description": "Данные для входа {{username}} будут удалены.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Сохранить аккаунт", "title": "Сохранить аккаунт",
@@ -58,14 +67,14 @@
"cancel_button": "Отмена" "cancel_button": "Отмена"
}, },
"pin": { "pin": {
"enter_pin": "Введите PIN", "enter_pin": "Введите PIN-код",
"enter_pin_for": "Введите PIN для {{username}}", "enter_pin_for": "Введите PIN-код для {{username}}",
"enter_4_digits": "Введите 4 цифры", "enter_4_digits": "Введите 4 цифры",
"invalid_pin": "Некорректный PIN", "invalid_pin": "Некорректный PIN-код",
"setup_pin": "Установить PIN", "setup_pin": "Установить PIN-код",
"confirm_pin": "Подтвердите PIN", "confirm_pin": "Подтвердите PIN-код",
"pins_dont_match": "PIN-коды не совпадают", "pins_dont_match": "PIN-коды не совпадают",
"forgot_pin": "Забыли PIN?", "forgot_pin": "Забыли PIN-код?",
"forgot_pin_desc": "Ваши данные для входа будут удалены" "forgot_pin_desc": "Ваши данные для входа будут удалены"
}, },
"password": { "password": {
@@ -84,8 +93,9 @@
"server_unreachable": "Сервер недоступен", "server_unreachable": "Сервер недоступен",
"server_unreachable_message": "Не удалось соединиться с сервером.\nПожалуйста, проверьте настройки сети.", "server_unreachable_message": "Не удалось соединиться с сервером.\nПожалуйста, проверьте настройки сети.",
"oops": "Упс!", "oops": "Упс!",
"error_message": "Что-то пошло не так.\nПожалуйста выйдите и зайдите снова.", "error_message": "Что-то пошло не так.\nПожалуйста, выйдите и зайдите снова.",
"continue_watching": "Продолжить", "continue_watching": "Продолжить",
"continue": "Continue",
"next_up": "Далее", "next_up": "Далее",
"continue_and_next_up": "Продолжить и Далее", "continue_and_next_up": "Продолжить и Далее",
"recently_added_in": "Недавно добавлено в {{libraryName}}", "recently_added_in": "Недавно добавлено в {{libraryName}}",
@@ -93,13 +103,13 @@
"suggested_episodes": "Предложенные серии", "suggested_episodes": "Предложенные серии",
"intro": { "intro": {
"welcome_to_streamyfin": "Добро пожаловать в Streamyfin", "welcome_to_streamyfin": "Добро пожаловать в Streamyfin",
"a_free_and_open_source_client_for_jellyfin": "Бесплатный клиент для Jellyfin с открытым кодом", "a_free_and_open_source_client_for_jellyfin": "Бесплатный клиент для Jellyfin с открытым кодом.",
"features_title": "Функции", "features_title": "Функции",
"features_description": "Streamyfin имеет множество функций и интегрируется с широким спектром программ, которое вы можете найти в меню настроек:", "features_description": "Streamyfin имеет множество функций и интегрируется с широким спектром программ, которое вы можете найти в меню настроек:",
"jellyseerr_feature_description": "Подключитесь к Jellyseerr и запрашивайте фильмы прямо в приложении.", "jellyseerr_feature_description": "Подключитесь к Jellyseerr и запрашивайте фильмы прямо в приложении.",
"downloads_feature_title": "Загрузки", "downloads_feature_title": "Загрузки",
"downloads_feature_description": "Скачивайте фильмы и сериалы для просмотра без интернета. Используйте стандартный способ или установите сервер оптимизации для загрузки файлов в фоновом режиме.", "downloads_feature_description": "Скачивайте фильмы и сериалы для просмотра без интернета. Используйте стандартный способ или установите сервер оптимизации для загрузки файлов в фоновом режиме.",
"chromecast_feature_description": "Транслируйте фильмы и сериалы на ваши устройста с поддержкой Chromecast.", "chromecast_feature_description": "Транслируйте фильмы и сериалы на ваши устройства с поддержкой Chromecast.",
"centralised_settings_plugin_title": "Плагин для централизованной настройки", "centralised_settings_plugin_title": "Плагин для централизованной настройки",
"centralised_settings_plugin_description": "Настраивайте параметры из централизованного места на сервере Jellyfin. Все настройки клиента для всех пользователей будут синхронизированы автоматически.", "centralised_settings_plugin_description": "Настраивайте параметры из централизованного места на сервере Jellyfin. Все настройки клиента для всех пользователей будут синхронизированы автоматически.",
"done_button": "Готово", "done_button": "Готово",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Настройки", "settings_title": "Настройки",
"log_out_button": "Выйти", "log_out_button": "Выйти",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Категории" "title": "Категории"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Внешний вид", "title": "Внешний вид",
"merge_next_up_continue_watching": "Объединить «Продолжить» и «Далее»", "merge_next_up_continue_watching": "Объединить «Продолжить» и «Далее»",
"hide_remote_session_button": "Скрыть кнопку «Удалённый сеанс»" "hide_remote_session_button": "Скрыть кнопку «Удалённый сеанс»",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Сеть", "title": "Сеть",
@@ -129,7 +154,7 @@
"auto_switch_enabled": "Переключаться дома автоматически", "auto_switch_enabled": "Переключаться дома автоматически",
"auto_switch_description": "Автоматически переключаться на локальный URL при присоединении к домашней WiFi сети", "auto_switch_description": "Автоматически переключаться на локальный URL при присоединении к домашней WiFi сети",
"local_url": "Локальный URL", "local_url": "Локальный URL",
"local_url_hint": "Введите локальный URL вашего сервера (e.g., http://192.168.1.100:8096)", "local_url_hint": "Введите локальный URL вашего сервера (например, http://192.168.1.100:8096)",
"local_url_placeholder": "http://192.168.1.100:8096", "local_url_placeholder": "http://192.168.1.100:8096",
"home_wifi_networks": "Домашние WiFi сети", "home_wifi_networks": "Домашние WiFi сети",
"add_current_network": "Добавить \"{{ssid}}\"", "add_current_network": "Добавить \"{{ssid}}\"",
@@ -160,28 +185,44 @@
}, },
"quick_connect": { "quick_connect": {
"quick_connect_title": "Быстрое подключение", "quick_connect_title": "Быстрое подключение",
"authorize_button": "Авторизировать через быстрое подключение", "authorize_button": "Авторизовать через быстрое подключение",
"enter_the_quick_connect_code": "Введите код для быстрого подключения...", "enter_the_quick_connect_code": "Введите код для быстрого подключения...",
"success": "Успех", "success": "Успех",
"quick_connect_autorized": "Быстрое подключение авторизовано", "quick_connect_autorized": "Быстрое подключение авторизовано",
"error": "Ошибка", "error": "Ошибка",
"invalid_code": "Неверный код", "invalid_code": "Неверный код",
"authorize": "Авторизировать" "authorize": "Авторизовать"
}, },
"media_controls": { "media_controls": {
"media_controls_title": "Медиа-контроль", "media_controls_title": "Управление воспроизведением",
"forward_skip_length": "Шаг перемотки вперёд", "forward_skip_length": "Шаг перемотки вперёд",
"rewind_length": "Шаг перемотки назад", "rewind_length": "Шаг перемотки назад",
"seconds_unit": "c" "seconds_unit": "c"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Управление жестами", "gesture_controls_title": "Управление жестами",
"horizontal_swipe_skip": "Горизонтальный свайп для перемотки", "horizontal_swipe_skip": "Проведите влево/вправо для перемотки",
"horizontal_swipe_skip_description": "Проведите влево/вправо, когда элементы управления скрыты, чтобы пропустить", "horizontal_swipe_skip_description": "Проведите влево/вправо, когда элементы управления скрыты, чтобы перемотать",
"left_side_brightness": "Управление яркостью левой стороны", "left_side_brightness": "Управление яркостью слева",
"left_side_brightness_description": "Смахните вверх/вниз на левой стороне для настройки яркости", "left_side_brightness_description": "Проведите вверх/вниз на левой стороне для настройки яркости",
"right_side_volume": "Управление громкостью справа", "right_side_volume": "Управление громкостью справа",
"right_side_volume_description": "Свайп вверх/вниз с правой стороны для настройки громкости", "right_side_volume_description": "Проведите вверх/вниз с правой стороны для настройки громкости",
"hide_volume_slider": "Скрыть индикатор громкости", "hide_volume_slider": "Скрыть индикатор громкости",
"hide_volume_slider_description": "Скрывает индикатор громкости в плеере", "hide_volume_slider_description": "Скрывает индикатор громкости в плеере",
"hide_brightness_slider": "Скрыть индикатор яркости", "hide_brightness_slider": "Скрыть индикатор яркости",
@@ -205,7 +246,7 @@
}, },
"subtitles": { "subtitles": {
"subtitle_title": "Субтитры", "subtitle_title": "Субтитры",
"subtitle_hint": "Настройки отображения субтитров", "subtitle_hint": "Настройки отображения субтитров.",
"subtitle_language": "Язык субтитров", "subtitle_language": "Язык субтитров",
"subtitle_mode": "Режим субтитров", "subtitle_mode": "Режим субтитров",
"set_subtitle_track": "Устанавливать субтитры из предыдущего элемента", "set_subtitle_track": "Устанавливать субтитры из предыдущего элемента",
@@ -256,7 +297,23 @@
"subtitle_font": "Шрифт субтитров", "subtitle_font": "Шрифт субтитров",
"ksplayer_title": "Настройки KSPlayer", "ksplayer_title": "Настройки KSPlayer",
"hardware_decode": "Аппаратное декодирование", "hardware_decode": "Аппаратное декодирование",
"hardware_decode_description": "Использовать аппаратное ускорение для декодирования видео. Выключите, если наблюдаете проблемы с воспроизведением." "hardware_decode_description": "Использовать аппаратное ускорение для декодирования видео. Выключите, если наблюдаете проблемы с воспроизведением.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "Настройки субтитров в VLC", "title": "Настройки субтитров в VLC",
@@ -299,7 +356,7 @@
"VLC_3": "VLC 3", "VLC_3": "VLC 3",
"VLC_4": "VLC 4 (Экспериментальный + PiP)" "VLC_4": "VLC 4 (Экспериментальный + PiP)"
}, },
"show_custom_menu_links": "Показать ссылки кастомного меню", "show_custom_menu_links": "Показать ссылки пользовательского меню",
"show_large_home_carousel": "Показывать большую карусель (beta)", "show_large_home_carousel": "Показывать большую карусель (beta)",
"hide_libraries": "Скрыть библиотеки", "hide_libraries": "Скрыть библиотеки",
"select_liraries_you_want_to_hide": "Выберите Библиотеки, которое хотите спрятать из вкладки Библиотеки и домашней страницы.", "select_liraries_you_want_to_hide": "Выберите Библиотеки, которое хотите спрятать из вкладки Библиотеки и домашней страницы.",
@@ -307,7 +364,7 @@
"default_quality": "Качество по умолчанию", "default_quality": "Качество по умолчанию",
"default_playback_speed": "Скорость воспроизведения по умолчанию", "default_playback_speed": "Скорость воспроизведения по умолчанию",
"auto_play_next_episode": "Автоматически воспроизводить следующий эпизод", "auto_play_next_episode": "Автоматически воспроизводить следующий эпизод",
"max_auto_play_episode_count": "Максимальное количество автовоспроизведения эпизодов", "max_auto_play_episode_count": "Максимальное количество авто воспроизводимых эпизодов",
"disabled": "Отключено" "disabled": "Отключено"
}, },
"downloads": { "downloads": {
@@ -319,9 +376,9 @@
"playback_description": "Настройте воспроизведение музыки.", "playback_description": "Настройте воспроизведение музыки.",
"prefer_downloaded": "Предпочитать скачанные песни", "prefer_downloaded": "Предпочитать скачанные песни",
"caching_title": "Кеширование", "caching_title": "Кеширование",
"caching_description": "Автоматически предкешировать следующие треки для стабильного воспроизведения.", "caching_description": "Автоматически кешировать следующие треки для стабильного воспроизведения.",
"lookahead_enabled": "Включить предкеширование", "lookahead_enabled": "Включить предкеширование",
"lookahead_count": "Сколько предкешировать", "lookahead_count": "Сколько треков предкешировать",
"max_cache_size": "Максимальное число предкешированных треков" "max_cache_size": "Максимальное число предкешированных треков"
}, },
"plugins": { "plugins": {
@@ -329,8 +386,8 @@
"jellyseerr": { "jellyseerr": {
"jellyseerr_warning": "Эта интеграция находится на ранней стадии. Ожидайте изменений.", "jellyseerr_warning": "Эта интеграция находится на ранней стадии. Ожидайте изменений.",
"server_url": "URL сервера", "server_url": "URL сервера",
"server_url_hint": "Пример: http(s)://your-host.url\n(Добавьте порт если необходимо)", "server_url_hint": "Пример: http(s)://your-host.url\n(добавьте порт если необходимо)",
"server_url_placeholder": "Jellyseerr URL...", "server_url_placeholder": "Seerr URL...",
"password": "Пароль", "password": "Пароль",
"password_placeholder": "Введите пароль для пользователя Jellyfin {{username}}", "password_placeholder": "Введите пароль для пользователя Jellyfin {{username}}",
"login_button": "Войти", "login_button": "Войти",
@@ -399,14 +456,20 @@
"size_used": "{{used}} из {{total}} использовано", "size_used": "{{used}} из {{total}} использовано",
"delete_all_downloaded_files": "Удалить все загруженные файлы", "delete_all_downloaded_files": "Удалить все загруженные файлы",
"music_cache_title": "Кеш музыки", "music_cache_title": "Кеш музыки",
"music_cache_description": "Автоматически прекешировать песни по мере прослушивания для плавного воспроизведения и поддержки отсутствия интернета", "music_cache_description": "Автоматически кешировать песни по мере прослушивания для плавного воспроизведения и поддержки отсутствия интернета",
"enable_music_cache": "Кешировать музыку", "enable_music_cache": "Кешировать музыку",
"clear_music_cache": "Очистить кеш музыки", "clear_music_cache": "Очистить кеш музыки",
"music_cache_size": "{{size}} кешировано", "music_cache_size": "Кешировано: {{size}}",
"music_cache_cleared": "Кеш музыки очищен", "music_cache_cleared": "Кеш музыки очищен",
"delete_all_downloaded_songs": "Удалить все скачанные песни", "delete_all_downloaded_songs": "Удалить все скачанные песни",
"downloaded_songs_size": "{{size}} скачано", "downloaded_songs_size": "Скачано: {{size}}",
"downloaded_songs_deleted": "Скачанные песни удалены" "downloaded_songs_deleted": "Скачанные песни удалены",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Вступление", "title": "Вступление",
@@ -415,7 +478,7 @@
}, },
"logs": { "logs": {
"logs_title": "Логи", "logs_title": "Логи",
"export_logs": "Экспорт журналов", "export_logs": "Сохранить логи",
"click_for_more_info": "Нажмите для получения дополнительной информации", "click_for_more_info": "Нажмите для получения дополнительной информации",
"level": "Уровень", "level": "Уровень",
"no_logs_available": "Логи не доступны", "no_logs_available": "Логи не доступны",
@@ -430,6 +493,21 @@
"error_deleting_files": "Ошибка при удалении файлов", "error_deleting_files": "Ошибка при удалении файлов",
"background_downloads_enabled": "Фоновая загрузка включена", "background_downloads_enabled": "Фоновая загрузка включена",
"background_downloads_disabled": "Фоновая загрузка отключена" "background_downloads_disabled": "Фоновая загрузка отключена"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -453,9 +531,10 @@
"no_active_downloads": "Нет активных загрузок", "no_active_downloads": "Нет активных загрузок",
"active_downloads": "Активные", "active_downloads": "Активные",
"new_app_version_requires_re_download": "Новая версия приложения требует повторной загрузки", "new_app_version_requires_re_download": "Новая версия приложения требует повторной загрузки",
"new_app_version_requires_re_download_description": "Новая версия приложения требует повторной загрузки. Пожалуйста удалите всё и попробуйте заново.", "new_app_version_requires_re_download_description": "Новая версия приложения требует повторной загрузки контента. Пожалуйста, удалите весь скачанный контент и попробуйте заново.",
"back": "Назад", "back": "Назад",
"delete": "Удалить", "delete": "Удалить",
"delete_download": "Delete Download",
"something_went_wrong": "Что-то пошло не так", "something_went_wrong": "Что-то пошло не так",
"could_not_get_stream_url_from_jellyfin": "Не удалось получить ссылку трансляции из Jellyfin", "could_not_get_stream_url_from_jellyfin": "Не удалось получить ссылку трансляции из Jellyfin",
"eta": "Осталось {{eta}}", "eta": "Осталось {{eta}}",
@@ -465,53 +544,59 @@
"failed_to_delete_all_movies": "Возникла ошибка при удалении всех фильмов", "failed_to_delete_all_movies": "Возникла ошибка при удалении всех фильмов",
"deleted_all_tvseries_successfully": "Все сериалы были успешно удалены!", "deleted_all_tvseries_successfully": "Все сериалы были успешно удалены!",
"failed_to_delete_all_tvseries": "Возникла ошибка при удалении всех сериалов", "failed_to_delete_all_tvseries": "Возникла ошибка при удалении всех сериалов",
"deleted_media_successfully": "Другие носители успешно удалены!", "deleted_media_successfully": "Остальные медиафайлы успешно удалены!",
"failed_to_delete_media": "Не удалось удалить другой файл", "failed_to_delete_media": "Не удалось удалить остальные медиафайлы",
"download_deleted": "Удалено", "download_deleted": "Загруженный контент удалён",
"download_cancelled": "Загрузка отменена", "download_cancelled": "Загрузка отменена",
"could_not_delete_download": "Не удалось удалить загрузку", "could_not_delete_download": "Не удалось удалить загрузку",
"download_paused": "На паузе", "download_paused": "На паузе",
"could_not_pause_download": "Не удалось приостановить загрузку", "could_not_pause_download": "Не удалось приостановить загрузку",
"download_resumed": "Продолжено", "download_resumed": "Продолжено",
"could_not_resume_download": "Не удалось продолжить загрузку", "could_not_resume_download": "Не удалось возобновить загрузку",
"download_completed": "Завершено", "download_completed": "Завершено",
"download_failed": "Не удалось загрузить", "download_failed": "Не удалось загрузить",
"download_failed_for_item": "Загрузка {{item}} провалилась с ошибкой: {{error}}", "download_failed_for_item": "Загрузка {{item}} провалилась с ошибкой: {{error}}",
"download_completed_for_item": "{{item}} успешно загружен", "download_completed_for_item": "{{item}} успешно загружен",
"download_started_for_item": "Загрузка началась для {{item}}", "download_started_for_item": "Загрузка {{item}} началась",
"failed_to_start_download": "Не удалось начать загрузку", "failed_to_start_download": "Не удалось начать загрузку",
"item_already_downloading": "{{item}} уже загружается", "item_already_downloading": "{{item}} уже загружается",
"all_files_deleted": "Все загрузки удалены", "all_files_deleted": "Все загрузки удалены",
"files_deleted_by_type": "{{count}} {{type}} удалён(о)", "files_deleted_by_type": "Удалено: {{count}} {{type}}",
"all_files_folders_and_jobs_deleted_successfully": "Все файлы, папки, и задачи были успешно удалены", "all_files_folders_and_jobs_deleted_successfully": "Все файлы, папки, и задачи были успешно удалены",
"failed_to_clean_cache_directory": "Не удалось очистить директорию кэша", "failed_to_clean_cache_directory": "Не удалось очистить директорию кэша",
"could_not_get_download_url_for_item": "Не удалось получить URL загрузки для {{itemName}}", "could_not_get_download_url_for_item": "Не удалось получить URL для загрузки {{itemName}}",
"go_to_downloads": "В загрузки", "go_to_downloads": "В загрузки",
"file_deleted": "{{item}} удалён" "file_deleted": "Удалено: {{item}}"
} }
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Выбрать", "select": "Выбрать",
"no_trailer_available": "Трейлер недоступен", "no_trailer_available": "Трейлер недоступен",
"video": "Видео", "video": "Видео",
"audio": "Звук", "audio": "Звук",
"subtitle": "Субтитры", "subtitle": "Субтитры",
"play": "Воспроизвести", "play": "Воспроизвести",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "Отсутствует", "none": "Отсутствует",
"track": "Трек", "track": "Трек",
"cancel": "Отмена", "cancel": "Отмена",
"stop": "Stop",
"delete": "Удалить", "delete": "Удалить",
"ok": "ОК", "ok": "ОК",
"remove": "Удалить", "remove": "Удалить",
"next": "Вперед", "next": "Вперед",
"back": "Назад", "back": "Назад",
"continue": "Продолжить", "continue": "Продолжить",
"verifying": "Проверка..." "verifying": "Проверка...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Поиск...", "search": "Поиск...",
"x_items": "{{count}} элементов", "x_items": "Элементов: {{count}}",
"library": "Библиотека", "library": "Библиотека",
"discover": "Найти новое", "discover": "Найти новое",
"no_results": "Ничего не найдено", "no_results": "Ничего не найдено",
@@ -529,14 +614,14 @@
"request_series": "Запросить сериалы", "request_series": "Запросить сериалы",
"recently_added": "Недавно добавлено", "recently_added": "Недавно добавлено",
"recent_requests": "Недавно запрошено", "recent_requests": "Недавно запрошено",
"plex_watchlist": "Список просмотра с Plex", "plex_watchlist": "Список просмотра Plex",
"trending": "В тренде", "trending": "В тренде",
"popular_movies": "Популярные фильмы", "popular_movies": "Популярные фильмы",
"movie_genres": "Популярные жанры", "movie_genres": "Популярные жанры",
"upcoming_movies": "Предстоящие фильмы", "upcoming_movies": "Предстоящие фильмы",
"studios": "Студии", "studios": "Студии",
"popular_tv": "Популярные сериалы", "popular_tv": "Популярные сериалы",
"tv_genres": "жанры сериалов", "tv_genres": "Жанры сериалов",
"upcoming_tv": "Предстоящие сериалы", "upcoming_tv": "Предстоящие сериалы",
"networks": "Сети", "networks": "Сети",
"tmdb_movie_keyword": "TMDB Ключевые слова фильмов", "tmdb_movie_keyword": "TMDB Ключевые слова фильмов",
@@ -556,7 +641,8 @@
"movies": "Фильмы", "movies": "Фильмы",
"series": "Сериалы", "series": "Сериалы",
"boxsets": "Коллекции", "boxsets": "Коллекции",
"items": "элементы" "playlists": "Playlists",
"items": "Элементы"
}, },
"options": { "options": {
"display": "Отображать", "display": "Отображать",
@@ -565,8 +651,9 @@
"image_style": "Стиль изображения", "image_style": "Стиль изображения",
"poster": "Постер", "poster": "Постер",
"cover": "Обложка", "cover": "Обложка",
"show_titles": "Показывать загаловки", "show_titles": "Показывать заголовки",
"show_stats": "Показывать статистику" "show_stats": "Показывать статистику",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Жанры", "genres": "Жанры",
@@ -574,7 +661,11 @@
"sort_by": "Сортировка", "sort_by": "Сортировка",
"filter_by": "Фильтр", "filter_by": "Фильтр",
"sort_order": "Порядок", "sort_order": "Порядок",
"tags": "Тэги" "tags": "Теги",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "Нет ссылок" "no_links": "Нет ссылок"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Ошибка", "error": "Ошибка",
"failed_to_get_stream_url": "Не удалось получить URL потока", "failed_to_get_stream_url": "Не удалось получить URL потока",
"an_error_occured_while_playing_the_video": "Возникла Неожиданная ошибка во время воспроизведения. Проверьте логи в настройках.", "an_error_occured_while_playing_the_video": "Возникла Неожиданная ошибка во время воспроизведения. Проверьте логи в настройках.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Хотите воспроизвести скачанный файл?", "downloaded_file_message": "Хотите воспроизвести скачанный файл?",
"downloaded_file_yes": "Да", "downloaded_file_yes": "Да",
"downloaded_file_no": "Нет", "downloaded_file_no": "Нет",
"downloaded_file_cancel": "Отмена" "downloaded_file_cancel": "Отмена",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "Далее", "next_up": "Далее",
@@ -617,6 +738,11 @@
"series": "Серии", "series": "Серии",
"seasons": "Сезоны", "seasons": "Сезоны",
"season": "Сезон", "season": "Сезон",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "В этом сезоне нет серий", "no_episodes_for_this_season": "В этом сезоне нет серий",
"overview": "Обзор", "overview": "Обзор",
"more_with": "Больше с {{name}}", "more_with": "Больше с {{name}}",
@@ -624,13 +750,24 @@
"no_similar_items_found": "Похожие элементы не найдены", "no_similar_items_found": "Похожие элементы не найдены",
"video": "Видео", "video": "Видео",
"more_details": "Больше деталей", "more_details": "Больше деталей",
"media_options": "Media Options", "media_options": "Опции медиа",
"quality": "Качество", "quality": "Качество",
"audio": "Звук", "audio": "Звук",
"subtitles": "Субтитры", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Показать больше", "show_more": "Показать больше",
"show_less": "Показать меньше", "show_less": "Показать меньше",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Появлялся в", "appeared_in": "Появлялся в",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Не удалось загрузить элемент", "could_not_load_item": "Не удалось загрузить элемент",
"none": "Отсутствует", "none": "Отсутствует",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Загрузить {{item_count}} элементов", "download_x_item": "Загрузить {{item_count}} элементов",
"download_unwatched_only": "Только непросмотренные", "download_unwatched_only": "Только непросмотренные",
"download_button": "Загрузить" "download_button": "Загрузить"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Далее", "next": "Далее",
@@ -652,7 +795,18 @@
"movies": "Фильмы", "movies": "Фильмы",
"sports": "Спорт", "sports": "Спорт",
"for_kids": "Для детей", "for_kids": "Для детей",
"news": "Новости" "news": "Новости",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Подтвердить", "confirm": "Подтвердить",
@@ -685,26 +839,32 @@
"currently_streaming_on": "Сейчас доступно на", "currently_streaming_on": "Сейчас доступно на",
"advanced": "Продвинутое", "advanced": "Продвинутое",
"request_as": "Запросить как", "request_as": "Запросить как",
"tags": "Тэги", "tags": "Теги",
"quality_profile": "Профиль качества", "quality_profile": "Профиль качества",
"root_folder": "Корневая папка", "root_folder": "Корневая папка",
"season_all": "Сезон (все)", "season_all": "Сезон (все)",
"season_number": "Сезон {{season_number}}", "season_number": "Сезон {{season_number}}",
"number_episodes": "{{episode_number}} серий", "number_episodes": "Серий: {{episode_number}}",
"born": "Рожден", "born": "Рожден",
"appearances": "Появления", "appearances": "Появления",
"approve": "Одобрить", "approve": "Одобрить",
"decline": "Отклонить", "decline": "Отклонить",
"requested_by": "Запрошено {{user}}", "requested_by": "Запрошено {{user}}",
"unknown_user": "Неизвестный пользователь", "unknown_user": "Неизвестный пользователь",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Сервер Jellyseerr не соответствует минимальным требованиям версии! Пожалуйста, обновите до версии не ниже 2.0.0", "jellyseer_does_not_meet_requirements": "Сервер Jellyseerr не соответствует минимальным требованиям версии! Пожалуйста, обновите до версии не ниже 2.0.0",
"jellyseerr_test_failed": "Тест Jellyseerr не пройден. Попробуйте еще раз.", "jellyseerr_test_failed": "Тест Jellyseerr не пройден. Попробуйте еще раз.",
"failed_to_test_jellyseerr_server_url": "Не удалось проверить URL-адрес сервера jellyseerr", "failed_to_test_jellyseerr_server_url": "Не удалось проверить URL-адрес сервера Seerr",
"issue_submitted": "Проблема отправлена!", "issue_submitted": "Проблема отправлена!",
"requested_item": "Запрошено {{item}}!", "requested_item": "Запрошено {{item}}!",
"you_dont_have_permission_to_request": "У вас нет разрешения на запрос!", "you_dont_have_permission_to_request": "У вас нет разрешения на запрос!",
"something_went_wrong_requesting_media": "Что-то пошло не так при запросе медиафайлов!", "something_went_wrong_requesting_media": "Что-то пошло не так при запросе медиа!",
"request_approved": "Запрос одобрен!", "request_approved": "Запрос одобрен!",
"request_declined": "Запрос отклонён!", "request_declined": "Запрос отклонён!",
"failed_to_approve_request": "Не удалось одобрить запрос", "failed_to_approve_request": "Не удалось одобрить запрос",
@@ -716,7 +876,8 @@
"search": "Поиск", "search": "Поиск",
"library": "Библиотека", "library": "Библиотека",
"custom_links": "Ссылки", "custom_links": "Ссылки",
"favorites": "Избранное" "favorites": "Избранное",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Музыка", "title": "Музыка",
@@ -841,5 +1002,36 @@
"show": "Ко всему сериалу", "show": "Ко всему сериалу",
"all": "Ко всем файлам (по умолчанию)" "all": "Ко всем файлам (по умолчанию)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Fel", "error_title": "Fel",
"login_title": "Logga in", "login_title": "Logga in",
"login_to_title": "Logga in till", "login_to_title": "Logga in till",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Användarnamn", "username_placeholder": "Användarnamn",
"password_placeholder": "Lösenord", "password_placeholder": "Lösenord",
"login_button": "Logga in", "login_button": "Logga in",
@@ -44,7 +47,11 @@
"add_account": "Lägg till konto", "add_account": "Lägg till konto",
"remove_account_description": "Detta kommer att ta bort de sparade uppgifterna för {{username}}.", "remove_account_description": "Detta kommer att ta bort de sparade uppgifterna för {{username}}.",
"remove_server": "Ta bort server", "remove_server": "Ta bort server",
"remove_server_description": "Detta kommer att ta bort {{server}} och alla sparade konton från din lista." "remove_server_description": "Detta kommer att ta bort {{server}} och alla sparade konton från din lista.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Spara konto", "title": "Spara konto",
@@ -112,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Inställningar", "settings_title": "Inställningar",
"log_out_button": "Logga ut", "log_out_button": "Logga ut",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Kategorier" "title": "Kategorier"
}, },
@@ -128,12 +141,12 @@
"show_home_backdrop": "Dynamisk hembakgrund", "show_home_backdrop": "Dynamisk hembakgrund",
"show_hero_carousel": "Hjältekarusell", "show_hero_carousel": "Hjältekarusell",
"show_series_poster_on_episode": "Visa serieaffisch på avsnitt", "show_series_poster_on_episode": "Visa serieaffisch på avsnitt",
"theme_music": "Temamusik",
"display_size": "Visningsstorlek", "display_size": "Visningsstorlek",
"display_size_small": "Liten", "display_size_small": "Liten",
"display_size_default": "Standard", "display_size_default": "Standard",
"display_size_large": "Stor", "display_size_large": "Stor",
"display_size_extra_large": "Extra stor", "display_size_extra_large": "Extra stor"
"theme_music": "Temamusik"
}, },
"network": { "network": {
"title": "Nätverk", "title": "Nätverk",
@@ -196,6 +209,12 @@
"max_cache_size": "Max cachestorlek", "max_cache_size": "Max cachestorlek",
"max_backward_cache": "Max bakåtcache" "max_backward_cache": "Max bakåtcache"
}, },
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Gestkontroller", "gesture_controls_title": "Gestkontroller",
"horizontal_swipe_skip": "Horisontell Svepning för att Hoppa Fram/Bak", "horizontal_swipe_skip": "Horisontell Svepning för att Hoppa Fram/Bak",
@@ -371,7 +390,7 @@
"server_url_placeholder": "Seerr URL", "server_url_placeholder": "Seerr URL",
"password": "Lösenord", "password": "Lösenord",
"password_placeholder": "Ange lösenord för Jellyfin användare {{username}}", "password_placeholder": "Ange lösenord för Jellyfin användare {{username}}",
"login_button": "Logga in", "login_button": "Login",
"total_media_requests": "Totalt antal mediaförfrågningar", "total_media_requests": "Totalt antal mediaförfrågningar",
"movie_quota_limit": "Gräns för filmkvot", "movie_quota_limit": "Gräns för filmkvot",
"movie_quota_days": "Filmkvot Dagar", "movie_quota_days": "Filmkvot Dagar",
@@ -444,7 +463,13 @@
"music_cache_cleared": "Musikcache rensad", "music_cache_cleared": "Musikcache rensad",
"delete_all_downloaded_songs": "Ta bort alla nerladdade filer", "delete_all_downloaded_songs": "Ta bort alla nerladdade filer",
"downloaded_songs_size": "{{size}} nedladdad", "downloaded_songs_size": "{{size}} nedladdad",
"downloaded_songs_deleted": "Nedladdade låtar raderade" "downloaded_songs_deleted": "Nedladdade låtar raderade",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Introduktion", "title": "Introduktion",
@@ -468,6 +493,21 @@
"error_deleting_files": "Fel Vid Borttagning Av Filer", "error_deleting_files": "Fel Vid Borttagning Av Filer",
"background_downloads_enabled": "Bakgrundsnedladdningar aktiverade", "background_downloads_enabled": "Bakgrundsnedladdningar aktiverade",
"background_downloads_disabled": "Bakgrundsnedladdningar inaktiverade" "background_downloads_disabled": "Bakgrundsnedladdningar inaktiverade"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -494,6 +534,7 @@
"new_app_version_requires_re_download_description": "Den nya uppdateringen kräver att innehållet laddas ner igen. Ta bort allt nedladdat innehåll och försök igen.", "new_app_version_requires_re_download_description": "Den nya uppdateringen kräver att innehållet laddas ner igen. Ta bort allt nedladdat innehåll och försök igen.",
"back": "Tillbaka", "back": "Tillbaka",
"delete": "Radera", "delete": "Radera",
"delete_download": "Delete Download",
"something_went_wrong": "Något Gick Fel", "something_went_wrong": "Något Gick Fel",
"could_not_get_stream_url_from_jellyfin": "Det gick inte att hämta strömadressen från Jellyfin", "could_not_get_stream_url_from_jellyfin": "Det gick inte att hämta strömadressen från Jellyfin",
"eta": "ETA {{eta}}", "eta": "ETA {{eta}}",
@@ -537,6 +578,8 @@
"audio": "Ljud", "audio": "Ljud",
"subtitle": "Undertext", "subtitle": "Undertext",
"play": "Spela", "play": "Spela",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "Ingen", "none": "Ingen",
"track": "Spår", "track": "Spår",
"cancel": "Avbryt", "cancel": "Avbryt",
@@ -549,8 +592,7 @@
"continue": "Fortsätt", "continue": "Fortsätt",
"verifying": "Verifierar...", "verifying": "Verifierar...",
"login": "Logga in", "login": "Logga in",
"refresh": "Uppdatera", "refresh": "Uppdatera"
"seeAll": "Visa alla"
}, },
"search": { "search": {
"search": "Sök...", "search": "Sök...",
@@ -610,7 +652,8 @@
"poster": "Affisch", "poster": "Affisch",
"cover": "Omslag", "cover": "Omslag",
"show_titles": "Visa Titlar", "show_titles": "Visa Titlar",
"show_stats": "Visa Statistik" "show_stats": "Visa Statistik",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Genrer", "genres": "Genrer",
@@ -640,6 +683,7 @@
}, },
"player": { "player": {
"live": "LIVE", "live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Fel", "error": "Fel",
"failed_to_get_stream_url": "Kunde inte hämta stream-URL", "failed_to_get_stream_url": "Kunde inte hämta stream-URL",
"an_error_occured_while_playing_the_video": "Ett fel uppstod vid uppspelning av videon. Kontrollera loggarna i inställningarna.", "an_error_occured_while_playing_the_video": "Ett fel uppstod vid uppspelning av videon. Kontrollera loggarna i inställningarna.",
@@ -681,6 +725,12 @@
"stopPlayingConfirm": "Är du säker på att du vill stoppa uppspelningen?", "stopPlayingConfirm": "Är du säker på att du vill stoppa uppspelningen?",
"downloaded": "Nedladdad" "downloaded": "Nedladdad"
}, },
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": { "item_card": {
"next_up": "Näst på tur", "next_up": "Näst på tur",
"no_items_to_display": "Inga Artiklar Att Visa", "no_items_to_display": "Inga Artiklar Att Visa",
@@ -793,7 +843,7 @@
"quality_profile": "Kvalitetsprofil", "quality_profile": "Kvalitetsprofil",
"root_folder": "Rotkatalog", "root_folder": "Rotkatalog",
"season_all": "Säsong (alla)", "season_all": "Säsong (alla)",
"season_number": "Säsong {{season_number}}", "season_number": "Säsong {{seasonNumber}}",
"number_episodes": "{{episode_number}} Avsnitt", "number_episodes": "{{episode_number}} Avsnitt",
"born": "Född", "born": "Född",
"appearances": "Framträdanden", "appearances": "Framträdanden",
@@ -952,5 +1002,36 @@
"show": "Denna serie", "show": "Denna serie",
"all": "Alla media (standard)" "all": "Alla media (standard)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Error", "error_title": "Error",
"login_title": "Log In", "login_title": "Log In",
"login_to_title": "Log in to", "login_to_title": "Log in to",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Username", "username_placeholder": "Username",
"password_placeholder": "Password", "password_placeholder": "Password",
"login_button": "Log In", "login_button": "Log In",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} accounts",
"select_account": "Select Account", "select_account": "Select Account",
"add_account": "Add Account", "add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "This will remove the saved credentials for {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "Save Account",
@@ -86,6 +95,7 @@
"oops": "Oops!", "oops": "Oops!",
"error_message": "Something went wrong.\nPlease log out and in again.", "error_message": "Something went wrong.\nPlease log out and in again.",
"continue_watching": "Continue Watching", "continue_watching": "Continue Watching",
"continue": "Continue",
"next_up": "Next Up", "next_up": "Next Up",
"continue_and_next_up": "Continue & Next Up", "continue_and_next_up": "Continue & Next Up",
"recently_added_in": "Recently Added in {{libraryName}}", "recently_added_in": "Recently Added in {{libraryName}}",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Settings", "settings_title": "Settings",
"log_out_button": "Log Out", "log_out_button": "Log Out",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Categories" "title": "Categories"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "ปรับแต่งลักษณะภายนอก", "title": "ปรับแต่งลักษณะภายนอก",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up", "merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button" "hide_remote_session_button": "Hide Remote Session Button",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "Network",
@@ -174,6 +199,22 @@
"rewind_length": "Rewind Length", "rewind_length": "Rewind Length",
"seconds_unit": "s" "seconds_unit": "s"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Gesture Controls", "gesture_controls_title": "Gesture Controls",
"horizontal_swipe_skip": "Horizontal Swipe to Skip", "horizontal_swipe_skip": "Horizontal Swipe to Skip",
@@ -256,7 +297,23 @@
"subtitle_font": "Subtitle Font", "subtitle_font": "Subtitle Font",
"ksplayer_title": "KSPlayer Settings", "ksplayer_title": "KSPlayer Settings",
"hardware_decode": "Hardware Decoding", "hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues." "hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "VLC Subtitle Settings",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Music cache cleared", "music_cache_cleared": "Music cache cleared",
"delete_all_downloaded_songs": "Delete All Downloaded Songs", "delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded", "downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "Downloaded songs deleted",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Intro", "title": "Intro",
@@ -430,6 +493,21 @@
"error_deleting_files": "Error Deleting Files", "error_deleting_files": "Error Deleting Files",
"background_downloads_enabled": "Background downloads enabled", "background_downloads_enabled": "Background downloads enabled",
"background_downloads_disabled": "Background downloads disabled" "background_downloads_disabled": "Background downloads disabled"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "The new update requires content to be downloaded again. Please remove all downloaded content and try again.", "new_app_version_requires_re_download_description": "The new update requires content to be downloaded again. Please remove all downloaded content and try again.",
"back": "Back", "back": "Back",
"delete": "Delete", "delete": "Delete",
"delete_download": "Delete Download",
"something_went_wrong": "Something Went Wrong", "something_went_wrong": "Something Went Wrong",
"could_not_get_stream_url_from_jellyfin": "Could not get the stream URL from Jellyfin", "could_not_get_stream_url_from_jellyfin": "Could not get the stream URL from Jellyfin",
"eta": "ETA {{eta}}", "eta": "ETA {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Select", "select": "Select",
"no_trailer_available": "No trailer available", "no_trailer_available": "No trailer available",
"video": "Video", "video": "Video",
"audio": "Audio", "audio": "Audio",
"subtitle": "Subtitle", "subtitle": "Subtitle",
"play": "Play", "play": "Play",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "None", "none": "None",
"track": "Track", "track": "Track",
"cancel": "Cancel", "cancel": "Cancel",
"stop": "Stop",
"delete": "Delete", "delete": "Delete",
"ok": "OK", "ok": "OK",
"remove": "Remove", "remove": "Remove",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"continue": "Continue", "continue": "Continue",
"verifying": "Verifying..." "verifying": "Verifying...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Search...", "search": "Search...",
@@ -556,6 +641,7 @@
"movies": "Movies", "movies": "Movies",
"series": "Series", "series": "Series",
"boxsets": "Box Sets", "boxsets": "Box Sets",
"playlists": "Playlists",
"items": "Items" "items": "Items"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Poster", "poster": "Poster",
"cover": "Cover", "cover": "Cover",
"show_titles": "Show Titles", "show_titles": "Show Titles",
"show_stats": "Show Stats" "show_stats": "Show Stats",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Genres", "genres": "Genres",
@@ -574,7 +661,11 @@
"sort_by": "Sort By", "sort_by": "Sort By",
"filter_by": "Filter By", "filter_by": "Filter By",
"sort_order": "Sort Order", "sort_order": "Sort Order",
"tags": "Tags" "tags": "Tags",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "No Links" "no_links": "No Links"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Error", "error": "Error",
"failed_to_get_stream_url": "Failed to get the stream URL", "failed_to_get_stream_url": "Failed to get the stream URL",
"an_error_occured_while_playing_the_video": "An error occurred while playing the video. Check logs in settings.", "an_error_occured_while_playing_the_video": "An error occurred while playing the video. Check logs in settings.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Do you want to play the downloaded file?", "downloaded_file_message": "Do you want to play the downloaded file?",
"downloaded_file_yes": "Yes", "downloaded_file_yes": "Yes",
"downloaded_file_no": "No", "downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel" "downloaded_file_cancel": "Cancel",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "Next Up", "next_up": "Next Up",
@@ -617,6 +738,11 @@
"series": "Series", "series": "Series",
"seasons": "Seasons", "seasons": "Seasons",
"season": "Season", "season": "Season",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "No episodes for this season", "no_episodes_for_this_season": "No episodes for this season",
"overview": "Overview", "overview": "Overview",
"more_with": "More with {{name}}", "more_with": "More with {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Media Options", "media_options": "Media Options",
"quality": "Quality", "quality": "Quality",
"audio": "Audio", "audio": "Audio",
"subtitles": "Subtitle", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Show More", "show_more": "Show More",
"show_less": "Show Less", "show_less": "Show Less",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Appeared In", "appeared_in": "Appeared In",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Could Not Load Item", "could_not_load_item": "Could Not Load Item",
"none": "None", "none": "None",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Download {{item_count}} Items", "download_x_item": "Download {{item_count}} Items",
"download_unwatched_only": "Unwatched Only", "download_unwatched_only": "Unwatched Only",
"download_button": "Download" "download_button": "Download"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Next", "next": "Next",
@@ -652,7 +795,18 @@
"movies": "Movies", "movies": "Movies",
"sports": "Sports", "sports": "Sports",
"for_kids": "For Kids", "for_kids": "For Kids",
"news": "News" "news": "News",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Confirm", "confirm": "Confirm",
@@ -697,6 +851,12 @@
"decline": "Decline", "decline": "Decline",
"requested_by": "Requested by {{user}}", "requested_by": "Requested by {{user}}",
"unknown_user": "Unknown User", "unknown_user": "Unknown User",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Seerr server does not meet minimum version requirements! Please update to at least 2.0.0", "jellyseer_does_not_meet_requirements": "Seerr server does not meet minimum version requirements! Please update to at least 2.0.0",
"jellyseerr_test_failed": "Seerr test failed. Please try again.", "jellyseerr_test_failed": "Seerr test failed. Please try again.",
@@ -716,7 +876,8 @@
"search": "Search", "search": "Search",
"library": "Library", "library": "Library",
"custom_links": "Custom Links", "custom_links": "Custom Links",
"favorites": "Favorites" "favorites": "Favorites",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Music", "title": "Music",
@@ -841,5 +1002,36 @@
"show": "This show", "show": "This show",
"all": "All media (default)" "all": "All media (default)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "ghIq", "error_title": "ghIq",
"login_title": "lut 'el", "login_title": "lut 'el",
"login_to_title": "lut 'el", "login_to_title": "lut 'el",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "tlhIngan", "username_placeholder": "tlhIngan",
"password_placeholder": "ngoq De'", "password_placeholder": "ngoq De'",
"login_button": "yI'el!", "login_button": "yI'el!",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} accounts",
"select_account": "Select Account", "select_account": "Select Account",
"add_account": "Add Account", "add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "This will remove the saved credentials for {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "Save Account",
@@ -86,6 +95,7 @@
"oops": "QI'ya!", "oops": "QI'ya!",
"error_message": "Doch rurbe'.\nyIQo' 'ej yI'elqa'.", "error_message": "Doch rurbe'.\nyIQo' 'ej yI'elqa'.",
"continue_watching": "tlhol yIHaDqa'", "continue_watching": "tlhol yIHaDqa'",
"continue": "Continue",
"next_up": "wej", "next_up": "wej",
"continue_and_next_up": "Continue & Next Up", "continue_and_next_up": "Continue & Next Up",
"recently_added_in": "num tu'lu' {{libraryName}}", "recently_added_in": "num tu'lu' {{libraryName}}",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "men", "settings_title": "men",
"log_out_button": "yIQo'", "log_out_button": "yIQo'",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Categories" "title": "Categories"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Appearance", "title": "Appearance",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up", "merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button" "hide_remote_session_button": "Hide Remote Session Button",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "Network",
@@ -174,6 +199,22 @@
"rewind_length": "bavHom vum", "rewind_length": "bavHom vum",
"seconds_unit": "tera' rep" "seconds_unit": "tera' rep"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "QavwI' 'ej Qap", "gesture_controls_title": "QavwI' 'ej Qap",
"horizontal_swipe_skip": "SaS mup loSmeH", "horizontal_swipe_skip": "SaS mup loSmeH",
@@ -256,7 +297,23 @@
"subtitle_font": "Subtitle Font", "subtitle_font": "Subtitle Font",
"ksplayer_title": "KSPlayer Settings", "ksplayer_title": "KSPlayer Settings",
"hardware_decode": "Hardware Decoding", "hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues." "hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "VLC Subtitle Settings",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Music cache cleared", "music_cache_cleared": "Music cache cleared",
"delete_all_downloaded_songs": "Delete All Downloaded Songs", "delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded", "downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "Downloaded songs deleted",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Intro", "title": "Intro",
@@ -430,6 +493,21 @@
"error_deleting_files": "Qaw' ghIq", "error_deleting_files": "Qaw' ghIq",
"background_downloads_enabled": "tlhegh Qaw' chu'", "background_downloads_enabled": "tlhegh Qaw' chu'",
"background_downloads_disabled": "tlhegh Qaw' QIj" "background_downloads_disabled": "tlhegh Qaw' QIj"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "wej chu' Doch Qaw'qa' DaneH. Hoch Qaw' Doch yIQaw' 'ej yIHaDqa'.", "new_app_version_requires_re_download_description": "wej chu' Doch Qaw'qa' DaneH. Hoch Qaw' Doch yIQaw' 'ej yIHaDqa'.",
"back": "yIbav", "back": "yIbav",
"delete": "yIQaw'", "delete": "yIQaw'",
"delete_download": "Delete Download",
"something_went_wrong": "Doch rurbe'", "something_went_wrong": "Doch rurbe'",
"could_not_get_stream_url_from_jellyfin": "Jellyfin tlhol ret URL tu'laHbe'", "could_not_get_stream_url_from_jellyfin": "Jellyfin tlhol ret URL tu'laHbe'",
"eta": "ETA {{eta}}", "eta": "ETA {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Select", "select": "Select",
"no_trailer_available": "No trailer available", "no_trailer_available": "No trailer available",
"video": "mu'tlhegh", "video": "mu'tlhegh",
"audio": "QoQ", "audio": "QoQ",
"subtitle": "De' chu'", "subtitle": "De' chu'",
"play": "Play", "play": "Play",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "None", "none": "None",
"track": "Track", "track": "Track",
"cancel": "Cancel", "cancel": "Cancel",
"stop": "Stop",
"delete": "Delete", "delete": "Delete",
"ok": "OK", "ok": "OK",
"remove": "Remove", "remove": "Remove",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"continue": "Continue", "continue": "Continue",
"verifying": "Verifying..." "verifying": "Verifying...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "yISam...", "search": "yISam...",
@@ -556,6 +641,7 @@
"movies": "DIS", "movies": "DIS",
"series": "Hem", "series": "Hem",
"boxsets": "Hem ghom", "boxsets": "Hem ghom",
"playlists": "Playlists",
"items": "Doch" "items": "Doch"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "nagh", "poster": "nagh",
"cover": "nagh chop", "cover": "nagh chop",
"show_titles": "pab HoS yIHoch", "show_titles": "pab HoS yIHoch",
"show_stats": "chIm De' yIHoch" "show_stats": "chIm De' yIHoch",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "qorDu'", "genres": "qorDu'",
@@ -574,7 +661,11 @@
"sort_by": "yIwIv", "sort_by": "yIwIv",
"filter_by": "Filter By", "filter_by": "Filter By",
"sort_order": "wIv mIw", "sort_order": "wIv mIw",
"tags": "De'Hom" "tags": "De'Hom",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "ret pagh" "no_links": "ret pagh"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "ghIq", "error": "ghIq",
"failed_to_get_stream_url": "tlhol ret URL tu'laHbe'", "failed_to_get_stream_url": "tlhol ret URL tu'laHbe'",
"an_error_occured_while_playing_the_video": "mu'tlhegh tlholDI' ghIq. menDaq De' qon mej.", "an_error_occured_while_playing_the_video": "mu'tlhegh tlholDI' ghIq. menDaq De' qon mej.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Do you want to play the downloaded file?", "downloaded_file_message": "Do you want to play the downloaded file?",
"downloaded_file_yes": "Yes", "downloaded_file_yes": "Yes",
"downloaded_file_no": "No", "downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel" "downloaded_file_cancel": "Cancel",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "wej", "next_up": "wej",
@@ -617,6 +738,11 @@
"series": "Hem", "series": "Hem",
"seasons": "muv", "seasons": "muv",
"season": "muv", "season": "muv",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "muvvam HemHom pagh", "no_episodes_for_this_season": "muvvam HemHom pagh",
"overview": "Hoch Sov", "overview": "Hoch Sov",
"more_with": "{{name}} latlh", "more_with": "{{name}} latlh",
@@ -627,10 +753,21 @@
"media_options": "Media Options", "media_options": "Media Options",
"quality": "luj", "quality": "luj",
"audio": "QoQ", "audio": "QoQ",
"subtitles": "De' chu'", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "latlh yIHoch", "show_more": "latlh yIHoch",
"show_less": "Hom yIHoch", "show_less": "Hom yIHoch",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "tlholvam", "appeared_in": "tlholvam",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Doch tlha'laHbe'", "could_not_load_item": "Doch tlha'laHbe'",
"none": "pagh", "none": "pagh",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "{{item_count}} Doch yIQaw'", "download_x_item": "{{item_count}} Doch yIQaw'",
"download_unwatched_only": "Unwatched Only", "download_unwatched_only": "Unwatched Only",
"download_button": "yIQaw'" "download_button": "yIQaw'"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "wej", "next": "wej",
@@ -652,7 +795,18 @@
"movies": "DIS", "movies": "DIS",
"sports": "QI'", "sports": "QI'",
"for_kids": "puqbeq", "for_kids": "puqbeq",
"news": "De'" "news": "De'",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "yInej", "confirm": "yInej",
@@ -697,6 +851,12 @@
"decline": "Decline", "decline": "Decline",
"requested_by": "Requested by {{user}}", "requested_by": "Requested by {{user}}",
"unknown_user": "Unknown User", "unknown_user": "Unknown User",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Jellyseerr Ho'Do' veS wej law'be'! 2.0.0 yIchu'!", "jellyseer_does_not_meet_requirements": "Jellyseerr Ho'Do' veS wej law'be'! 2.0.0 yIchu'!",
"jellyseerr_test_failed": "Jellyseerr nejlaHbe'. yIHaDqa'.", "jellyseerr_test_failed": "Jellyseerr nejlaHbe'. yIHaDqa'.",
@@ -716,7 +876,8 @@
"search": "Sam", "search": "Sam",
"library": "De'wI' bom", "library": "De'wI' bom",
"custom_links": "teqlu' ret", "custom_links": "teqlu' ret",
"favorites": "wIv Doch" "favorites": "wIv Doch",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Music", "title": "Music",
@@ -841,5 +1002,36 @@
"show": "This show", "show": "This show",
"all": "All media (default)" "all": "All media (default)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Hata", "error_title": "Hata",
"login_title": "Giriş yap", "login_title": "Giriş yap",
"login_to_title": " 'e giriş yap", "login_to_title": " 'e giriş yap",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Kullanıcı adı", "username_placeholder": "Kullanıcı adı",
"password_placeholder": "Şifre", "password_placeholder": "Şifre",
"login_button": "Giriş yap", "login_button": "Giriş yap",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} hesap", "accounts_count": "{{count}} hesap",
"select_account": "Hesap Seç", "select_account": "Hesap Seç",
"add_account": "Hesap Ekle", "add_account": "Hesap Ekle",
"remove_account_description": "{{username}} için kayıtlı bilgiler kaldırılacaktır." "remove_account_description": "{{username}} için kayıtlı bilgiler kaldırılacaktır.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Hesabı Kaydet", "title": "Hesabı Kaydet",
@@ -86,6 +95,7 @@
"oops": "Hups!", "oops": "Hups!",
"error_message": "Bir şeyler ters gitti.\nLütfen çıkış yapıp tekrar giriş yapın.", "error_message": "Bir şeyler ters gitti.\nLütfen çıkış yapıp tekrar giriş yapın.",
"continue_watching": "İzlemeye Devam Et", "continue_watching": "İzlemeye Devam Et",
"continue": "Continue",
"next_up": "Sonraki", "next_up": "Sonraki",
"continue_and_next_up": "İzlemeye Devam Et & Sıradakiler", "continue_and_next_up": "İzlemeye Devam Et & Sıradakiler",
"recently_added_in": "{{libraryName}} Kütüphanesine Son Eklenenler", "recently_added_in": "{{libraryName}} Kütüphanesine Son Eklenenler",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Ayarlar", "settings_title": "Ayarlar",
"log_out_button": ıkış Yap", "log_out_button": ıkış Yap",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Kategoriler" "title": "Kategoriler"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Görünüm", "title": "Görünüm",
"merge_next_up_continue_watching": "İzlemeye Devam Et & Sıradakiler'i birleştir", "merge_next_up_continue_watching": "İzlemeye Devam Et & Sıradakiler'i birleştir",
"hide_remote_session_button": "Uzak Oturum Butonunu Gizle" "hide_remote_session_button": "Uzak Oturum Butonunu Gizle",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Ağ", "title": "Ağ",
@@ -174,6 +199,22 @@
"rewind_length": "Geri Sarma Uzunluğu", "rewind_length": "Geri Sarma Uzunluğu",
"seconds_unit": "sn" "seconds_unit": "sn"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Hareketle Kontrol", "gesture_controls_title": "Hareketle Kontrol",
"horizontal_swipe_skip": "Atlamak için yatay kaydırma", "horizontal_swipe_skip": "Atlamak için yatay kaydırma",
@@ -256,7 +297,23 @@
"subtitle_font": "Altyazı Yazı Tipi", "subtitle_font": "Altyazı Yazı Tipi",
"ksplayer_title": "KSPlayer Ayarları", "ksplayer_title": "KSPlayer Ayarları",
"hardware_decode": "Donanımsal Kod Çözme", "hardware_decode": "Donanımsal Kod Çözme",
"hardware_decode_description": "Video kod çözme için donanımsal hızlandırma kullan. Oynatma sorunları yaşıyorsanız devre dışı bırakın." "hardware_decode_description": "Video kod çözme için donanımsal hızlandırma kullan. Oynatma sorunları yaşıyorsanız devre dışı bırakın.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Altyazı Ayarları", "title": "VLC Altyazı Ayarları",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Müzik ön belleği temizlendi", "music_cache_cleared": "Müzik ön belleği temizlendi",
"delete_all_downloaded_songs": "Tüm İndirilen Müzikleri Sil", "delete_all_downloaded_songs": "Tüm İndirilen Müzikleri Sil",
"downloaded_songs_size": "{{size}} indirildi", "downloaded_songs_size": "{{size}} indirildi",
"downloaded_songs_deleted": "İndirilen müzikler silindi" "downloaded_songs_deleted": "İndirilen müzikler silindi",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Giriş", "title": "Giriş",
@@ -430,6 +493,21 @@
"error_deleting_files": "Dosyalar silinirken hata oluştu", "error_deleting_files": "Dosyalar silinirken hata oluştu",
"background_downloads_enabled": "Arka plan indirmeleri etkinleştirildi", "background_downloads_enabled": "Arka plan indirmeleri etkinleştirildi",
"background_downloads_disabled": "Arka plan indirmeleri devre dışı bırakıldı" "background_downloads_disabled": "Arka plan indirmeleri devre dışı bırakıldı"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "Yeni güncelleme, içeriğin yeniden indirilmesini gerektiriyor. Lütfen tüm indirilen içerikleri kaldırıp tekrar deneyin.", "new_app_version_requires_re_download_description": "Yeni güncelleme, içeriğin yeniden indirilmesini gerektiriyor. Lütfen tüm indirilen içerikleri kaldırıp tekrar deneyin.",
"back": "Geri", "back": "Geri",
"delete": "Sil", "delete": "Sil",
"delete_download": "Delete Download",
"something_went_wrong": "Bir şeyler ters gitti", "something_went_wrong": "Bir şeyler ters gitti",
"could_not_get_stream_url_from_jellyfin": "Jellyfin'den yayın URL'si alınamadı", "could_not_get_stream_url_from_jellyfin": "Jellyfin'den yayın URL'si alınamadı",
"eta": "Tahmini Süre {{eta}}", "eta": "Tahmini Süre {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Seç", "select": "Seç",
"no_trailer_available": "Fragman mevcut değil", "no_trailer_available": "Fragman mevcut değil",
"video": "Video", "video": "Video",
"audio": "Ses", "audio": "Ses",
"subtitle": "Altyazı", "subtitle": "Altyazı",
"play": "Oynat", "play": "Oynat",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "Hiçbiri", "none": "Hiçbiri",
"track": "Parça", "track": "Parça",
"cancel": "Vazgeç", "cancel": "Vazgeç",
"stop": "Stop",
"delete": "Sil", "delete": "Sil",
"ok": "Tamam", "ok": "Tamam",
"remove": "Kaldır", "remove": "Kaldır",
"next": "Sonraki", "next": "Sonraki",
"back": "Geri", "back": "Geri",
"continue": "Devam", "continue": "Devam",
"verifying": "Doğrulanıyor..." "verifying": "Doğrulanıyor...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Ara...", "search": "Ara...",
@@ -556,6 +641,7 @@
"movies": "filmler", "movies": "filmler",
"series": "diziler", "series": "diziler",
"boxsets": "koleksiyonlar", "boxsets": "koleksiyonlar",
"playlists": "Playlists",
"items": "ögeler" "items": "ögeler"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Poster", "poster": "Poster",
"cover": "Kapak", "cover": "Kapak",
"show_titles": "Başlıkları göster", "show_titles": "Başlıkları göster",
"show_stats": "İstatistikleri göster" "show_stats": "İstatistikleri göster",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Türler", "genres": "Türler",
@@ -574,7 +661,11 @@
"sort_by": "Sırala", "sort_by": "Sırala",
"filter_by": "Filtrele", "filter_by": "Filtrele",
"sort_order": "Sıralama düzeni", "sort_order": "Sıralama düzeni",
"tags": "Etiketler" "tags": "Etiketler",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "Bağlantı yok" "no_links": "Bağlantı yok"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Hata", "error": "Hata",
"failed_to_get_stream_url": "Yayın URL'si alınamadı", "failed_to_get_stream_url": "Yayın URL'si alınamadı",
"an_error_occured_while_playing_the_video": "Video oynatılırken bir hata oluştu. Ayarlardaki günlüklere bakın.", "an_error_occured_while_playing_the_video": "Video oynatılırken bir hata oluştu. Ayarlardaki günlüklere bakın.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "İndirilmiş dosyayı oynatmak ister misiniz?", "downloaded_file_message": "İndirilmiş dosyayı oynatmak ister misiniz?",
"downloaded_file_yes": "Evet", "downloaded_file_yes": "Evet",
"downloaded_file_no": "Hayır", "downloaded_file_no": "Hayır",
"downloaded_file_cancel": "Vazgeç" "downloaded_file_cancel": "Vazgeç",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "Sıradaki", "next_up": "Sıradaki",
@@ -617,6 +738,11 @@
"series": "Dizi", "series": "Dizi",
"seasons": "Sezonlar", "seasons": "Sezonlar",
"season": "Sezon", "season": "Sezon",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "Bu sezona ait bölüm yok", "no_episodes_for_this_season": "Bu sezona ait bölüm yok",
"overview": "Özet", "overview": "Özet",
"more_with": "Daha fazla {{name}}", "more_with": "Daha fazla {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Medya Seçenekleri", "media_options": "Medya Seçenekleri",
"quality": "Kalite", "quality": "Kalite",
"audio": "Ses", "audio": "Ses",
"subtitles": "Altyazı", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Daha fazla göster", "show_more": "Daha fazla göster",
"show_less": "Daha az göster", "show_less": "Daha az göster",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Şurada yer aldı", "appeared_in": "Şurada yer aldı",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Öge yüklenemedi", "could_not_load_item": "Öge yüklenemedi",
"none": "Hiçbiri", "none": "Hiçbiri",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "{{item_count}} tane ögeyi indir", "download_x_item": "{{item_count}} tane ögeyi indir",
"download_unwatched_only": "Yalnızca İzlenmemişler", "download_unwatched_only": "Yalnızca İzlenmemişler",
"download_button": "İndir" "download_button": "İndir"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Sonraki", "next": "Sonraki",
@@ -652,7 +795,18 @@
"movies": "Filmler", "movies": "Filmler",
"sports": "Spor", "sports": "Spor",
"for_kids": "Çocuklar İçin", "for_kids": "Çocuklar İçin",
"news": "Haberler" "news": "Haberler",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Onayla", "confirm": "Onayla",
@@ -697,6 +851,12 @@
"decline": "Reddet", "decline": "Reddet",
"requested_by": "{{user}} tarafından istendi", "requested_by": "{{user}} tarafından istendi",
"unknown_user": "Bilinmeyen Kullanıcı", "unknown_user": "Bilinmeyen Kullanıcı",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Jellyseerr sunucusu minimum sürüm gereksinimlerini karşılamıyor! Lütfen en az 2.0.0 sürümüne güncelleyin", "jellyseer_does_not_meet_requirements": "Jellyseerr sunucusu minimum sürüm gereksinimlerini karşılamıyor! Lütfen en az 2.0.0 sürümüne güncelleyin",
"jellyseerr_test_failed": "Jellyseerr testi başarısız oldu. Lütfen tekrar deneyin.", "jellyseerr_test_failed": "Jellyseerr testi başarısız oldu. Lütfen tekrar deneyin.",
@@ -716,7 +876,8 @@
"search": "Ara", "search": "Ara",
"library": "Kütüphane", "library": "Kütüphane",
"custom_links": "Özel Bağlantılar", "custom_links": "Özel Bağlantılar",
"favorites": "Favoriler" "favorites": "Favoriler",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Müzik", "title": "Müzik",
@@ -841,5 +1002,36 @@
"show": "Bu dizide", "show": "Bu dizide",
"all": "Bütün medyalarda (varsayılan)" "all": "Bütün medyalarda (varsayılan)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Помилка", "error_title": "Помилка",
"login_title": "Вхід", "login_title": "Вхід",
"login_to_title": "Увійти в", "login_to_title": "Увійти в",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Імʼя користувача", "username_placeholder": "Імʼя користувача",
"password_placeholder": "Пароль", "password_placeholder": "Пароль",
"login_button": "Вхід", "login_button": "Вхід",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} accounts",
"select_account": "Select Account", "select_account": "Select Account",
"add_account": "Add Account", "add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "This will remove the saved credentials for {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "Save Account",
@@ -86,6 +95,7 @@
"oops": "Упс!", "oops": "Упс!",
"error_message": "Щось пішло не так.\nБудь ласка вийдіть і увійдіть знов.", "error_message": "Щось пішло не так.\nБудь ласка вийдіть і увійдіть знов.",
"continue_watching": "Продовжити перегляд", "continue_watching": "Продовжити перегляд",
"continue": "Continue",
"next_up": "Далі", "next_up": "Далі",
"continue_and_next_up": "Continue & Next Up", "continue_and_next_up": "Continue & Next Up",
"recently_added_in": "Нещодавно додане до \"{{libraryName}}\"", "recently_added_in": "Нещодавно додане до \"{{libraryName}}\"",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Параметри", "settings_title": "Параметри",
"log_out_button": "Вихід", "log_out_button": "Вихід",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Categories" "title": "Categories"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Appearance", "title": "Appearance",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up", "merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button" "hide_remote_session_button": "Hide Remote Session Button",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "Network",
@@ -174,6 +199,22 @@
"rewind_length": "Довжина перемотування назад", "rewind_length": "Довжина перемотування назад",
"seconds_unit": "с" "seconds_unit": "с"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Gesture Controls", "gesture_controls_title": "Gesture Controls",
"horizontal_swipe_skip": "Horizontal Swipe to Skip", "horizontal_swipe_skip": "Horizontal Swipe to Skip",
@@ -256,7 +297,23 @@
"subtitle_font": "Subtitle Font", "subtitle_font": "Subtitle Font",
"ksplayer_title": "KSPlayer Settings", "ksplayer_title": "KSPlayer Settings",
"hardware_decode": "Hardware Decoding", "hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues." "hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "VLC Subtitle Settings",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Music cache cleared", "music_cache_cleared": "Music cache cleared",
"delete_all_downloaded_songs": "Delete All Downloaded Songs", "delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded", "downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "Downloaded songs deleted",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Intro", "title": "Intro",
@@ -430,6 +493,21 @@
"error_deleting_files": "Помилка при видалені файлів", "error_deleting_files": "Помилка при видалені файлів",
"background_downloads_enabled": "Завантаження в фоні увімкнене", "background_downloads_enabled": "Завантаження в фоні увімкнене",
"background_downloads_disabled": "Завантаження в фоні вимкнене" "background_downloads_disabled": "Завантаження в фоні вимкнене"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "Нове оновлення вимагає повторного завантаження вмісту. Будь ласка, видаліть весь завантажений вміст і повторіть спробу.", "new_app_version_requires_re_download_description": "Нове оновлення вимагає повторного завантаження вмісту. Будь ласка, видаліть весь завантажений вміст і повторіть спробу.",
"back": "Назад", "back": "Назад",
"delete": "Видалити", "delete": "Видалити",
"delete_download": "Delete Download",
"something_went_wrong": "Щось пішло не так", "something_went_wrong": "Щось пішло не так",
"could_not_get_stream_url_from_jellyfin": "Не вдалося отримати URL-адресу потоку від Jellyfin", "could_not_get_stream_url_from_jellyfin": "Не вдалося отримати URL-адресу потоку від Jellyfin",
"eta": "ETA {{eta}}", "eta": "ETA {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Select", "select": "Select",
"no_trailer_available": "No trailer available", "no_trailer_available": "No trailer available",
"video": "Video", "video": "Video",
"audio": "Audio", "audio": "Audio",
"subtitle": "Subtitle", "subtitle": "Subtitle",
"play": "Play", "play": "Play",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "None", "none": "None",
"track": "Track", "track": "Track",
"cancel": "Cancel", "cancel": "Cancel",
"stop": "Stop",
"delete": "Delete", "delete": "Delete",
"ok": "OK", "ok": "OK",
"remove": "Remove", "remove": "Remove",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"continue": "Continue", "continue": "Continue",
"verifying": "Verifying..." "verifying": "Verifying...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Шукати...", "search": "Шукати...",
@@ -556,6 +641,7 @@
"movies": "фільми", "movies": "фільми",
"series": "серіали", "series": "серіали",
"boxsets": "бокс-сети", "boxsets": "бокс-сети",
"playlists": "Playlists",
"items": "елементи" "items": "елементи"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Постер", "poster": "Постер",
"cover": "Обкладинка", "cover": "Обкладинка",
"show_titles": "Показати заголовки", "show_titles": "Показати заголовки",
"show_stats": "Показати статистику" "show_stats": "Показати статистику",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Жанри", "genres": "Жанри",
@@ -574,7 +661,11 @@
"sort_by": "Відсортувати за", "sort_by": "Відсортувати за",
"filter_by": "Filter By", "filter_by": "Filter By",
"sort_order": "Порядок сортування", "sort_order": "Порядок сортування",
"tags": "Теги" "tags": "Теги",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "Немає посилань" "no_links": "Немає посилань"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Помилка", "error": "Помилка",
"failed_to_get_stream_url": "Не вдалося отримати URL-адресу потоку", "failed_to_get_stream_url": "Не вдалося отримати URL-адресу потоку",
"an_error_occured_while_playing_the_video": "Під час відтворення відео сталася помилка. Перевірте журнал в налаштуваннях.", "an_error_occured_while_playing_the_video": "Під час відтворення відео сталася помилка. Перевірте журнал в налаштуваннях.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Do you want to play the downloaded file?", "downloaded_file_message": "Do you want to play the downloaded file?",
"downloaded_file_yes": "Yes", "downloaded_file_yes": "Yes",
"downloaded_file_no": "No", "downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel" "downloaded_file_cancel": "Cancel",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "Далі", "next_up": "Далі",
@@ -617,6 +738,11 @@
"series": "Серіали", "series": "Серіали",
"seasons": "Сезони", "seasons": "Сезони",
"season": "Сезон", "season": "Сезон",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "У цьому сезоні немає епізодів", "no_episodes_for_this_season": "У цьому сезоні немає епізодів",
"overview": "Огляд", "overview": "Огляд",
"more_with": "Більше з {{name}}", "more_with": "Більше з {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Media Options", "media_options": "Media Options",
"quality": "Якість", "quality": "Якість",
"audio": "Аудіо", "audio": "Аудіо",
"subtitles": "Субтитри", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Показати більше", "show_more": "Показати більше",
"show_less": "Показати менше", "show_less": "Показати менше",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Зʼявлявся у", "appeared_in": "Зʼявлявся у",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Неможливо завантажити елемент", "could_not_load_item": "Неможливо завантажити елемент",
"none": "Нічого", "none": "Нічого",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Завантажено {{item_count}} елементів", "download_x_item": "Завантажено {{item_count}} елементів",
"download_unwatched_only": "Unwatched Only", "download_unwatched_only": "Unwatched Only",
"download_button": "Завантажити" "download_button": "Завантажити"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Наступний", "next": "Наступний",
@@ -652,7 +795,18 @@
"movies": "Фільми", "movies": "Фільми",
"sports": "Спорт", "sports": "Спорт",
"for_kids": "Для дітей", "for_kids": "Для дітей",
"news": "Новини" "news": "Новини",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Підтвердити", "confirm": "Підтвердити",
@@ -697,6 +851,12 @@
"decline": "Decline", "decline": "Decline",
"requested_by": "Requested by {{user}}", "requested_by": "Requested by {{user}}",
"unknown_user": "Unknown User", "unknown_user": "Unknown User",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Версія Jellyseerr не відповідає мінімальним вимогам! Будь ласка, оновіться принаймні до 2.0.0", "jellyseer_does_not_meet_requirements": "Версія Jellyseerr не відповідає мінімальним вимогам! Будь ласка, оновіться принаймні до 2.0.0",
"jellyseerr_test_failed": "Тест Jellyseerr завершився невдало. Спробуйте ще раз.", "jellyseerr_test_failed": "Тест Jellyseerr завершився невдало. Спробуйте ще раз.",
@@ -716,7 +876,8 @@
"search": "Пошук", "search": "Пошук",
"library": "Медіатека", "library": "Медіатека",
"custom_links": "Ваші Посилання", "custom_links": "Ваші Посилання",
"favorites": "Улюблене" "favorites": "Улюблене",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Music", "title": "Music",
@@ -841,5 +1002,36 @@
"show": "This show", "show": "This show",
"all": "All media (default)" "all": "All media (default)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Lỗi", "error_title": "Lỗi",
"login_title": "Đăng nhập", "login_title": "Đăng nhập",
"login_to_title": "Đăng nhập vào", "login_to_title": "Đăng nhập vào",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Tên người dùng", "username_placeholder": "Tên người dùng",
"password_placeholder": "Mật khẩu", "password_placeholder": "Mật khẩu",
"login_button": "Đăng nhập", "login_button": "Đăng nhập",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} accounts",
"select_account": "Select Account", "select_account": "Select Account",
"add_account": "Add Account", "add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "This will remove the saved credentials for {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "Save Account",
@@ -86,6 +95,7 @@
"oops": "Ối!", "oops": "Ối!",
"error_message": "Có lỗi xảy ra.\nVui lòng đăng xuất rồi đăng nhập lại.", "error_message": "Có lỗi xảy ra.\nVui lòng đăng xuất rồi đăng nhập lại.",
"continue_watching": "Tiếp tục xem", "continue_watching": "Tiếp tục xem",
"continue": "Continue",
"next_up": "Tiếp theo", "next_up": "Tiếp theo",
"continue_and_next_up": "Continue & Next Up", "continue_and_next_up": "Continue & Next Up",
"recently_added_in": "Mới thêm trong {{libraryName}}", "recently_added_in": "Mới thêm trong {{libraryName}}",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Cài đặt", "settings_title": "Cài đặt",
"log_out_button": "Đăng xuất", "log_out_button": "Đăng xuất",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Categories" "title": "Categories"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Appearance", "title": "Appearance",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up", "merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button" "hide_remote_session_button": "Hide Remote Session Button",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "Network",
@@ -174,6 +199,22 @@
"rewind_length": "Thời gian tua lui", "rewind_length": "Thời gian tua lui",
"seconds_unit": "s" "seconds_unit": "s"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Gesture Controls", "gesture_controls_title": "Gesture Controls",
"horizontal_swipe_skip": "Horizontal Swipe to Skip", "horizontal_swipe_skip": "Horizontal Swipe to Skip",
@@ -256,7 +297,23 @@
"subtitle_font": "Subtitle Font", "subtitle_font": "Subtitle Font",
"ksplayer_title": "KSPlayer Settings", "ksplayer_title": "KSPlayer Settings",
"hardware_decode": "Hardware Decoding", "hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues." "hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "VLC Subtitle Settings",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Music cache cleared", "music_cache_cleared": "Music cache cleared",
"delete_all_downloaded_songs": "Delete All Downloaded Songs", "delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded", "downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "Downloaded songs deleted",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Intro", "title": "Intro",
@@ -430,6 +493,21 @@
"error_deleting_files": "Lỗi khi xóa tập tin", "error_deleting_files": "Lỗi khi xóa tập tin",
"background_downloads_enabled": "Tải trong nền đã bật", "background_downloads_enabled": "Tải trong nền đã bật",
"background_downloads_disabled": "Tải trong nền đã tắt" "background_downloads_disabled": "Tải trong nền đã tắt"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "Cập nhật mới yêu cầu phải tải lại nội dung. Vui lòng xóa toàn bộ nội dung đã tải và thử lại.", "new_app_version_requires_re_download_description": "Cập nhật mới yêu cầu phải tải lại nội dung. Vui lòng xóa toàn bộ nội dung đã tải và thử lại.",
"back": "Quay lại", "back": "Quay lại",
"delete": "Xóa", "delete": "Xóa",
"delete_download": "Delete Download",
"something_went_wrong": "Đã xảy ra lỗi", "something_went_wrong": "Đã xảy ra lỗi",
"could_not_get_stream_url_from_jellyfin": "Không thể lấy URL phát trực tiếp từ Jellyfin", "could_not_get_stream_url_from_jellyfin": "Không thể lấy URL phát trực tiếp từ Jellyfin",
"eta": "Thời gian còn lại {{eta}}", "eta": "Thời gian còn lại {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Select", "select": "Select",
"no_trailer_available": "No trailer available", "no_trailer_available": "No trailer available",
"video": "Video", "video": "Video",
"audio": "Âm thanh", "audio": "Âm thanh",
"subtitle": "Phụ đề", "subtitle": "Phụ đề",
"play": "Play", "play": "Play",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "None", "none": "None",
"track": "Track", "track": "Track",
"cancel": "Cancel", "cancel": "Cancel",
"stop": "Stop",
"delete": "Delete", "delete": "Delete",
"ok": "OK", "ok": "OK",
"remove": "Remove", "remove": "Remove",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"continue": "Continue", "continue": "Continue",
"verifying": "Verifying..." "verifying": "Verifying...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Tìm...", "search": "Tìm...",
@@ -556,6 +641,7 @@
"movies": "phim", "movies": "phim",
"series": "chương trình", "series": "chương trình",
"boxsets": "bộ sưu tập", "boxsets": "bộ sưu tập",
"playlists": "Playlists",
"items": "nội dung" "items": "nội dung"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Ảnh bìa dọc", "poster": "Ảnh bìa dọc",
"cover": "Bìa", "cover": "Bìa",
"show_titles": "Hiển thị tiêu đề", "show_titles": "Hiển thị tiêu đề",
"show_stats": "Hiện thống kê" "show_stats": "Hiện thống kê",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Thể loại", "genres": "Thể loại",
@@ -574,7 +661,11 @@
"sort_by": "Sắp xếp theo", "sort_by": "Sắp xếp theo",
"filter_by": "Filter By", "filter_by": "Filter By",
"sort_order": "Thứ tự", "sort_order": "Thứ tự",
"tags": "Thẻ" "tags": "Thẻ",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "Chưa có liên kết" "no_links": "Chưa có liên kết"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Lỗi", "error": "Lỗi",
"failed_to_get_stream_url": "Không thể lấy URL phát trực tiếp", "failed_to_get_stream_url": "Không thể lấy URL phát trực tiếp",
"an_error_occured_while_playing_the_video": "Có lỗi khi phát video. Xem nhật ký trong cài đặt.", "an_error_occured_while_playing_the_video": "Có lỗi khi phát video. Xem nhật ký trong cài đặt.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Do you want to play the downloaded file?", "downloaded_file_message": "Do you want to play the downloaded file?",
"downloaded_file_yes": "Yes", "downloaded_file_yes": "Yes",
"downloaded_file_no": "No", "downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel" "downloaded_file_cancel": "Cancel",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "Tiếp theo", "next_up": "Tiếp theo",
@@ -617,6 +738,11 @@
"series": "Chương trình", "series": "Chương trình",
"seasons": "Mùa", "seasons": "Mùa",
"season": "Mùa", "season": "Mùa",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "Không có tập cho mùa này", "no_episodes_for_this_season": "Không có tập cho mùa này",
"overview": "Giới thiệu", "overview": "Giới thiệu",
"more_with": "Thêm với {{name}}", "more_with": "Thêm với {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Media Options", "media_options": "Media Options",
"quality": "Chất lượng", "quality": "Chất lượng",
"audio": "Âm thanh", "audio": "Âm thanh",
"subtitles": "Phụ đề", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Xem thêm", "show_more": "Xem thêm",
"show_less": "Thu gọn", "show_less": "Thu gọn",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Xuất hiện trong", "appeared_in": "Xuất hiện trong",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Không thể tải nội dung", "could_not_load_item": "Không thể tải nội dung",
"none": "Không có", "none": "Không có",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Tải {{item_count}} nội dung", "download_x_item": "Tải {{item_count}} nội dung",
"download_unwatched_only": "Unwatched Only", "download_unwatched_only": "Unwatched Only",
"download_button": "Tải" "download_button": "Tải"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Tiếp theo", "next": "Tiếp theo",
@@ -652,7 +795,18 @@
"movies": "Phim", "movies": "Phim",
"sports": "Thể thao", "sports": "Thể thao",
"for_kids": "Dành cho trẻ em", "for_kids": "Dành cho trẻ em",
"news": "Tin tức" "news": "Tin tức",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Xác nhận", "confirm": "Xác nhận",
@@ -697,6 +851,12 @@
"decline": "Decline", "decline": "Decline",
"requested_by": "Requested by {{user}}", "requested_by": "Requested by {{user}}",
"unknown_user": "Unknown User", "unknown_user": "Unknown User",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Máy chủ Jellyseerr không đạt yêu cầu tối thiểu! Vui lòng cập nhật lên ít nhất 2.0.0", "jellyseer_does_not_meet_requirements": "Máy chủ Jellyseerr không đạt yêu cầu tối thiểu! Vui lòng cập nhật lên ít nhất 2.0.0",
"jellyseerr_test_failed": "Kiểm tra Jellyseerr thất bại. Vui lòng thử lại.", "jellyseerr_test_failed": "Kiểm tra Jellyseerr thất bại. Vui lòng thử lại.",
@@ -716,7 +876,8 @@
"search": "Tìm kiếm", "search": "Tìm kiếm",
"library": "Thư viện", "library": "Thư viện",
"custom_links": "Liên kết tùy chỉnh", "custom_links": "Liên kết tùy chỉnh",
"favorites": "Yêu thích" "favorites": "Yêu thích",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Music", "title": "Music",
@@ -841,5 +1002,36 @@
"show": "This show", "show": "This show",
"all": "All media (default)" "all": "All media (default)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -4,6 +4,9 @@
"error_title": "Error", "error_title": "Error",
"login_title": "Log In", "login_title": "Log In",
"login_to_title": "Log in to", "login_to_title": "Log in to",
"select_user": "Select a user to log in",
"add_user_to_login": "Add a user to log in",
"add_user": "Add User",
"username_placeholder": "Username", "username_placeholder": "Username",
"password_placeholder": "Password", "password_placeholder": "Password",
"login_button": "Log In", "login_button": "Log In",
@@ -42,7 +45,13 @@
"accounts_count": "{{count}} accounts", "accounts_count": "{{count}} accounts",
"select_account": "Select Account", "select_account": "Select Account",
"add_account": "Add Account", "add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}." "remove_account_description": "This will remove the saved credentials for {{username}}.",
"remove_server": "Remove Server",
"remove_server_description": "This will remove {{server}} and all saved accounts from your list.",
"select_your_server": "Select Your Server",
"add_server_to_get_started": "Add a server to get started",
"add_server": "Add Server",
"change_server": "Change Server"
}, },
"save_account": { "save_account": {
"title": "Save Account", "title": "Save Account",
@@ -86,6 +95,7 @@
"oops": "Oops!", "oops": "Oops!",
"error_message": "Something went wrong.\nPlease log out and in again.", "error_message": "Something went wrong.\nPlease log out and in again.",
"continue_watching": "Continue Watching", "continue_watching": "Continue Watching",
"continue": "Continue",
"next_up": "Next Up", "next_up": "Next Up",
"continue_and_next_up": "Continue & Next Up", "continue_and_next_up": "Continue & Next Up",
"recently_added_in": "Recently Added in {{libraryName}}", "recently_added_in": "Recently Added in {{libraryName}}",
@@ -109,6 +119,12 @@
"settings": { "settings": {
"settings_title": "Settings", "settings_title": "Settings",
"log_out_button": "Log Out", "log_out_button": "Log Out",
"switch_user": {
"title": "Switch User",
"account": "Account",
"switch_user": "Switch User on This Server",
"current": "current"
},
"categories": { "categories": {
"title": "Categories" "title": "Categories"
}, },
@@ -121,7 +137,16 @@
"appearance": { "appearance": {
"title": "Appearance", "title": "Appearance",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up", "merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button" "hide_remote_session_button": "Hide Remote Session Button",
"show_home_backdrop": "Dynamic Home Backdrop",
"show_hero_carousel": "Hero Carousel",
"show_series_poster_on_episode": "Show Series Poster on Episodes",
"theme_music": "Theme Music",
"display_size": "Display Size",
"display_size_small": "Small",
"display_size_default": "Default",
"display_size_large": "Large",
"display_size_extra_large": "Extra Large"
}, },
"network": { "network": {
"title": "Network", "title": "Network",
@@ -174,6 +199,22 @@
"rewind_length": "Rewind Length", "rewind_length": "Rewind Length",
"seconds_unit": "s" "seconds_unit": "s"
}, },
"buffer": {
"title": "Buffer Settings",
"cache_mode": "Cache Mode",
"cache_auto": "Auto",
"cache_yes": "Enabled",
"cache_no": "Disabled",
"buffer_duration": "Buffer Duration",
"max_cache_size": "Max Cache Size",
"max_backward_cache": "Max Backward Cache"
},
"vo_driver": {
"title": "Video Output",
"vo_mode": "VO Driver",
"gpu_next": "gpu-next (Recommended)",
"gpu": "gpu"
},
"gesture_controls": { "gesture_controls": {
"gesture_controls_title": "Gesture Controls", "gesture_controls_title": "Gesture Controls",
"horizontal_swipe_skip": "Horizontal Swipe to Skip", "horizontal_swipe_skip": "Horizontal Swipe to Skip",
@@ -256,7 +297,23 @@
"subtitle_font": "Subtitle Font", "subtitle_font": "Subtitle Font",
"ksplayer_title": "KSPlayer Settings", "ksplayer_title": "KSPlayer Settings",
"hardware_decode": "Hardware Decoding", "hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues." "hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues.",
"opensubtitles_title": "OpenSubtitles",
"opensubtitles_hint": "Enter your OpenSubtitles API key to enable client-side subtitle search as a fallback when your Jellyfin server doesn't have a subtitle provider configured.",
"opensubtitles_api_key": "API Key",
"opensubtitles_api_key_placeholder": "Enter API key...",
"opensubtitles_get_key": "Get your free API key at opensubtitles.com/en/consumers",
"mpv_subtitle_scale": "Subtitle Scale",
"mpv_subtitle_margin_y": "Vertical Margin",
"mpv_subtitle_align_x": "Horizontal Align",
"mpv_subtitle_align_y": "Vertical Align",
"align": {
"left": "Left",
"center": "Center",
"right": "Right",
"top": "Top",
"bottom": "Bottom"
}
}, },
"vlc_subtitles": { "vlc_subtitles": {
"title": "VLC Subtitle Settings", "title": "VLC Subtitle Settings",
@@ -406,7 +463,13 @@
"music_cache_cleared": "Music cache cleared", "music_cache_cleared": "Music cache cleared",
"delete_all_downloaded_songs": "Delete All Downloaded Songs", "delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded", "downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted" "downloaded_songs_deleted": "Downloaded songs deleted",
"clear_all_cache": "Clear All Cache",
"clear_all_cache_confirm": "Clear All Cache?",
"clear_all_cache_confirm_desc": "Are you sure you want to clear all cached data? This will clear all cached images, music files, subtitles, and query caches. Your settings and login session will be kept.",
"clear_all_cache_success": "Cache Cleared",
"clear_all_cache_success_desc": "All cache has been cleared successfully.",
"clear_all_cache_error_desc": "An error occurred while clearing the cache."
}, },
"intro": { "intro": {
"title": "Intro", "title": "Intro",
@@ -430,6 +493,21 @@
"error_deleting_files": "Error Deleting Files", "error_deleting_files": "Error Deleting Files",
"background_downloads_enabled": "Background downloads enabled", "background_downloads_enabled": "Background downloads enabled",
"background_downloads_disabled": "Background downloads disabled" "background_downloads_disabled": "Background downloads disabled"
},
"security": {
"title": "Security",
"inactivity_timeout": {
"title": "Inactivity Timeout",
"description": "Auto logout after inactivity",
"disabled": "Disabled",
"1_minute": "1 minute",
"5_minutes": "5 minutes",
"15_minutes": "15 minutes",
"30_minutes": "30 minutes",
"1_hour": "1 hour",
"4_hours": "4 hours",
"24_hours": "24 hours"
}
} }
}, },
"sessions": { "sessions": {
@@ -456,6 +534,7 @@
"new_app_version_requires_re_download_description": "The new update requires content to be downloaded again. Please remove all downloaded content and try again.", "new_app_version_requires_re_download_description": "The new update requires content to be downloaded again. Please remove all downloaded content and try again.",
"back": "Back", "back": "Back",
"delete": "Delete", "delete": "Delete",
"delete_download": "Delete Download",
"something_went_wrong": "Something Went Wrong", "something_went_wrong": "Something Went Wrong",
"could_not_get_stream_url_from_jellyfin": "Could not get the stream URL from Jellyfin", "could_not_get_stream_url_from_jellyfin": "Could not get the stream URL from Jellyfin",
"eta": "ETA {{eta}}", "eta": "ETA {{eta}}",
@@ -492,22 +571,28 @@
} }
}, },
"common": { "common": {
"no_results": "No Results",
"select": "Select", "select": "Select",
"no_trailer_available": "No trailer available", "no_trailer_available": "No trailer available",
"video": "Video", "video": "Video",
"audio": "Audio", "audio": "Audio",
"subtitle": "Subtitle", "subtitle": "Subtitle",
"play": "Play", "play": "Play",
"mark_as_played": "Mark as Played",
"mark_as_not_played": "Mark as not Played",
"none": "None", "none": "None",
"track": "Track", "track": "Track",
"cancel": "Cancel", "cancel": "Cancel",
"stop": "Stop",
"delete": "Delete", "delete": "Delete",
"ok": "OK", "ok": "OK",
"remove": "Remove", "remove": "Remove",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"continue": "Continue", "continue": "Continue",
"verifying": "Verifying..." "verifying": "Verifying...",
"login": "Login",
"refresh": "Refresh"
}, },
"search": { "search": {
"search": "Search...", "search": "Search...",
@@ -556,6 +641,7 @@
"movies": "Movies", "movies": "Movies",
"series": "Series", "series": "Series",
"boxsets": "Box Sets", "boxsets": "Box Sets",
"playlists": "Playlists",
"items": "Items" "items": "Items"
}, },
"options": { "options": {
@@ -566,7 +652,8 @@
"poster": "Poster", "poster": "Poster",
"cover": "Cover", "cover": "Cover",
"show_titles": "Show Titles", "show_titles": "Show Titles",
"show_stats": "Show Stats" "show_stats": "Show Stats",
"options_title": "Options"
}, },
"filters": { "filters": {
"genres": "Genres", "genres": "Genres",
@@ -574,7 +661,11 @@
"sort_by": "Sort By", "sort_by": "Sort By",
"filter_by": "Filter By", "filter_by": "Filter By",
"sort_order": "Sort Order", "sort_order": "Sort Order",
"tags": "Tags" "tags": "Tags",
"all": "All",
"reset": "Reset",
"asc": "Ascending",
"desc": "Descending"
} }
}, },
"favorites": { "favorites": {
@@ -591,6 +682,8 @@
"no_links": "No Links" "no_links": "No Links"
}, },
"player": { "player": {
"live": "LIVE",
"mpv_player_title": "MPV Player",
"error": "Error", "error": "Error",
"failed_to_get_stream_url": "Failed to get the stream URL", "failed_to_get_stream_url": "Failed to get the stream URL",
"an_error_occured_while_playing_the_video": "An error occurred while playing the video. Check logs in settings.", "an_error_occured_while_playing_the_video": "An error occurred while playing the video. Check logs in settings.",
@@ -608,7 +701,35 @@
"downloaded_file_message": "Do you want to play the downloaded file?", "downloaded_file_message": "Do you want to play the downloaded file?",
"downloaded_file_yes": "Yes", "downloaded_file_yes": "Yes",
"downloaded_file_no": "No", "downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel" "downloaded_file_cancel": "Cancel",
"swipe_down_settings": "Swipe down for settings",
"ends_at": "Ends at {{time}}",
"search_subtitles": "Search Subtitles",
"subtitle_tracks": "Tracks",
"subtitle_search": "Search & Download",
"download": "Download",
"subtitle_download_hint": "Downloaded subtitles will be saved to your library",
"using_jellyfin_server": "Using Jellyfin Server",
"language": "Language",
"results": "Results",
"searching": "Searching...",
"search_failed": "Search failed",
"no_subtitle_provider": "No subtitle provider configured on server",
"no_subtitles_found": "No subtitles found",
"add_opensubtitles_key_hint": "Add OpenSubtitles API key in settings for client-side fallback",
"settings": "Settings",
"skip_intro": "Skip Intro",
"skip_credits": "Skip Credits",
"stopPlayback": "Stop Playback",
"stopPlayingTitle": "Stop playing \"{{title}}\"?",
"stopPlayingConfirm": "Are you sure you want to stop playback?",
"downloaded": "Downloaded"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
}, },
"item_card": { "item_card": {
"next_up": "Next Up", "next_up": "Next Up",
@@ -617,6 +738,11 @@
"series": "Series", "series": "Series",
"seasons": "Seasons", "seasons": "Seasons",
"season": "Season", "season": "Season",
"from_this_series": "From This Series",
"more_from_this_season": "More from this Season",
"view_series": "View Series",
"view_season": "View Season",
"select_season": "Select Season",
"no_episodes_for_this_season": "No episodes for this season", "no_episodes_for_this_season": "No episodes for this season",
"overview": "Overview", "overview": "Overview",
"more_with": "More with {{name}}", "more_with": "More with {{name}}",
@@ -627,10 +753,21 @@
"media_options": "Media Options", "media_options": "Media Options",
"quality": "Quality", "quality": "Quality",
"audio": "Audio", "audio": "Audio",
"subtitles": "Subtitle", "subtitles": {
"label": "Subtitle",
"none": "None",
"tracks": "Tracks"
},
"show_more": "Show More", "show_more": "Show More",
"show_less": "Show Less", "show_less": "Show Less",
"left": "left",
"more_info": "More Info",
"director": "Director",
"cast": "Cast",
"technical_details": "Technical Details",
"appeared_in": "Appeared In", "appeared_in": "Appeared In",
"movies": "Movies",
"shows": "Shows",
"could_not_load_item": "Could Not Load Item", "could_not_load_item": "Could Not Load Item",
"none": "None", "none": "None",
"download": { "download": {
@@ -641,7 +778,13 @@
"download_x_item": "Download {{item_count}} Items", "download_x_item": "Download {{item_count}} Items",
"download_unwatched_only": "Unwatched Only", "download_unwatched_only": "Unwatched Only",
"download_button": "Download" "download_button": "Download"
} },
"mark_played": "Mark as Watched",
"mark_unplayed": "Mark as Unwatched",
"resume_playback": "Resume Playback",
"resume_playback_description": "Do you want to continue where you left off or start from the beginning?",
"play_from_start": "Play from Start",
"continue_from": "Continue from {{time}}"
}, },
"live_tv": { "live_tv": {
"next": "Next", "next": "Next",
@@ -652,7 +795,18 @@
"movies": "Movies", "movies": "Movies",
"sports": "Sports", "sports": "Sports",
"for_kids": "For Kids", "for_kids": "For Kids",
"news": "News" "news": "News",
"page_of": "Page {{current}} of {{total}}",
"no_programs": "No programs available",
"no_channels": "No channels available",
"tabs": {
"programs": "Programs",
"guide": "Guide",
"channels": "Channels",
"recordings": "Recordings",
"schedule": "Schedule",
"series": "Series"
}
}, },
"jellyseerr": { "jellyseerr": {
"confirm": "Confirm", "confirm": "Confirm",
@@ -697,6 +851,12 @@
"decline": "Decline", "decline": "Decline",
"requested_by": "Requested by {{user}}", "requested_by": "Requested by {{user}}",
"unknown_user": "Unknown User", "unknown_user": "Unknown User",
"select": "Select",
"request_all": "Request All",
"request_seasons": "Request Seasons",
"select_seasons": "Select Seasons",
"request_selected": "Request Selected",
"n_selected": "{{count}} selected",
"toasts": { "toasts": {
"jellyseer_does_not_meet_requirements": "Seerr server does not meet minimum version requirements! Please update to at least 2.0.0", "jellyseer_does_not_meet_requirements": "Seerr server does not meet minimum version requirements! Please update to at least 2.0.0",
"jellyseerr_test_failed": "Seerr test failed. Please try again.", "jellyseerr_test_failed": "Seerr test failed. Please try again.",
@@ -716,7 +876,8 @@
"search": "Search", "search": "Search",
"library": "Library", "library": "Library",
"custom_links": "Custom Links", "custom_links": "Custom Links",
"favorites": "Favorites" "favorites": "Favorites",
"settings": "Settings"
}, },
"music": { "music": {
"title": "Music", "title": "Music",
@@ -841,5 +1002,36 @@
"show": "This show", "show": "This show",
"all": "All media (default)" "all": "All media (default)"
} }
},
"companion_login": {
"title": "Pair with TV",
"align_qr": "Align the QR code within the frame",
"enter_code_manually": "Enter code manually",
"pairing_enter_credentials": "Enter credentials for TV",
"pairing_code_label": "Pairing code",
"server": "Server",
"authorize_button": "Authorize",
"authorizing": "Authorizing...",
"scan_again": "Scan Again",
"done": "Done",
"success_title": "Authorization Sent",
"pairing_tv_connecting": "The TV is connecting to your account",
"error_title": "Authorization Failed",
"error_invalid_qr": "Invalid QR code. Please scan the TV pairing code.",
"error_generic": "Something went wrong. Please try again.",
"error_permission_denied": "Camera permission is required to scan QR codes.",
"login_as": "Log in as {{username}}?",
"on_server": "on {{server}}",
"use_different_user": "Use a different user",
"open_settings": "Open Settings"
},
"pairing": {
"pair_with_phone": "Pair with Phone",
"pair_with_phone_title": "Login TV",
"pair_with_phone_description": "Scan the QR code displayed on your TV to log in",
"waiting_for_phone": "Waiting for phone...",
"scan_with_phone": "Scan with the Streamyfin app on your phone",
"logging_in": "Logging in...",
"logging_in_description": "Connecting to your server"
} }
} }

View File

@@ -1,18 +0,0 @@
/**
* Convert bits to megabits or gigabits
*
* Return nice looking string
* If under 1000Mb, return XXXMB, else return X.XGB
*/
export function convertBitsToMegabitsOrGigabits(bits?: number | null): string {
if (!bits) return "0MB";
const megabits = bits / 1000000;
if (megabits < 1000) {
return `${Math.round(megabits)}MB`;
}
const gigabits = megabits / 1000;
return `${gigabits.toFixed(1)}GB`;
}

View File

@@ -1,47 +0,0 @@
import {
BaseItemKind,
CollectionType,
} from "@jellyfin/sdk/lib/generated-client";
/**
* Converts a ColletionType to a BaseItemKind (also called ItemType)
*
* CollectionTypes
* readonly Unknown: "unknown";
readonly Movies: "movies";
readonly Tvshows: "tvshows";
readonly Trailers: "trailers";
readonly Homevideos: "homevideos";
readonly Boxsets: "boxsets";
readonly Books: "books";
readonly Photos: "photos";
readonly Livetv: "livetv";
readonly Playlists: "playlists";
readonly Folders: "folders";
*/
export const colletionTypeToItemType = (
collectionType?: CollectionType | null,
): BaseItemKind | undefined => {
if (!collectionType) return undefined;
switch (collectionType) {
case CollectionType.Movies:
return BaseItemKind.Movie;
case CollectionType.Tvshows:
return BaseItemKind.Series;
case CollectionType.Homevideos:
return BaseItemKind.Video;
case CollectionType.Books:
return BaseItemKind.Book;
case CollectionType.Playlists:
return BaseItemKind.Playlist;
case CollectionType.Folders:
return BaseItemKind.Folder;
case CollectionType.Photos:
return BaseItemKind.Photo;
case CollectionType.Trailers:
return BaseItemKind.Trailer;
}
return undefined;
};

View File

@@ -1,56 +0,0 @@
import axios from "axios";
export interface SubtitleTrack {
index: number;
name: string;
uri: string;
language: string;
default: boolean;
forced: boolean;
autoSelect: boolean;
}
export async function parseM3U8ForSubtitles(
url: string,
): Promise<SubtitleTrack[]> {
try {
const response = await axios.get(url, { responseType: "text" });
const lines = response.data.split(/\r?\n/);
const subtitleTracks: SubtitleTrack[] = [];
let index = 0;
lines.forEach((line: string) => {
if (line.startsWith("#EXT-X-MEDIA:TYPE=SUBTITLES")) {
const attributes = parseAttributes(line);
const track: SubtitleTrack = {
index: index++,
name: attributes.NAME || "",
uri: attributes.URI || "",
language: attributes.LANGUAGE || "",
default: attributes.DEFAULT === "YES",
forced: attributes.FORCED === "YES",
autoSelect: attributes.AUTOSELECT === "YES",
};
subtitleTracks.push(track);
}
});
return subtitleTracks;
} catch (error) {
console.error("Failed to fetch or parse the M3U8 file:", error);
throw error;
}
}
function parseAttributes(line: string): { [key: string]: string } {
const attributes: { [key: string]: string } = {};
const regex = /([A-Z-]+)=(?:"([^"]*)"|([^,]*))/g;
for (const match of line.matchAll(regex)) {
const key = match[1];
const value = match[2] ?? match[3]; // quoted or unquoted
attributes[key] = value;
}
return attributes;
}

View File

@@ -1,56 +0,0 @@
import type { Api } from "@jellyfin/sdk";
import type { AxiosResponse } from "axios";
import type { Settings } from "../../atoms/settings";
import { generateDeviceProfile } from "../../profiles/native";
import { getAuthHeaders } from "../jellyfin";
interface PostCapabilitiesParams {
api: Api | null | undefined;
itemId: string | null | undefined;
sessionId: string | null | undefined;
deviceProfile: Settings["deviceProfile"];
}
/**
* Marks a media item as not played for a specific user.
*
* @param params - The parameters for marking an item as not played
* @returns A promise that resolves to true if the operation was successful, false otherwise
*/
export const postCapabilities = async ({
api,
itemId,
sessionId,
}: PostCapabilitiesParams): Promise<AxiosResponse> => {
if (!api || !itemId || !sessionId) {
throw new Error("Missing parameters for marking item as not played");
}
try {
const d = api.axiosInstance.post(
`${api.basePath}/Sessions/Capabilities/Full`,
{
playableMediaTypes: ["Audio", "Video"],
supportedCommands: [
"PlayState",
"Play",
"ToggleFullscreen",
"DisplayMessage",
"Mute",
"Unmute",
"SetVolume",
"ToggleMute",
],
supportsMediaControl: true,
id: sessionId,
DeviceProfile: generateDeviceProfile(),
},
{
headers: getAuthHeaders(api),
},
);
return d;
} catch (_error) {
throw new Error("Failed to mark as not played");
}
};

View File

@@ -1,44 +0,0 @@
import type { Api } from "@jellyfin/sdk";
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { getAuthHeaders } from "../jellyfin";
interface NextUpParams {
itemId?: string | null;
userId?: string | null;
api?: Api | null;
}
/**
* Fetches the next up episodes for a series or all series for a user.
*
* @param params - The parameters for fetching next up episodes
* @returns A promise that resolves to an array of BaseItemDto representing the next up episodes
*/
export const nextUp = async ({
itemId,
userId,
api,
}: NextUpParams): Promise<BaseItemDto[]> => {
if (!userId || !api) {
console.error("Invalid parameters for nextUp: missing userId or api");
return [];
}
try {
const response = await api.axiosInstance.get<{ Items: BaseItemDto[] }>(
`${api.basePath}/Shows/NextUp`,
{
params: {
SeriesId: itemId || undefined,
UserId: userId,
Fields: "MediaSourceCount",
},
headers: getAuthHeaders(api),
},
);
return response.data.Items;
} catch (_error) {
return [];
}
};

View File

@@ -1,34 +0,0 @@
import type { Api } from "@jellyfin/sdk";
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client/models";
import { getUserLibraryApi } from "@jellyfin/sdk/lib/utils/api";
/**
* Retrieves an item by its ID from the API.
*
* @param api - The Jellyfin API instance.
* @param itemId - The ID of the item to retrieve.
* @returns The item object or undefined if no item matches the ID.
*/
export const getItemById = async (
api?: Api | null | undefined,
itemId?: string | null | undefined,
): Promise<BaseItemDto | undefined> => {
if (!api || !itemId) {
return undefined;
}
try {
const itemData = await getUserLibraryApi(api).getItem({ itemId });
const item = itemData.data;
if (!item) {
console.error("No items found with the specified ID:", itemId);
return undefined;
}
return item;
} catch (error) {
console.error("Failed to retrieve the item:", error);
throw new Error(`Failed to retrieve the item due to an error: ${error}`);
}
};

View File

@@ -1,5 +0,0 @@
// seconds to ticks util
export function secondsToTicks(seconds: number): number {
return seconds * 10000000;
}