Compare commits

..

1 Commits

Author SHA1 Message Date
Crowdin Bot
6ec7f555bd feat(i18n): update translations from Crowdin 2026-05-30 07:23:23 +00:00
39 changed files with 1028 additions and 771 deletions

View File

@@ -1,54 +1,91 @@
<!--
Use a conventional commit title for the PR title,
for example `feat(auth): add MFA`
All sections below are required. Write N/A if a section is not applicable.
If you use AI to help implement this PR, you must declare it below. It's very important that the feature or fix implemented has been tested thoroughly by you personally on all target platforms. Only adding AI generated code without proper testing is not allowed and this PR will be closed immediately.
<!--
Pull Request Template for Streamyfin
====================================
Use this template to help reviewers understand the purpose of your PR
and to ensure all necessary checks are completed before merging.
-->
# 📦 Pull Request
<!--
🤖 AI ASSISTED?
Uncomment the line below if AI was used to assist with this PR:
-->
<!--
[![AI Assisted](https://img.shields.io/badge/AI_Assisted-18181b?style=for-the-badge&logo=openai&logoColor=white)](#) -->
## 📝 Description
## 🔖 Summary
<!--
A short description of the changes and why you're making them.
Example: “Add option to clean image cache, to mitigate stuck/blank movie poster issues.”
A concise description of the changes introduced by this PR.
Example:
“Add real-time currency conversion widget to dashboard.”
-->
## 🏷️ Ticket / Issue
<!--
Link to the related ticket, issue or user story.
Example: Fixes #123
You can also indicate if this PR supersedes a previous one.
Example:
- Closes #123
- Fixes STREAMYFIN-456
- Resolves #789
- Supersedes #120
- Related: #130
-->
### 🖼️ Screenshots / GIFs (if UI)
<!--
Include screenshots of relevant UI changes for both Android and iOS.
Before/After, responsive states (if relevant).
## 🛠️ Whats Changed
<!-- Use a Conventional Commit in the PR title, e.g., `feat(auth): add MFA`.
If this PR introduces a breaking change, include a `BREAKING CHANGE:` block in the description.
Spec: https://www.conventionalcommits.org/ -->
- Type: feat | fix | docs | style | refactor | perf | test | chore | build | ci | revert
- Scope (optional): e.g., auth, billing, mobile
- Short summary: what changed and why (12 lines)
-->
## 📋 Details
<!--
Provide more context or background. Explain any non-obvious decisions.
Include screenshots or GIFs for UI changes if applicable.
-->
### ⚠️ Breaking Changes
<!-- List any breaking API/contract changes and migration guidance. If none, write “None”. -->
### 🔐 Security & Privacy Impact
<!-- Data touched, new permissions/scopes, PII, secrets, threat considerations. If none, write “None”. -->
### ⚡ Performance Impact
<!-- Hot paths, memory/CPU/latency implications, benchmarks if available. -->
### 🖼️ Screenshots / GIFs (if UI)
<!-- Before/After, dark mode, responsive states. -->
## ✅ Checklist
<!--
Review and check off items as you complete them.
-->
- [ ] Ive read the [contribution guidelines](CONTRIBUTING.md)
- [ ] Verified that changes behave as expected for all platforms
- [ ] Code passes lint/formatting and type checks (`tsc`/`biome`)
- [ ] No secrets, hardcoded credentials, or private config files are included
- [ ] I've declared if AI was used to assist with this PR (by uncommenting the line at the bottom, or not)
- [ ] Code follows project style and passes lint/format (`npm|pnpm|yarn|bun` scripts)
- [ ] Type checks pass (tsc/biome/etc.)
- [ ] Docs updated (README/ADR/usage/API)
- [ ] No secrets/credentials included; env vars documented
- [ ] Release notes/CHANGELOG entry added (if applicable)
- [ ] Verified locally that changes behave as expected
## 🔍 Testing Instructions
<!--
Describe how reviewers can test your changes. This will help the PR get merged faster.
Describe how reviewers can test your changes.
Example:
1. Open the settings page and scroll to the bottom
2. Verify that the clear data button is visible and pressable
3. Verify that when you click the clear data button, a dialog appears prompting you to confirm
4. Verify that when you click the confirm button, the data is cleared and a toast message is displayed
1. `git fetch origin pull/<PR_ID>/head:branchname && git checkout branchname`
2. Install deps: `npm|pnpm|yarn|bun install`
3. Start service/app: `npm|pnpm|yarn|bun run [target]` (e.g., `npm run ios` or `bun run android:tv`)
4. Run tests: `npm|pnpm|yarn|bun test`
5. Verification steps:
- [ ] Expected UI/endpoint behavior
- [ ] Logs show no errors
- [ ] Edge cases covered (list)
-->
## ⚙️ Deployment Notes
<!--
Describe any deployment considerations such as config, environment vars, or native builds.
-->
## 📝 Additional Notes
<!--
Any other information or references related to this PR.
-->

4
.gitignore vendored
View File

@@ -72,6 +72,4 @@ modules/background-downloader/android/build/*
/modules/mpv-player/android/build
# ios:unsigned-build Artifacts
build/
.agents/skills/**
skills-lock.json
build/

View File

@@ -124,8 +124,8 @@
[
"./plugins/withGitPod.js",
{
"podName": "MPVKit",
"podspecUrl": "https://raw.githubusercontent.com/mpv-ios/MPVKit/0.41.0-av/MPVKit.podspec"
"podName": "MPVKit-GPL",
"podspecUrl": "https://raw.githubusercontent.com/streamyfin/MPVKit/0.40.0-av/MPVKit-GPL.podspec"
}
]
],

View File

@@ -9,7 +9,6 @@ import useRouter from "@/hooks/useAppRouter";
const Chromecast = Platform.isTV ? null : require("@/components/Chromecast");
import { useAtom } from "jotai";
import { HeaderBackButton } from "@/components/common/HeaderBackButton";
import { useSessions, type useSessionsProps } from "@/hooks/useSessions";
import { userAtom } from "@/providers/JellyfinProvider";
@@ -48,7 +47,15 @@ export default function IndexLayout() {
headerBlurEffect: "none",
headerTransparent: Platform.OS === "ios",
title: t("home.downloads.downloads_title"),
headerLeft: () => <HeaderBackButton />,
headerLeft: () => (
<Pressable
onPress={() => _router.back()}
className='pl-0.5'
style={{ marginRight: Platform.OS === "android" ? 16 : 0 }}
>
<Feather name='chevron-left' size={28} color='white' />
</Pressable>
),
}}
/>
<Stack.Screen
@@ -59,7 +66,15 @@ export default function IndexLayout() {
headerBlurEffect: "none",
headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
headerLeft: () => <HeaderBackButton />,
headerLeft: () => (
<Pressable
onPress={() => _router.back()}
className='pl-0.5'
style={{ marginRight: Platform.OS === "android" ? 16 : 0 }}
>
<Feather name='chevron-left' size={28} color='white' />
</Pressable>
),
}}
/>
<Stack.Screen
@@ -69,7 +84,15 @@ export default function IndexLayout() {
headerBlurEffect: "none",
headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
headerLeft: () => <HeaderBackButton />,
headerLeft: () => (
<Pressable
onPress={() => _router.back()}
className='pl-0.5'
style={{ marginRight: Platform.OS === "android" ? 16 : 0 }}
>
<Feather name='chevron-left' size={28} color='white' />
</Pressable>
),
}}
/>
<Stack.Screen
@@ -79,7 +102,15 @@ export default function IndexLayout() {
headerBlurEffect: "none",
headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
headerLeft: () => <HeaderBackButton />,
headerLeft: () => (
<Pressable
onPress={() => _router.back()}
className='pl-0.5'
style={{ marginRight: Platform.OS === "android" ? 16 : 0 }}
>
<Feather name='chevron-left' size={28} color='white' />
</Pressable>
),
}}
/>
<Stack.Screen
@@ -89,7 +120,15 @@ export default function IndexLayout() {
headerBlurEffect: "none",
headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
headerLeft: () => <HeaderBackButton />,
headerLeft: () => (
<Pressable
onPress={() => _router.back()}
className='pl-0.5'
style={{ marginRight: Platform.OS === "android" ? 16 : 0 }}
>
<Feather name='chevron-left' size={28} color='white' />
</Pressable>
),
}}
/>
<Stack.Screen
@@ -99,7 +138,15 @@ export default function IndexLayout() {
headerBlurEffect: "none",
headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
headerLeft: () => <HeaderBackButton />,
headerLeft: () => (
<Pressable
onPress={() => _router.back()}
className='pl-0.5'
style={{ marginRight: Platform.OS === "android" ? 16 : 0 }}
>
<Feather name='chevron-left' size={28} color='white' />
</Pressable>
),
}}
/>
<Stack.Screen
@@ -109,7 +156,15 @@ export default function IndexLayout() {
headerBlurEffect: "none",
headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
headerLeft: () => <HeaderBackButton />,
headerLeft: () => (
<Pressable
onPress={() => _router.back()}
className='pl-0.5'
style={{ marginRight: Platform.OS === "android" ? 16 : 0 }}
>
<Feather name='chevron-left' size={28} color='white' />
</Pressable>
),
}}
/>
<Stack.Screen
@@ -119,7 +174,15 @@ export default function IndexLayout() {
headerBlurEffect: "none",
headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
headerLeft: () => <HeaderBackButton />,
headerLeft: () => (
<Pressable
onPress={() => _router.back()}
className='pl-0.5'
style={{ marginRight: Platform.OS === "android" ? 16 : 0 }}
>
<Feather name='chevron-left' size={28} color='white' />
</Pressable>
),
}}
/>
<Stack.Screen
@@ -147,7 +210,15 @@ export default function IndexLayout() {
headerBlurEffect: "none",
headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
headerLeft: () => <HeaderBackButton />,
headerLeft: () => (
<Pressable
onPress={() => _router.back()}
className='pl-0.5'
style={{ marginRight: Platform.OS === "android" ? 16 : 0 }}
>
<Feather name='chevron-left' size={28} color='white' />
</Pressable>
),
}}
/>
<Stack.Screen
@@ -157,7 +228,15 @@ export default function IndexLayout() {
headerBlurEffect: "none",
headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
headerLeft: () => <HeaderBackButton />,
headerLeft: () => (
<Pressable
onPress={() => _router.back()}
className='pl-0.5'
style={{ marginRight: Platform.OS === "android" ? 16 : 0 }}
>
<Feather name='chevron-left' size={28} color='white' />
</Pressable>
),
}}
/>
<Stack.Screen
@@ -167,7 +246,15 @@ export default function IndexLayout() {
headerBlurEffect: "none",
headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
headerLeft: () => <HeaderBackButton />,
headerLeft: () => (
<Pressable
onPress={() => _router.back()}
className='pl-0.5'
style={{ marginRight: Platform.OS === "android" ? 16 : 0 }}
>
<Feather name='chevron-left' size={28} color='white' />
</Pressable>
),
}}
/>
<Stack.Screen
@@ -177,7 +264,15 @@ export default function IndexLayout() {
headerBlurEffect: "none",
headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
headerLeft: () => <HeaderBackButton />,
headerLeft: () => (
<Pressable
onPress={() => _router.back()}
className='pl-0.5'
style={{ marginRight: Platform.OS === "android" ? 16 : 0 }}
>
<Feather name='chevron-left' size={28} color='white' />
</Pressable>
),
}}
/>
<Stack.Screen
@@ -187,7 +282,15 @@ export default function IndexLayout() {
headerBlurEffect: "none",
headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
headerLeft: () => <HeaderBackButton />,
headerLeft: () => (
<Pressable
onPress={() => _router.back()}
className='pl-0.5'
style={{ marginRight: Platform.OS === "android" ? 16 : 0 }}
>
<Feather name='chevron-left' size={28} color='white' />
</Pressable>
),
}}
/>
<Stack.Screen
@@ -197,7 +300,15 @@ export default function IndexLayout() {
headerBlurEffect: "none",
headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
headerLeft: () => <HeaderBackButton />,
headerLeft: () => (
<Pressable
onPress={() => _router.back()}
className='pl-0.5'
style={{ marginRight: Platform.OS === "android" ? 16 : 0 }}
>
<Feather name='chevron-left' size={28} color='white' />
</Pressable>
),
}}
/>
<Stack.Screen
@@ -207,7 +318,15 @@ export default function IndexLayout() {
headerBlurEffect: "none",
headerTransparent: Platform.OS === "ios",
headerShadowVisible: false,
headerLeft: () => <HeaderBackButton />,
headerLeft: () => (
<Pressable
onPress={() => _router.back()}
className='pl-0.5'
style={{ marginRight: Platform.OS === "android" ? 16 : 0 }}
>
<Feather name='chevron-left' size={28} color='white' />
</Pressable>
),
}}
/>
{Object.entries(nestedTabPageScreenOptions).map(([name, options]) => (
@@ -217,7 +336,11 @@ export default function IndexLayout() {
name='collections/[collectionId]'
options={{
title: "",
headerLeft: () => <HeaderBackButton />,
headerLeft: () => (
<Pressable onPress={() => _router.back()} className='pl-0.5'>
<Feather name='chevron-left' size={28} color='white' />
</Pressable>
),
headerShown: true,
headerBlurEffect: "prominent",
headerTransparent: Platform.OS === "ios",

View File

@@ -1686,7 +1686,7 @@
"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"],
"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-udp": ["react-native-udp@4.1.7", "", { "dependencies": { "buffer": "^5.6.0", "events": "^3.1.0" } }, "sha512-NUE3zewu61NCdSsLlj+l0ad6qojcVEZPT4hVG/x6DU9U4iCzwtfZSASh9vm7teAcVzLkdD+cO3411LHshAi/wA=="],

View File

@@ -1,4 +1,4 @@
import { Button, ContextMenu, Host } from "@expo/ui/swift-ui";
import { Button, ContextMenu, Host, Picker } from "@expo/ui/swift-ui";
import { Ionicons } from "@expo/vector-icons";
import { BottomSheetScrollView } from "@gorhom/bottom-sheet";
import React, { useEffect } from "react";
@@ -254,39 +254,23 @@ const PlatformDropdownComponent = ({
// Otherwise render as individual buttons
if (radioOptions.length > 0) {
if (group.title) {
// Use a nested ContextMenu as a submenu for grouped options
const selectedOption = radioOptions.find(
(opt) => opt.selected,
);
const displayTitle = selectedOption
? `${group.title}: ${selectedOption.label}`
: group.title;
// Use Picker for grouped options
items.push(
<ContextMenu key={`submenu-${groupIndex}`}>
<ContextMenu.Trigger>
<Button>{displayTitle}</Button>
</ContextMenu.Trigger>
<ContextMenu.Items>
{radioOptions.map((option, optionIndex) => (
<Button
key={`radio-${groupIndex}-${optionIndex}`}
systemImage={
option.selected
? "checkmark.circle.fill"
: "circle"
}
onPress={() => {
option.onPress();
onOptionSelect?.(option.value);
}}
disabled={option.disabled}
>
{option.label}
</Button>
))}
</ContextMenu.Items>
</ContextMenu>,
<Picker
key={`picker-${groupIndex}`}
label={group.title}
options={radioOptions.map((opt) => opt.label)}
variant='menu'
selectedIndex={radioOptions.findIndex(
(opt) => opt.selected,
)}
onOptionSelected={(event: any) => {
const index = event.nativeEvent.index;
const selectedOption = radioOptions[index];
selectedOption?.onPress();
onOptionSelect?.(selectedOption?.value);
}}
/>,
);
} else {
// Render radio options as direct buttons

View File

@@ -1,4 +1,4 @@
import { Button, ContextMenu, Host } from "@expo/ui/swift-ui";
import { Button, ContextMenu, Host, Picker } from "@expo/ui/swift-ui";
import { Platform, View } from "react-native";
import { FilterButton } from "@/components/filters/FilterButton";
import { JellyseerrSearchSort } from "@/components/jellyseerr/JellyseerrIndexPage";
@@ -49,66 +49,32 @@ export const DiscoverFilters: React.FC<DiscoverFiltersProps> = ({
></Button>
</ContextMenu.Trigger>
<ContextMenu.Items>
<ContextMenu>
<ContextMenu.Trigger>
<Button>
{`${t("library.filters.sort_by")}: ${t(
`home.settings.plugins.jellyseerr.order_by.${jellyseerrOrderBy}`,
)}`}
</Button>
</ContextMenu.Trigger>
<ContextMenu.Items>
{sortOptions.map((item) => {
const label = t(
`home.settings.plugins.jellyseerr.order_by.${item}`,
);
const isSelected =
jellyseerrOrderBy ===
(item as unknown as JellyseerrSearchSort);
return (
<Button
key={item}
systemImage={
isSelected ? "checkmark.circle.fill" : "circle"
}
onPress={() =>
setJellyseerrOrderBy(
item as unknown as JellyseerrSearchSort,
)
}
>
{label}
</Button>
);
})}
</ContextMenu.Items>
</ContextMenu>
<ContextMenu>
<ContextMenu.Trigger>
<Button>
{`${t("library.filters.sort_order")}: ${t(
`library.filters.${jellyseerrSortOrder}`,
)}`}
</Button>
</ContextMenu.Trigger>
<ContextMenu.Items>
{orderOptions.map((item) => {
const label = t(`library.filters.${item}`);
const isSelected = jellyseerrSortOrder === item;
return (
<Button
key={item}
systemImage={
isSelected ? "checkmark.circle.fill" : "circle"
}
onPress={() => setJellyseerrSortOrder(item)}
>
{label}
</Button>
);
})}
</ContextMenu.Items>
</ContextMenu>
<Picker
label={t("library.filters.sort_by")}
options={sortOptions.map((item) =>
t(`home.settings.plugins.jellyseerr.order_by.${item}`),
)}
variant='menu'
selectedIndex={sortOptions.indexOf(
jellyseerrOrderBy as unknown as string,
)}
onOptionSelected={(event: any) => {
const index = event.nativeEvent.index;
setJellyseerrOrderBy(
sortOptions[index] as unknown as JellyseerrSearchSort,
);
}}
/>
<Picker
label={t("library.filters.sort_order")}
options={orderOptions.map((item) => t(`library.filters.${item}`))}
variant='menu'
selectedIndex={orderOptions.indexOf(jellyseerrSortOrder)}
onOptionSelected={(event: any) => {
const index = event.nativeEvent.index;
setJellyseerrSortOrder(orderOptions[index]);
}}
/>
</ContextMenu.Items>
</ContextMenu>
</Host>

View File

@@ -177,9 +177,6 @@ export const useAddToWatchlist = () => {
}
},
onSuccess: (_data, variables) => {
queryClient.invalidateQueries({
queryKey: ["streamystats", "watchlists"],
});
queryClient.invalidateQueries({
queryKey: ["streamystats", "watchlist", variables.watchlistId],
});
@@ -238,9 +235,6 @@ export const useRemoveFromWatchlist = () => {
}
},
onSuccess: (_data, variables) => {
queryClient.invalidateQueries({
queryKey: ["streamystats", "watchlists"],
});
queryClient.invalidateQueries({
queryKey: ["streamystats", "watchlist", variables.watchlistId],
});

View File

@@ -220,27 +220,20 @@ final class MPVLayerRenderer {
statusObservation?.invalidate()
statusObservation = nil
if let handle = self.mpv {
self.mpv = nil
// Remove the wakeup callback synchronously while `self` is still
// alive so it can never fire against a deallocated instance.
queue.sync { [weak self] in
guard let self, let handle = self.mpv else { return }
mpv_set_wakeup_callback(handle, nil, nil)
// Destroy mpv OFF the main thread. mpv_terminate_destroy() blocks
// until all mpv threads (including the vo_avfoundation output thread)
// are joined, and that teardown needs the main run loop to finish.
// Calling it via queue.sync from deinit (main thread) deadlocks/freezes
// the UI. queue.async only references `handle`, never `self`.
queue.async {
mpv_terminate_destroy(handle)
}
mpv_terminate_destroy(handle)
self.mpv = nil
}
let layer = self.displayLayer
DispatchQueue.main.async {
DispatchQueue.main.async { [weak self] in
guard let self else { return }
if #available(iOS 18.0, *) {
layer.sampleBufferRenderer.flush(removingDisplayedImage: true, completionHandler: nil)
self.displayLayer.sampleBufferRenderer.flush(removingDisplayedImage: true, completionHandler: nil)
} else {
layer.flushAndRemoveImage()
self.displayLayer.flushAndRemoveImage()
}
}

View File

@@ -1,19 +1,32 @@
Pod::Spec.new do |s|
s.name = 'MpvPlayer'
s.version = '1.0.0'
s.summary = 'MPV-based video player for Streamyfin (Expo module)'
s.author = 'Streamyfin'
s.homepage = 'https://github.com/streamyfin/streamyfin'
s.platforms = { :ios => '15.1', :tvos => '15.1' }
s.source = { git: '' }
s.name = 'MpvPlayer'
s.version = '1.0.0'
s.summary = 'MPVKit for Expo'
s.description = 'MPVKit for Expo'
s.author = 'mpvkit'
s.homepage = 'https://github.com/mpvkit/MPVKit'
s.platforms = {
:ios => '15.1',
:tvos => '15.1'
}
s.source = { git: 'https://github.com/mpvkit/MPVKit.git' }
s.static_framework = true
s.dependency 'ExpoModulesCore'
s.dependency 'MPVKit'
s.dependency 'MPVKit-GPL'
# Swift/Objective-C compatibility
s.pod_target_xcconfig = {
'DEFINES_MODULE' => 'YES',
'SWIFT_COMPILATION_MODE' => 'wholemodule'
'VALID_ARCHS' => 'arm64',
'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}"

View File

@@ -150,16 +150,6 @@ final class PiPController: NSObject {
CMTimebaseSetRate(tb, rate: Float64(rate))
}
}
deinit {
if let tb = timebase {
CMTimebaseSetRate(tb, rate: 0)
}
sampleBufferDisplayLayer?.controlTimebase = nil
timebase = nil
pipController?.delegate = nil
pipController = nil
}
}
// MARK: - AVPictureInPictureControllerDelegate

View File

@@ -30,48 +30,48 @@
"connect_button": "اتصل",
"previous_servers": "الخوادم السابقة",
"clear_button": "مسح",
"swipe_to_remove": "Swipe to remove",
"swipe_to_remove": "مرر للإزالة",
"search_for_local_servers": "البحث عن الخوادم المحلية",
"searching": "جاري البحث...",
"servers": "الخوادم",
"saved": "Saved",
"session_expired": "Session Expired",
"please_login_again": "Your saved session has expired. Please log in again.",
"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.",
"accounts_count": "{{count}} accounts",
"select_account": "Select Account",
"add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}."
"saved": "تم الحفظ",
"session_expired": "انتهت الجلسة",
"please_login_again": "انتهت مدة صلاحية جلستك. الرجاء تسجيل الدخول مرة أخرى.",
"remove_saved_login": "إزالة تسجيل دخول محفوظ",
"remove_saved_login_description": "سيؤدي هذا إلى إزالة بيانات تسجيل الدخول الخاص بك المحفوظة لهذا الخادم. ستحتاج إلى إدخال اسم المستخدم وكلمة المرور مرة أخرى في المرة القادمة.",
"accounts_count": "الحسابات {{count}}",
"select_account": "اختر الحساب",
"add_account": "إضافة حساب",
"remove_account_description": "سيؤدي هذا إلى إزالة بيانات تسجيل الدخول لـ {{username}}."
},
"save_account": {
"title": "Save Account",
"save_for_later": "Save this account",
"security_option": "Security Option",
"no_protection": "No protection",
"no_protection_desc": "Quick login without authentication",
"pin_code": "PIN code",
"pin_code_desc": "4-digit PIN required when switching",
"password": "Re-enter password",
"password_desc": "Password required when switching",
"save_button": "Save",
"cancel_button": "Cancel"
"title": "حفظ الحساب",
"save_for_later": "حفظ هذا الحساب",
"security_option": "‮خيارات الأمان",
"no_protection": "بدون حماية",
"no_protection_desc": "تسجيل دخول سريع بدون مصادقة",
"pin_code": "رمز PIN",
"pin_code_desc": "رمز PIN مكون من 4 أرقام مطلوب عند التبديل",
"password": "أعد إدخال كلمة المرور",
"password_desc": "كلمة المرور مطلوبة عند التبديل",
"save_button": "حفظ",
"cancel_button": "إلغاء"
},
"pin": {
"enter_pin": "Enter PIN",
"enter_pin_for": "Enter PIN for {{username}}",
"enter_4_digits": "Enter 4 digits",
"invalid_pin": "Invalid PIN",
"setup_pin": "Set Up PIN",
"confirm_pin": "Confirm PIN",
"pins_dont_match": "PINs don't match",
"forgot_pin": "Forgot PIN?",
"forgot_pin_desc": "Your saved credentials will be removed"
"enter_pin": "‏أدخل رمز PIN",
"enter_pin_for": "أدخل رمز PIN لـ {{username}}",
"enter_4_digits": "ادخل 4 أرقام",
"invalid_pin": "PIN غير صالح",
"setup_pin": "تعيين رمز PIN",
"confirm_pin": "تأكيد رمز PIN",
"pins_dont_match": "رموز PIN غير متطابقة",
"forgot_pin": "نسيت رمز PIN؟",
"forgot_pin_desc": "سيتم إزالة بيانات تسجيل الدخول المحفوظة الخاصة بك"
},
"password": {
"enter_password": "Enter Password",
"enter_password_for": "Enter password for {{username}}",
"invalid_password": "Invalid password"
"enter_password": "أدخل كلمة المرور",
"enter_password_for": "أدخل كلمة المرور لـ {{username}}",
"invalid_password": "كلمة المرور غير صحيحة"
},
"home": {
"checking_server_connection": "التحقق من اتصال الخادم...",
@@ -87,7 +87,7 @@
"error_message": "حدث خطأ ما.\nيرجى تسجيل الخروج ثم الدخول مرة أخرى.",
"continue_watching": "متابعة المشاهدة",
"next_up": "التالي",
"continue_and_next_up": "Continue & Next Up",
"continue_and_next_up": "تابع و التالي",
"recently_added_in": "أضيف مؤخراً في {{libraryName}}",
"suggested_movies": "أفلام مقترحة",
"suggested_episodes": "حلقات مقترحة",
@@ -120,36 +120,36 @@
},
"appearance": {
"title": "المظهر",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button"
"merge_next_up_continue_watching": "دمج تابع المشاهدة والتالي",
"hide_remote_session_button": "إخفاء زر جلسة البث عن بُعد"
},
"network": {
"title": "Network",
"local_network": "Local Network",
"auto_switch_enabled": "Auto-switch when at home",
"auto_switch_description": "Automatically switch to local URL when connected to home WiFi",
"local_url": "Local URL",
"local_url_hint": "Enter your local server address (e.g., http://192.168.1.100:8096)",
"title": "الشبكة",
"local_network": "الشبكة المحلية",
"auto_switch_enabled": "التبديل التلقائي عند المنزل",
"auto_switch_description": "التبديل تلقائياً إلى رابط URL محلي عند الاتصال بشبكة WiFi المنزلية",
"local_url": "رابط محلي",
"local_url_hint": "أدخل عنوان الخادم المحلي الخاص بك (على سبيل المثال http://192.168.1.100:8096)",
"local_url_placeholder": "http://192.168.1.100:8096",
"home_wifi_networks": "Home WiFi Networks",
"add_current_network": "Add \"{{ssid}}\"",
"not_connected_to_wifi": "Not connected to WiFi",
"no_networks_configured": "No networks configured",
"add_network_hint": "Add your home WiFi network to enable auto-switching",
"current_wifi": "Current WiFi",
"using_url": "Using",
"local": "Local URL",
"remote": "Remote URL",
"not_connected": "Not connected",
"current_server": "Current Server",
"remote_url": "Remote URL",
"active_url": "Active URL",
"not_configured": "Not configured",
"network_added": "Network added",
"network_already_added": "Network already added",
"no_wifi_connected": "Not connected to WiFi",
"permission_denied": "Location permission denied",
"permission_denied_explanation": "Location permission is required to detect WiFi network for auto-switching. Please enable it in Settings."
"home_wifi_networks": "شبكات WiFi المنزل",
"add_current_network": "إضافة \"{{ssid}}\"",
"not_connected_to_wifi": "غير متصل بشبكة WiFi",
"no_networks_configured": "لا توجد شبكات مكونة",
"add_network_hint": "إضافة شبكة WiFi المنزلية الخاصة بك لتمكين التبديل التلقائي",
"current_wifi": "شبكة WiFi الحالية",
"using_url": "استخدام",
"local": "رابط محلي",
"remote": "الـ URL الخارجي",
"not_connected": "غير متصل",
"current_server": "الخادم الحالي",
"remote_url": "الـ URL الخارجي",
"active_url": "الرابط النشط",
"not_configured": "لم يتم تكوينه",
"network_added": "تمت إضافة الشبكة",
"network_already_added": "الشبكة مضافة مسبقاً",
"no_wifi_connected": "غير متصل بشبكة WiFi",
"permission_denied": "تم رفض إذن الوصول إلى الموقع",
"permission_denied_explanation": "يتطلب التعرف على شبكة WiFi للتبديل التلقائي الحصول على إذن الوصول إلى الموقع. يرجى تفعيله من الإعدادات."
},
"user_info": {
"user_info_title": "معلومات المستخدم",
@@ -182,10 +182,10 @@
"left_side_brightness_description": "اسحب لأعلى/لأسفل على الجانب الأيسر لضبط السطوع",
"right_side_volume": "التحكم في مستوى الصوت من الجانب الأيمن",
"right_side_volume_description": "اسحب لأعلى/لأسفل على الجانب الأيمن لضبط مستوى الصوت",
"hide_volume_slider": "Hide Volume Slider",
"hide_volume_slider_description": "Hide the volume slider in the video player",
"hide_brightness_slider": "Hide Brightness Slider",
"hide_brightness_slider_description": "Hide the brightness slider in the video player"
"hide_volume_slider": "إخفاء شريط مستوى الصوت",
"hide_volume_slider_description": "إخفاء شريط التحكم في مستوى الصوت في مشغل الفيديو",
"hide_brightness_slider": "إخفاء شريط السطوع",
"hide_brightness_slider_description": "إخفاء شريط التحكم في السطوع في مشغل الفيديو"
},
"audio": {
"audio_title": "الصوت",
@@ -195,12 +195,12 @@
"none": "لا شيء",
"language": "اللغة",
"transcode_mode": {
"title": "Audio Transcoding",
"description": "Controls how surround audio (7.1, TrueHD, DTS-HD) is handled",
"auto": "Auto",
"stereo": "Force Stereo",
"5_1": "Allow 5.1",
"passthrough": "Passthrough"
"title": "تحويل ترميز الصوت",
"description": "يتحكم في كيفية التعامل مع الصوت المحيطي (7.1، TrueHD، DTS-HD)",
"auto": "تلقائي",
"stereo": "إجبار تشغيل ستيريو",
"5_1": "السماح بـ 5.1",
"passthrough": "تمرير الصوت"
}
},
"subtitles": {
@@ -251,29 +251,29 @@
"Normal": "عادي",
"Thick": "سميك"
},
"subtitle_color": "Subtitle Color",
"subtitle_background_color": "Background Color",
"subtitle_font": "Subtitle Font",
"ksplayer_title": "KSPlayer Settings",
"hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues."
"subtitle_color": "لون الترجمة",
"subtitle_background_color": "لون الخلفية",
"subtitle_font": "خط الترجمة",
"ksplayer_title": "إعدادات KSPlayer",
"hardware_decode": "فك الترميز بواسطة الجهاز",
"hardware_decode_description": "استخدم تسريع العتاد لفك ترميز الفيديو. قم بتعطيله إذا واجهت مشكلات في التشغيل."
},
"vlc_subtitles": {
"title": "VLC Subtitle Settings",
"hint": "Customize subtitle appearance for VLC player. Changes take effect on next playback.",
"text_color": "Text Color",
"background_color": "Background Color",
"background_opacity": "Background Opacity",
"outline_color": "Outline Color",
"outline_opacity": "Outline Opacity",
"outline_thickness": "Outline Thickness",
"bold": "Bold Text",
"margin": "Bottom Margin"
"title": "إعدادات ترجمة VLC",
"hint": "تخصيص مظهر الترجمة لمشغل VLC. تصبح التغييرات سارية المفعول عند التشغيل التالي.",
"text_color": "لون النص",
"background_color": "لون الخلفية",
"background_opacity": "شفافية الخلفية",
"outline_color": "لون إطار الخط",
"outline_opacity": "شفافية إطار الخط",
"outline_thickness": "سمك إطار الخط",
"bold": "خط عريض",
"margin": "الهامش السفلي"
},
"video_player": {
"title": "Video Player",
"video_player": "Video Player",
"video_player_description": "Choose which video player to use on iOS.",
"title": "مشغل الفيديو",
"video_player": "مشغل الفيديو",
"video_player_description": "اختر مشغل الفيديو الذي سيتم استخدامه على نظام iOS.",
"ksplayer": "KSPlayer",
"vlc": "VLC"
},
@@ -305,8 +305,8 @@
"select_liraries_you_want_to_hide": "اختر المكتبات التي تريد إخفاءها من تبويب المكتبة وأقسام الصفحة الرئيسية.",
"disable_haptic_feedback": "تعطيل ردود الفعل اللمسية",
"default_quality": "الجودة الافتراضية",
"default_playback_speed": "Default Playback Speed",
"auto_play_next_episode": "Auto-play Next Episode",
"default_playback_speed": "سرعة التشغيل الافتراضية",
"auto_play_next_episode": "تشغيل الحلقة التالية تلقائياً",
"max_auto_play_episode_count": "الحد الأقصى لعدد الحلقات التي يتم تشغيلها تلقائيًا",
"disabled": "معطل"
},
@@ -314,15 +314,15 @@
"downloads_title": "التنزيلات"
},
"music": {
"title": "Music",
"playback_title": "Playback",
"playback_description": "Configure how music is played.",
"prefer_downloaded": "Prefer Downloaded Songs",
"caching_title": "Caching",
"caching_description": "Automatically cache upcoming tracks for smoother playback.",
"lookahead_enabled": "Enable Look-Ahead Caching",
"lookahead_count": "Tracks to Pre-cache",
"max_cache_size": "Max Cache Size"
"title": "الموسيقى",
"playback_title": "التشغيل",
"playback_description": "ضبط كيفية تشغيل الموسيقى.",
"prefer_downloaded": "تفضيل الأغاني التي تم تنزيلها",
"caching_title": "التخزين المؤقت",
"caching_description": "تخزين الأغاني التالية مؤقتاً تلقائياً لضمان تشغيل أكثر سلاسة.",
"lookahead_enabled": "تفعيل التخزين المؤقت الاستباقي",
"lookahead_count": "عدد الأغاني المراد تخزينها مسبقاً",
"max_cache_size": "الحد الأقصى لحجم التخزين المؤقت"
},
"plugins": {
"plugins_title": "الإضافات",
@@ -357,39 +357,39 @@
"save_button": "حفظ",
"toasts": {
"saved": "تم الحفظ",
"refreshed": "Settings refreshed from server"
"refreshed": "تم تحديث الإعدادات من الخادم"
},
"refresh_from_server": "Refresh Settings from Server"
"refresh_from_server": "تحديث الإعدادات من الخادم"
},
"streamystats": {
"enable_streamystats": "Enable Streamystats",
"disable_streamystats": "Disable Streamystats",
"enable_search": "Use for Search",
"url": "URL",
"enable_streamystats": "تفعيل Streamystats",
"disable_streamystats": "تعطيل Streamystats",
"enable_search": "استخدم للبحث",
"url": "الرابط",
"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.",
"read_more_about_streamystats": "Read More About Streamystats.",
"save_button": "Save",
"save": "Save",
"features_title": "Features",
"home_sections_title": "Home Sections",
"enable_movie_recommendations": "Movie Recommendations",
"enable_series_recommendations": "Series Recommendations",
"enable_promoted_watchlists": "Promoted Watchlists",
"hide_watchlists_tab": "Hide Watchlists Tab",
"home_sections_hint": "Show personalized recommendations and promoted watchlists from Streamystats on the home page.",
"recommended_movies": "Recommended Movies",
"recommended_series": "Recommended Series",
"streamystats_search_hint": "أدخل رابط خادم Streamystats الخاص بك. يجب أن يتضمن الرابط البروتوكول http أو https مع رقم المنفذ اختيارياً.",
"read_more_about_streamystats": "اقرأ المزيد عن Streamystats.",
"save_button": "حفظ",
"save": "حفظ",
"features_title": "المميزات",
"home_sections_title": "أقسام الرئيسية",
"enable_movie_recommendations": "توصيات الأفلام",
"enable_series_recommendations": "توصيات المسلسلات",
"enable_promoted_watchlists": "قوائم مشاهدة مختارة",
"hide_watchlists_tab": "إخفاء تبويب قوائم المشاهدة",
"home_sections_hint": "إظهار التوصيات المخصصة وقوائم المشاهدة المختارة من Streamystats في الصفحة الرئيسية.",
"recommended_movies": "أفلام موصى بها",
"recommended_series": "مسلسلات موصى بها",
"toasts": {
"saved": "Saved",
"refreshed": "Settings refreshed from server",
"disabled": "Streamystats disabled"
"saved": "تم الحفظ",
"refreshed": "تم تحديث الإعدادات من الخادم",
"disabled": "تم تعطيل Streamystats"
},
"refresh_from_server": "Refresh Settings from Server"
"refresh_from_server": "تحديث الإعدادات من الخادم"
},
"kefinTweaks": {
"watchlist_enabler": "Enable our Watchlist integration",
"watchlist_button": "Toggle Watchlist integration"
"watchlist_enabler": "تفعيل الربط مع قائمة المشاهدة الخاصة بنا",
"watchlist_button": "تبديل حالة ربط قائمة المشاهدة"
}
},
"storage": {
@@ -398,15 +398,15 @@
"device_usage": "الجهاز {{availableSpace}}%",
"size_used": "تم استخدام {{used}} من {{total}}",
"delete_all_downloaded_files": "حذف جميع الملفات التي تم تنزيلها",
"music_cache_title": "Music Cache",
"music_cache_description": "Automatically cache songs as you listen for smoother playback and offline support",
"enable_music_cache": "Enable Music Cache",
"clear_music_cache": "Clear Music Cache",
"music_cache_size": "{{size}} cached",
"music_cache_cleared": "Music cache cleared",
"delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted"
"music_cache_title": "التخزين المؤقت للموسيقى",
"music_cache_description": "تخزين الأغاني تلقائياً أثناء الاستماع لضمان تشغيل أكثر سلاسة ودعم الاستماع بدون اتصال",
"enable_music_cache": "تمكين التخزين المؤقت للموسيقى",
"clear_music_cache": "مسح التخزين المؤقت للموسيقى",
"music_cache_size": "تم تخزين {{size}} مؤقتاً",
"music_cache_cleared": "تم مسح التخزين المؤقت للموسيقى",
"delete_all_downloaded_songs": "حذف جميع الأغاني التي تم تنزيلها",
"downloaded_songs_size": "تم تنزيل {{size}}",
"downloaded_songs_deleted": "تم حذف الأغاني التي تم تنزيلها"
},
"intro": {
"title": "المقدمة",
@@ -499,15 +499,15 @@
"subtitle": "الترجمة",
"play": "تشغيل",
"none": "لا شيء",
"track": "Track",
"cancel": "Cancel",
"delete": "Delete",
"ok": "OK",
"remove": "Remove",
"next": "Next",
"back": "Back",
"continue": "Continue",
"verifying": "Verifying..."
"track": "أغنية",
"cancel": "إلغاء",
"delete": "حذف",
"ok": "حسناً",
"remove": "إزالة",
"next": "التالي",
"back": "رجوع",
"continue": "متابعة",
"verifying": "جارٍ التحقق..."
},
"search": {
"search": "بحث...",
@@ -521,10 +521,10 @@
"episodes": "حلقات",
"collections": "مجموعات",
"actors": "ممثلون",
"artists": "Artists",
"albums": "Albums",
"songs": "Songs",
"playlists": "Playlists",
"artists": "الفنانون",
"albums": "الألبومات",
"songs": "الأغاني",
"playlists": "قوائم التشغيل",
"request_movies": "طلب أفلام",
"request_series": "طلب مسلسلات",
"recently_added": "أضيف مؤخرًا",
@@ -572,7 +572,7 @@
"genres": "الأنواع",
"years": "السنوات",
"sort_by": "ترتيب حسب",
"filter_by": "Filter By",
"filter_by": "تصفية حسب",
"sort_order": "اتجاه الترتيب",
"tags": "الوسوم"
}
@@ -604,11 +604,17 @@
"index": "الفِهْرِس:",
"continue_watching": "متابعة المشاهدة",
"go_back": "رجوع",
"downloaded_file_title": "You have this file downloaded",
"downloaded_file_title": "تم تنزيل هذا الملف",
"downloaded_file_message": "هل تريد تشغيل الملف الذي تم تنزيله؟",
"downloaded_file_yes": "نعم",
"downloaded_file_no": "لا",
"downloaded_file_cancel": "Cancel"
"downloaded_file_cancel": "إلغاء"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "التالي",
@@ -624,7 +630,7 @@
"no_similar_items_found": "لم يتم العثور على عناصر مشابهة",
"video": "فيديو",
"more_details": "المزيد من التفاصيل",
"media_options": "Media Options",
"media_options": "خيارات الوسائط",
"quality": "الجودة",
"audio": "الصوت",
"subtitles": "الترجمة",
@@ -719,127 +725,127 @@
"favorites": "المفضلة"
},
"music": {
"title": "Music",
"title": "الموسيقى",
"tabs": {
"suggestions": "Suggestions",
"albums": "Albums",
"artists": "Artists",
"playlists": "Playlists",
"tracks": "tracks"
"suggestions": "الإقتراحات",
"albums": "الألبومات",
"artists": "الفنانون",
"playlists": "قوائم التشغيل",
"tracks": "الأغاني"
},
"filters": {
"all": "All"
"all": "الكل"
},
"recently_added": "Recently Added",
"recently_played": "Recently Played",
"frequently_played": "Frequently Played",
"explore": "Explore",
"top_tracks": "Top Tracks",
"play": "Play",
"shuffle": "Shuffle",
"play_top_tracks": "Play Top Tracks",
"no_suggestions": "No suggestions available",
"no_albums": "No albums found",
"no_artists": "No artists found",
"no_playlists": "No playlists found",
"album_not_found": "Album not found",
"artist_not_found": "Artist not found",
"playlist_not_found": "Playlist not found",
"recently_added": "أضيف مؤخرًا",
"recently_played": "تم تشغيله مؤخرًا",
"frequently_played": "الأكثر تشغيلاً",
"explore": "اكتشف",
"top_tracks": "أفضل الأغاني",
"play": "تشغيل",
"shuffle": "ترتيب عشوائي",
"play_top_tracks": "تشغيل أفضل الأغاني",
"no_suggestions": "لا توجد مقترحات متاحة",
"no_albums": "لا توجد ألبومات",
"no_artists": "لا يوجد فنانون",
"no_playlists": "لا توجد قوائم تشغيل",
"album_not_found": "الألبوم غير موجود",
"artist_not_found": "الفنان غير موجود",
"playlist_not_found": "قائمة التشغيل غير موجودة",
"track_options": {
"play_next": "Play Next",
"add_to_queue": "Add to Queue",
"add_to_playlist": "Add to Playlist",
"download": "Download",
"downloaded": "Downloaded",
"downloading": "Downloading...",
"cached": "Cached",
"delete_download": "Delete Download",
"delete_cache": "Remove from Cache",
"go_to_artist": "Go to Artist",
"go_to_album": "Go to Album",
"add_to_favorites": "Add to Favorites",
"remove_from_favorites": "Remove from Favorites",
"remove_from_playlist": "Remove from Playlist"
"play_next": "تشغيل التالي",
"add_to_queue": "إضافة إلى قائمة الانتظار",
"add_to_playlist": "أضف إلى قائمة التشغيل",
"download": "تنزيل",
"downloaded": "تم التنزيل",
"downloading": "جارٍ التنزيل...",
"cached": "تم التخزين مؤقتاً",
"delete_download": "حذف ملف التنزيل",
"delete_cache": "إزالة من التخزين المؤقت",
"go_to_artist": "انتقال إلى الفنان",
"go_to_album": "انتقال إلى الألبوم",
"add_to_favorites": "إضافة إلى المفضلة",
"remove_from_favorites": "إزالة من المفضلة",
"remove_from_playlist": "إزالة من قائمة التشغيل"
},
"playlists": {
"create_playlist": "Create Playlist",
"playlist_name": "Playlist Name",
"enter_name": "Enter playlist name",
"create": "Create",
"search_playlists": "Search playlists...",
"added_to": "Added to {{name}}",
"added": "Added to playlist",
"removed_from": "Removed from {{name}}",
"removed": "Removed from playlist",
"created": "Playlist created",
"create_new": "Create New Playlist",
"failed_to_add": "Failed to add to playlist",
"failed_to_remove": "Failed to remove from playlist",
"failed_to_create": "Failed to create playlist",
"delete_playlist": "Delete Playlist",
"delete_confirm": "Are you sure you want to delete \"{{name}}\"? This action cannot be undone.",
"deleted": "Playlist deleted",
"failed_to_delete": "Failed to delete playlist"
"create_playlist": "إنشاء قائمة التشغيل",
"playlist_name": "اسم قائمة التشغيل",
"enter_name": "أدخل اسم قائمة التشغيل",
"create": "إنشاء",
"search_playlists": "البحث عن قوائم التشغيل...",
"added_to": "تمت الإضافة إلى {{name}}",
"added": "تمت الإضافة إلى قائمة التشغيل",
"removed_from": "تمت الإزالة من {{name}}",
"removed": "تمت الازالة من قائمة التشغيل",
"created": "تم إنشاء قائمة التشغيل",
"create_new": "إنشاء قائمة تشغيل جديدة",
"failed_to_add": "فشلت الإضافة إلى قائمة التشغيل",
"failed_to_remove": "فشلت الإزالة من قائمة التشغيل",
"failed_to_create": "فشل إنشاء قائمة التشغيل",
"delete_playlist": "حذف قائمة التشغيل",
"delete_confirm": "هل أنت متأكد من رغبتك في حذف {{name}}؟ لا يمكن التراجع عن هذا الإجراء.",
"deleted": "تم حذف قائمة التشغيل",
"failed_to_delete": "فشل إنشاء قائمة التشغيل"
},
"sort": {
"title": "Sort By",
"alphabetical": "Alphabetical",
"date_created": "Date Created"
"title": "ترتيب حسب",
"alphabetical": "أبجدي",
"date_created": "تاريخ الإنشاء"
}
},
"watchlists": {
"title": "Watchlists",
"my_watchlists": "My Watchlists",
"public_watchlists": "Public Watchlists",
"create_title": "Create Watchlist",
"edit_title": "Edit Watchlist",
"create_button": "Create Watchlist",
"save_button": "Save Changes",
"delete_button": "Delete",
"remove_button": "Remove",
"cancel_button": "Cancel",
"name_label": "Name",
"name_placeholder": "Enter watchlist name",
"description_label": "Description",
"description_placeholder": "Enter description (optional)",
"is_public_label": "Public Watchlist",
"is_public_description": "Allow others to view this watchlist",
"allowed_type_label": "Content Type",
"sort_order_label": "Default Sort Order",
"empty_title": "No Watchlists",
"empty_description": "Create your first watchlist to start organizing your media",
"empty_watchlist": "This watchlist is empty",
"empty_watchlist_hint": "Add items from your library to this watchlist",
"not_configured_title": "Streamystats Not Configured",
"not_configured_description": "Configure Streamystats in settings to use watchlists",
"go_to_settings": "Go to Settings",
"add_to_watchlist": "Add to Watchlist",
"remove_from_watchlist": "Remove from Watchlist",
"select_watchlist": "Select Watchlist",
"create_new": "Create New Watchlist",
"item": "item",
"items": "items",
"public": "Public",
"private": "Private",
"you": "You",
"by_owner": "By another user",
"not_found": "Watchlist not found",
"delete_confirm_title": "Delete Watchlist",
"delete_confirm_message": "Are you sure you want to delete \"{{name}}\"? This action cannot be undone.",
"remove_item_title": "Remove from Watchlist",
"remove_item_message": "Remove \"{{name}}\" from this watchlist?",
"loading": "Loading watchlists...",
"no_compatible_watchlists": "No compatible watchlists",
"create_one_first": "Create a watchlist that accepts this content type"
"title": "قوائم المشاهدة",
"my_watchlists": "قوائم المشاهدة الخاصة بي",
"public_watchlists": "قوائم مشاهدة عامة",
"create_title": "إنشاء قائمة مشاهدة",
"edit_title": "تعديل قائمة المشاهدة",
"create_button": "إنشاء قائمة مشاهدة",
"save_button": "حفظ التغييرات",
"delete_button": "حذف",
"remove_button": "إزالة",
"cancel_button": "إلغاء",
"name_label": "الاسم",
"name_placeholder": "أدخل اسم قائمة المشاهدة",
"description_label": "الوصف",
"description_placeholder": "أدخل الوصف (اختياري)",
"is_public_label": "قائمة مشاهدة عامة",
"is_public_description": "السماح للآخرين بعرض قائمة المشاهدة هذه",
"allowed_type_label": "نوع المحتوى",
"sort_order_label": "الترتيب الافتراضي",
"empty_title": "لا توجد قوائم مشاهدة",
"empty_description": "قم بإنشاء أول قائمة مشاهدة لبدء تنظيم الوسائط الخاصة بك",
"empty_watchlist": "قائمة المشاهدة هذه فارغة",
"empty_watchlist_hint": "إضافة عناصر من مكتبتك إلى قائمة المشاهدة هذه",
"not_configured_title": "لم يتم ضبط Streamystats",
"not_configured_description": "اضبط Streamystats في الإعدادات لاستخدام قوائم المشاهدة",
"go_to_settings": "الذهاب إلى الإعدادات",
"add_to_watchlist": "إضافة إلى قائمة المشاهدة",
"remove_from_watchlist": "إزالة من قائمة المشاهدة",
"select_watchlist": "تحديد قائمة المشاهدة",
"create_new": "إنشاء قائمة مشاهدة جديدة",
"item": "عنصر",
"items": "عناصر",
"public": "عامة",
"private": "خاصة",
"you": "أنت",
"by_owner": "بواسطة مستخدم آخر",
"not_found": "قائمة المشاهدة غير موجودة",
"delete_confirm_title": "حذف قائمة المشاهدة",
"delete_confirm_message": "هل أنت متأكد من رغبتك في حذف \"{{name}}\"؟ لا يمكن التراجع عن هذا الإجراء.",
"remove_item_title": "إزالة من قائمة المشاهدة",
"remove_item_message": "إزالة \"{{name}}\" من قائمة المشاهدة هذه؟",
"loading": "تحميل قوائم المشاهدة...",
"no_compatible_watchlists": "لا توجد قوائم مشاهدة متوافقة",
"create_one_first": "إنشاء قائمة مشاهدة تقبل نوع المحتوى هذا"
},
"playback_speed": {
"title": "Playback Speed",
"apply_to": "Apply To",
"speed": "Speed",
"title": "سرعة التشغيل",
"apply_to": "تطبيق على",
"speed": "السرعة",
"scope": {
"media": "This media only",
"show": "This show",
"all": "All media (default)"
"media": "الوسائط هذه فقط",
"show": "هذا المسلسل",
"all": "جميع الوسائط (الافتراضي)"
}
}
}

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "A continuació",
"no_items_to_display": "No hi ha elements per mostrar",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Další nahoru",
"no_items_to_display": "Žádné položky k zobrazení",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Næste",
"no_items_to_display": "Ingen elementer at vise",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "Nein",
"downloaded_file_cancel": "Abbrechen"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Als Nächstes",
"no_items_to_display": "Keine Elemente",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Επόμενο Επάνω",
"no_items_to_display": "Δεν υπάρχουν στοιχεία προς εμφάνιση",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "No",
"downloaded_file_cancel": "Cancelar"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "A continuación",
"no_items_to_display": "No hay ítems para mostrar",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "Ei",
"downloaded_file_cancel": "Peruuta"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Seuraavaksi",
"no_items_to_display": "Ei kohteita näytettäväksi",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "Non",
"downloaded_file_cancel": "Annuler"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "À suivre",
"no_items_to_display": "Aucuns médias à afficher",
@@ -788,8 +794,8 @@
}
},
"watchlists": {
"title": "Watchlists",
"my_watchlists": "My Watchlists",
"title": "Listes de lecture",
"my_watchlists": "Mes listes de lecture",
"public_watchlists": "Watchlist publique",
"create_title": "Créer une Watchlist",
"edit_title": "Modifier la Watchlist",
@@ -802,7 +808,7 @@
"name_placeholder": "Entrer le nom de la playlist",
"description_label": "Description",
"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",
"allowed_type_label": "Type de contenu",
"sort_order_label": "Ordre de tri par défaut",

View File

@@ -39,7 +39,7 @@
"please_login_again": "Your saved session has expired. Please log in again.",
"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.",
"accounts_count": "{{count}} accounts",
"accounts_count": "{{count}} חשבונות",
"select_account": "Select Account",
"add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}."
@@ -110,16 +110,16 @@
"settings_title": "הגדרות",
"log_out_button": "התנתק",
"categories": {
"title": "Categories"
"title": "קטגוריות"
},
"playback_controls": {
"title": "Playback & Controls"
},
"audio_subtitles": {
"title": "Audio & Subtitles"
"title": "שמע וכתוביות"
},
"appearance": {
"title": "Appearance",
"title": "מראה",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button"
},
@@ -188,7 +188,7 @@
"hide_brightness_slider_description": "Hide the brightness slider in the video player"
},
"audio": {
"audio_title": "אודיו",
"audio_title": "שמע",
"set_audio_track": "בחר רצועת שמע מהפריט הקודם",
"audio_language": "שפת שמע",
"audio_hint": "בחר שפת שמע אוטומטית.",
@@ -271,8 +271,8 @@
"margin": "Bottom Margin"
},
"video_player": {
"title": "Video Player",
"video_player": "Video Player",
"title": "נגן וידאו",
"video_player": "נגן וידאו",
"video_player_description": "Choose which video player to use on iOS.",
"ksplayer": "KSPlayer",
"vlc": "VLC"
@@ -314,7 +314,7 @@
"downloads_title": "הורדות"
},
"music": {
"title": "Music",
"title": "מוזיקה",
"playback_title": "Playback",
"playback_description": "Configure how music is played.",
"prefer_downloaded": "Prefer Downloaded Songs",
@@ -409,7 +409,7 @@
"downloaded_songs_deleted": "Downloaded songs deleted"
},
"intro": {
"title": "Intro",
"title": "הקדמה",
"show_intro": "הצג פתיח",
"reset_intro": "אפס פתיח"
},
@@ -495,7 +495,7 @@
"select": "בחר",
"no_trailer_available": "אין טריילר זמין",
"video": "וידאו",
"audio": "אודיו",
"audio": "שמע",
"subtitle": "כתובית",
"play": "נגן",
"none": "ללא",
@@ -521,9 +521,9 @@
"episodes": "פרקים",
"collections": "אוספים",
"actors": "שחקנים",
"artists": "Artists",
"albums": "Albums",
"songs": "Songs",
"artists": "אומנים",
"albums": "אלבומים",
"songs": "שירים",
"playlists": "Playlists",
"request_movies": "סרטים מבוקשים",
"request_series": "סדרות מבוקשים",
@@ -606,10 +606,16 @@
"go_back": "חזור",
"downloaded_file_title": "You have this file downloaded",
"downloaded_file_message": "Do you want to play the downloaded file?",
"downloaded_file_yes": "Yes",
"downloaded_file_no": "No",
"downloaded_file_yes": "כן",
"downloaded_file_no": "לא",
"downloaded_file_cancel": "Cancel"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "הבא בתור",
"no_items_to_display": "אין פריטים להציג",
@@ -626,7 +632,7 @@
"more_details": "פרטים נוספים",
"media_options": "Media Options",
"quality": "איכות",
"audio": "אודיו",
"audio": "שמע",
"subtitles": "כתובית",
"show_more": "הצג עוד",
"show_less": "הצג פחות",
@@ -719,10 +725,10 @@
"favorites": "מועדפים"
},
"music": {
"title": "Music",
"title": "מוזיקה",
"tabs": {
"suggestions": "Suggestions",
"albums": "Albums",
"albums": "אלבומים",
"artists": "Artists",
"playlists": "Playlists",
"tracks": "tracks"
@@ -798,9 +804,9 @@
"delete_button": "Delete",
"remove_button": "Remove",
"cancel_button": "Cancel",
"name_label": "Name",
"name_label": "שם",
"name_placeholder": "Enter watchlist name",
"description_label": "Description",
"description_label": "תיאור",
"description_placeholder": "Enter description (optional)",
"is_public_label": "Public Watchlist",
"is_public_description": "Allow others to view this watchlist",
@@ -817,10 +823,10 @@
"remove_from_watchlist": "Remove from Watchlist",
"select_watchlist": "Select Watchlist",
"create_new": "Create New Watchlist",
"item": "item",
"items": "items",
"public": "Public",
"private": "Private",
"item": "פריט",
"items": "פריטים",
"public": "ציבורי",
"private": "פרטי",
"you": "You",
"by_owner": "By another user",
"not_found": "Watchlist not found",
@@ -835,7 +841,7 @@
"playback_speed": {
"title": "Playback Speed",
"apply_to": "Apply To",
"speed": "Speed",
"speed": "מהירות",
"scope": {
"media": "This media only",
"show": "This show",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Következő",
"no_items_to_display": "Nincs Megjeleníthető Elem",

View File

@@ -136,7 +136,7 @@
"not_connected_to_wifi": "Not connected to WiFi",
"no_networks_configured": "No networks configured",
"add_network_hint": "Add your home WiFi network to enable auto-switching",
"current_wifi": "Current WiFi",
"current_wifi": "WiFi Attuale",
"using_url": "Sta utilizzando",
"local": "Local URL",
"remote": "Remote URL",
@@ -610,6 +610,12 @@
"downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Il prossimo",
"no_items_to_display": "Nessun elemento da visualizzare",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "次",
"no_items_to_display": "表示するアイテムがありません",

View File

@@ -1,187 +1,187 @@
{
"login": {
"username_required": "Username Is Required",
"error_title": "Error",
"login_title": "Log In",
"login_to_title": "Log in to",
"username_placeholder": "Username",
"password_placeholder": "Password",
"login_button": "Log In",
"quick_connect": "Quick Connect",
"enter_code_to_login": "Enter code {{code}} to login",
"failed_to_initiate_quick_connect": "Failed to initiate Quick Connect",
"got_it": "Got It",
"connection_failed": "Connection Failed",
"could_not_connect_to_server": "Could not connect to the server. Please check the URL and your network connection.",
"an_unexpected_error_occured": "An Unexpected Error Occurred",
"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": "An unexpected error occurred. Did you enter the server URL correctly?",
"username_required": "사용자 이름이 필요합니다",
"error_title": "오류",
"login_title": "로그인",
"login_to_title": "다음 서비스에 연결 중",
"username_placeholder": "사용자 이름",
"password_placeholder": "비밀번호",
"login_button": "로그인",
"quick_connect": "퀵 커넥트",
"enter_code_to_login": "로그인 하기 위해 코드{{code}}를 입력하세요",
"failed_to_initiate_quick_connect": "Quick Connect 연결을 시작하는 데 실패했습니다",
"got_it": "성공",
"connection_failed": "연결 실패",
"could_not_connect_to_server": "서버에 연결되지 않았습니다. URL과 네트워크 상태를 확인하세요.",
"an_unexpected_error_occured": "예기치 않은 오류가 발생했습니다",
"change_server": "서버 변경",
"invalid_username_or_password": "잘못된 아이디 혹은 비밀번호입니다",
"user_does_not_have_permission_to_log_in": "로그인 하기 위한 권한이 없습니다",
"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_description": "Please update Jellyfin to the latest version"
},
"server": {
"enter_url_to_jellyfin_server": "Enter the URL to your Jellyfin server",
"server_url_placeholder": "http(s)://your-server.com",
"connect_button": "Connect",
"previous_servers": "Previous Servers",
"clear_button": "Clear all",
"swipe_to_remove": "Swipe to remove",
"search_for_local_servers": "Search for Local Servers",
"searching": "Searching...",
"servers": "Servers",
"saved": "Saved",
"session_expired": "Session Expired",
"please_login_again": "Your saved session has expired. Please log in again.",
"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.",
"accounts_count": "{{count}} accounts",
"select_account": "Select Account",
"add_account": "Add Account",
"remove_account_description": "This will remove the saved credentials for {{username}}."
"connect_button": "연결",
"previous_servers": "이전 서버",
"clear_button": "모두 지우기",
"swipe_to_remove": "스와이프해서 지우기",
"search_for_local_servers": "로컬 서버 찾기",
"searching": "찾는 중...",
"servers": "서버",
"saved": "저장됨",
"session_expired": "세션 만료됨",
"please_login_again": "사용자 세션이 만료되었습니다. 다시 로그인하십시오.",
"remove_saved_login": "저장된 로그인 정보 삭제",
"remove_saved_login_description": "해당 서버에 저장된 자격 증명이 삭제됩니다. 다음에 접속할 때는 사용자 이름과 비밀번호를 다시 입력해야 합니다.",
"accounts_count": "{{count}} 계정",
"select_account": "계정 선택",
"add_account": "계정 추가",
"remove_account_description": "{{username}}에 저장된 자격 증명이 삭제됩니다."
},
"save_account": {
"title": "Save Account",
"save_for_later": "Save this account",
"security_option": "Security Option",
"no_protection": "No protection",
"no_protection_desc": "Quick login without authentication",
"pin_code": "PIN code",
"pin_code_desc": "4-digit PIN required when switching",
"password": "Re-enter password",
"password_desc": "Password required when switching",
"save_button": "Save",
"cancel_button": "Cancel"
"title": "계정 저장",
"save_for_later": "이 계정 저장",
"security_option": "보안 설정",
"no_protection": "보안 없음",
"no_protection_desc": "인증 없이 빠른 로그인",
"pin_code": "PIN 코드",
"pin_code_desc": "전환하려면 4자리 PIN 필요함",
"password": "암호 확인",
"password_desc": "전환하려면 비밀번호 필요함",
"save_button": "저장",
"cancel_button": "취소"
},
"pin": {
"enter_pin": "Enter PIN",
"enter_pin_for": "Enter PIN for {{username}}",
"enter_4_digits": "Enter 4 digits",
"invalid_pin": "Invalid PIN",
"setup_pin": "Set Up PIN",
"confirm_pin": "Confirm PIN",
"pins_dont_match": "PINs don't match",
"forgot_pin": "Forgot PIN?",
"forgot_pin_desc": "Your saved credentials will be removed"
"enter_pin": "PIN 입력",
"enter_pin_for": "{{username}} PIN 입력",
"enter_4_digits": "4자리 입력",
"invalid_pin": "잘못된 PIN",
"setup_pin": "PIN 설정",
"confirm_pin": "PIN 확인",
"pins_dont_match": "PIN이 일치하지 않습니다",
"forgot_pin": "PIN을 잊으셨나요?",
"forgot_pin_desc": "저장된 계정 정보가 삭제됩니다"
},
"password": {
"enter_password": "Enter Password",
"enter_password_for": "Enter password for {{username}}",
"invalid_password": "Invalid password"
"enter_password": "비밀번호 입력",
"enter_password_for": "{{username}}의 비밀번호 입력",
"invalid_password": "잘못된 비밀번호"
},
"home": {
"checking_server_connection": "Checking server connection...",
"no_internet": "No Internet",
"no_items": "No Items",
"no_internet_message": "No worries, you can still watch\ndownloaded content.",
"checking_server_connection": "서버 연결 체크중...",
"no_internet": "인터넷에 연결되지 않음",
"no_items": "항목 없음",
"no_internet_message": "걱정마세요. 다운로드 된 컨텐츠는 여전히 볼 수 있습니다.",
"checking_server_connection_message": "Checking connection to server",
"go_to_downloads": "Go to Downloads",
"retry": "Retry",
"server_unreachable": "Server Unreachable",
"server_unreachable_message": "Could not reach the server.\nPlease check your network connection.",
"oops": "Oops!",
"error_message": "Something went wrong.\nPlease log out and in again.",
"continue_watching": "Continue Watching",
"next_up": "Next Up",
"continue_and_next_up": "Continue & Next Up",
"recently_added_in": "Recently Added in {{libraryName}}",
"suggested_movies": "Suggested Movies",
"suggested_episodes": "Suggested Episodes",
"retry": "재시도",
"server_unreachable": "서버에 연결할 수 없음",
"server_unreachable_message": "서버에 연결할 수 없습니다. 네트워크 상태를 체크하세요.",
"oops": "이런!",
"error_message": "문제가 발생했습니다.\n로그아웃 후 다시 로그인해 주세요.",
"continue_watching": "이어서 보기",
"next_up": "다음 시청",
"continue_and_next_up": "이어서 보기 & 다음 시청",
"recently_added_in": "최근에 추가된 {{libraryName}}",
"suggested_movies": "추천 영화",
"suggested_episodes": "추천 에피소드",
"intro": {
"welcome_to_streamyfin": "Welcome to Streamyfin",
"a_free_and_open_source_client_for_jellyfin": "A Free and Open-Source Client for Jellyfin.",
"features_title": "Features",
"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:",
"jellyseerr_feature_description": "Connect to your Seerr instance and request movies directly in the app.",
"downloads_feature_title": "Downloads",
"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.",
"chromecast_feature_description": "Cast movies and tv-shows to your Chromecast devices.",
"centralised_settings_plugin_title": "Centralised Settings Plugin",
"centralised_settings_plugin_description": "Configure settings from a centralised location on your Jellyfin server. All client settings for all users will be synced automatically.",
"done_button": "Done",
"go_to_settings_button": "Go to Settings",
"read_more": "Read More"
"welcome_to_streamyfin": "스트리미핀에 오신 것을 환영합니다",
"a_free_and_open_source_client_for_jellyfin": "젤리핀을 위한 무료 오픈소스 클라이언트입니다.",
"features_title": "기능",
"features_description": "스트리미핀은 다양한 기능을 제공하며 설정 메뉴에서 확인할 수 있는 여러 소프트웨어와 통합됩니다. 이러한 소프트웨어에는 다음이 포함됩니다:",
"jellyseerr_feature_description": "Seerr 인스턴스에 연결하여 앱에서 직접 영화를 요청할 수 있습니다.",
"downloads_feature_title": "다운로드된 컨텐츠",
"downloads_feature_description": "오프라인으로 보기위해 다운로드 하세요. 기본 다운로드 방식을 사용하거나, 백그라운드에서 파일을 다운로드하는 최적화 서버를 설치할 수 있습니다.",
"chromecast_feature_description": "영화와 TV 프로그램을 Chromecast 기기로 전송하기",
"centralised_settings_plugin_title": "중앙 설정 플러그인",
"centralised_settings_plugin_description": "Jellyfin 서버의 중앙 집중식 위치에서 설정을 구성합니다. 모든 사용자의 모든 클라이언트 설정이 자동으로 동기화됩니다.",
"done_button": "확인",
"go_to_settings_button": "설정으로 이동",
"read_more": "자세히 보기"
},
"settings": {
"settings_title": "Settings",
"log_out_button": "Log Out",
"settings_title": "설정",
"log_out_button": "로그아웃",
"categories": {
"title": "Categories"
"title": "카테고리"
},
"playback_controls": {
"title": "Playback & Controls"
"title": "재생 & 컨트롤"
},
"audio_subtitles": {
"title": "Audio & Subtitles"
"title": "오디오 & 자막"
},
"appearance": {
"title": "Appearance",
"merge_next_up_continue_watching": "Merge Continue Watching & Next Up",
"hide_remote_session_button": "Hide Remote Session Button"
"title": "화면 스타일",
"merge_next_up_continue_watching": "[이어보기]와 [다음 보기] 합치기",
"hide_remote_session_button": "원격 세션 버튼 숨기기"
},
"network": {
"title": "Network",
"local_network": "Local Network",
"auto_switch_enabled": "Auto-switch when at home",
"auto_switch_description": "Automatically switch to local URL when connected to home WiFi",
"local_url": "Local URL",
"local_url_hint": "Enter your local server address (e.g., http://192.168.1.100:8096)",
"title": "네트워크",
"local_network": "로컬 네트워크",
"auto_switch_enabled": "홈 네트워크 자동 전환",
"auto_switch_description": "홈 WiFi에 연결되었을 때 로컬 URL로 자동 전환",
"local_url": "로컬 URL",
"local_url_hint": "로컬 서버 주소를 입력하세요 (e.g., http://192.168.1.100:8096)",
"local_url_placeholder": "http://192.168.1.100:8096",
"home_wifi_networks": "Home WiFi Networks",
"add_current_network": "Add \"{{ssid}}\"",
"not_connected_to_wifi": "Not connected to WiFi",
"no_networks_configured": "No networks configured",
"add_network_hint": "Add your home WiFi network to enable auto-switching",
"current_wifi": "Current WiFi",
"using_url": "Using",
"local": "Local URL",
"remote": "Remote URL",
"not_connected": "Not connected",
"current_server": "Current Server",
"remote_url": "Remote URL",
"active_url": "Active URL",
"not_configured": "Not configured",
"network_added": "Network added",
"network_already_added": "Network already added",
"no_wifi_connected": "Not connected to WiFi",
"permission_denied": "Location permission denied",
"permission_denied_explanation": "Location permission is required to detect WiFi network for auto-switching. Please enable it in Settings."
"home_wifi_networks": " WiFi 네트워크",
"add_current_network": "\"{{ssid}}\" 추가",
"not_connected_to_wifi": "WiFi에 연결되지 않음",
"no_networks_configured": "구성된 네트워크가 없습니다",
"add_network_hint": "자동 전환을 위한 홈 WiFi 추가",
"current_wifi": "현재 WiFi",
"using_url": "사용중",
"local": "로컬 URL",
"remote": "원격 URL",
"not_connected": "연결되지 않았습니다",
"current_server": "현재 서버",
"remote_url": "원격 URL",
"active_url": "현재 사용 중인 URL",
"not_configured": "설정되지 않음",
"network_added": "네트워크 추가됨",
"network_already_added": "네트워크 이미 추가됨",
"no_wifi_connected": "WiFi에 연결되지 않음",
"permission_denied": "위치 권한이 거부되었습니다",
"permission_denied_explanation": "자동 전환 Wi-Fi 네트워크를 감지하려면 위치 권한이 필요합니다. 설정에서 위치 권한을 활성화해 주세요."
},
"user_info": {
"user_info_title": "User Info",
"user": "User",
"server": "Server",
"token": "Token",
"app_version": "App Version"
"user_info_title": "사용자 정보",
"user": "사용자",
"server": "서버",
"token": "토큰",
"app_version": "앱 버전"
},
"quick_connect": {
"quick_connect_title": "Quick Connect",
"authorize_button": "Authorize Quick Connect",
"enter_the_quick_connect_code": "Enter the quick connect code...",
"success": "Success",
"quick_connect_autorized": "Quick Connect Authorized",
"error": "Error",
"invalid_code": "Invalid Code",
"authorize": "Authorize"
"quick_connect_title": "퀵 커넥트",
"authorize_button": "퀵 커넥트 승인",
"enter_the_quick_connect_code": "퀵 커넥트 코드 입력...",
"success": "성공",
"quick_connect_autorized": "퀵 커넥트 승인됨",
"error": "오류",
"invalid_code": "유효하지 않은 코드",
"authorize": "승인"
},
"media_controls": {
"media_controls_title": "Media Controls",
"forward_skip_length": "Forward Skip Length",
"rewind_length": "Rewind Length",
"seconds_unit": "s"
"media_controls_title": "미디어 컨트롤",
"forward_skip_length": "앞으로 건너뛸 시간",
"rewind_length": "뒤로 되감을 시간",
"seconds_unit": ""
},
"gesture_controls": {
"gesture_controls_title": "Gesture Controls",
"horizontal_swipe_skip": "Horizontal Swipe to Skip",
"horizontal_swipe_skip_description": "Swipe left/right when controls are hidden to skip",
"left_side_brightness": "Left Side Brightness Control",
"left_side_brightness_description": "Swipe up/down on left side to adjust brightness",
"right_side_volume": "Right Side Volume Control",
"right_side_volume_description": "Swipe up/down on right side to adjust volume",
"gesture_controls_title": "제스처 제어",
"horizontal_swipe_skip": "좌/우로 스와이프하여 건너뛰기",
"horizontal_swipe_skip_description": "컨트롤 숨김상태에서 좌/우로 스와이프하여 건너뛰기",
"left_side_brightness": "왼쪽 영역 밝기 조정 컨트롤",
"left_side_brightness_description": "왼쪽 영역을 위/아래 스와이프하여 밝기 조절",
"right_side_volume": "오른쪽 영역 볼륨 컨트롤",
"right_side_volume_description": "오른족 영역을 위/아래로 스와이프 하여 볼륨 조절",
"hide_volume_slider": "Hide Volume Slider",
"hide_volume_slider_description": "Hide the volume slider in the video player",
"hide_brightness_slider": "Hide Brightness Slider",
@@ -196,7 +196,7 @@
"language": "Language",
"transcode_mode": {
"title": "Audio Transcoding",
"description": "Controls how surround audio (7.1, TrueHD, DTS-HD) is handled",
"description": "서라운드 오디오(7.1, TrueHD, DTS-HD)를 어떻게 처리할지 설정합니다",
"auto": "Auto",
"stereo": "Force Stereo",
"5_1": "Allow 5.1",
@@ -228,52 +228,52 @@
"outline_opacity": "Outline Opacity",
"bold_text": "Bold Text",
"colors": {
"Black": "Black",
"Gray": "Gray",
"Silver": "Silver",
"White": "White",
"Maroon": "Maroon",
"Red": "Red",
"Fuchsia": "Fuchsia",
"Yellow": "Yellow",
"Olive": "Olive",
"Green": "Green",
"Teal": "Teal",
"Lime": "Lime",
"Purple": "Purple",
"Navy": "Navy",
"Blue": "Blue",
"Aqua": "Aqua"
"Black": "검정색",
"Gray": "회색",
"Silver": "은색",
"White": "흰색",
"Maroon": "밤색",
"Red": "빨간색",
"Fuchsia": "분홍색",
"Yellow": "노란색",
"Olive": "올리브 색",
"Green": "녹색",
"Teal": "청록색",
"Lime": "라임색",
"Purple": "보라색",
"Navy": "남색",
"Blue": "파란색",
"Aqua": "아쿠아색"
},
"thickness": {
"None": "None",
"Thin": "Thin",
"Normal": "Normal",
"Thick": "Thick"
"None": "없음",
"Thin": "얇게",
"Normal": "보통",
"Thick": "굵게"
},
"subtitle_color": "Subtitle Color",
"subtitle_background_color": "Background Color",
"subtitle_font": "Subtitle Font",
"ksplayer_title": "KSPlayer Settings",
"hardware_decode": "Hardware Decoding",
"hardware_decode_description": "Use hardware acceleration for video decoding. Disable if you experience playback issues."
"subtitle_color": "자막 색상",
"subtitle_background_color": "배경 색상",
"subtitle_font": "자막 폰트",
"ksplayer_title": "KSPlayer 설정",
"hardware_decode": "하드웨어 디코딩",
"hardware_decode_description": "비디오 디코딩에 하드웨어 가속을 사용하십시오. 재생 문제가 발생하는 경우 비활성화하십시오."
},
"vlc_subtitles": {
"title": "VLC Subtitle Settings",
"hint": "Customize subtitle appearance for VLC player. Changes take effect on next playback.",
"text_color": "Text Color",
"background_color": "Background Color",
"background_opacity": "Background Opacity",
"outline_color": "Outline Color",
"outline_opacity": "Outline Opacity",
"outline_thickness": "Outline Thickness",
"bold": "Bold Text",
"margin": "Bottom Margin"
"title": "VLC 자막 설정",
"hint": "VLC 플레이어의 자막 표시 방식을 설정하세요. 변경 사항은 다음 재생 시 적용됩니다.",
"text_color": "글자색",
"background_color": "배경 색상",
"background_opacity": "배경 투명도",
"outline_color": "외곽선 색상",
"outline_opacity": "외곽선 투명도",
"outline_thickness": "외곽선 굵기",
"bold": "굵은 글씨",
"margin": "아래쪽 여백"
},
"video_player": {
"title": "Video Player",
"video_player": "Video Player",
"video_player_description": "Choose which video player to use on iOS.",
"title": "비디오 플레이어",
"video_player": "비디오 플레이어",
"video_player_description": "iOS 사용자는 비디오 플레이어를 선택하세요.",
"ksplayer": "KSPlayer",
"vlc": "VLC"
},
@@ -288,20 +288,20 @@
"PORTRAIT_UP": "Portrait Up",
"PORTRAIT_DOWN": "Portrait Down",
"LANDSCAPE": "Landscape",
"LANDSCAPE_LEFT": "Landscape Left",
"LANDSCAPE_RIGHT": "Landscape Right",
"LANDSCAPE_LEFT": "왼쪽 가로 모드",
"LANDSCAPE_RIGHT": "오른쪽 가로 모드",
"OTHER": "Other",
"UNKNOWN": "Unknown"
},
"safe_area_in_controls": "Safe Area in Controls",
"safe_area_in_controls": "컨트롤 안전 영역",
"video_player": "Video Player",
"video_players": {
"VLC_3": "VLC 3",
"VLC_4": "VLC 4 (Experimental + PiP)"
},
"show_custom_menu_links": "Show Custom Menu Links",
"show_large_home_carousel": "Show Large Home Carousel (beta)",
"hide_libraries": "Hide Libraries",
"show_custom_menu_links": "사용자 지정 메뉴 링크 표시",
"show_large_home_carousel": "대형 홈 슬라이드 배너 표시 (베타)",
"hide_libraries": "라이브러리 숨기기",
"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",
"default_quality": "Default Quality",
@@ -334,24 +334,24 @@
"password": "Password",
"password_placeholder": "Enter password for Jellyfin user {{username}}",
"login_button": "Login",
"total_media_requests": "Total Media Requests",
"movie_quota_limit": "Movie Quota Limit",
"movie_quota_days": "Movie Quota Days",
"total_media_requests": "전체 미디어 요청 수",
"movie_quota_limit": "영화 요청 한도",
"movie_quota_days": "영화 요청 제한 기간",
"tv_quota_limit": "TV Quota Limit",
"tv_quota_days": "TV Quota Days",
"reset_jellyseerr_config_button": "Reset Seerr Config",
"tv_quota_days": "TV 요청 제한 기간",
"reset_jellyseerr_config_button": "Seerr 설정 초기화",
"unlimited": "Unlimited",
"plus_n_more": "+{{n}} More",
"plus_n_more": "+{{n}}개 더",
"order_by": {
"DEFAULT": "Default",
"VOTE_COUNT_AND_AVERAGE": "Vote count and average",
"VOTE_COUNT_AND_AVERAGE": "평균 평점 및 투표 수",
"POPULARITY": "Popularity"
}
},
"marlin_search": {
"enable_marlin_search": "Enable Marlin Search",
"enable_marlin_search": "Marlin 검색 활성화",
"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.",
"read_more_about_marlin": "Read More About Marlin.",
"save_button": "Save",
@@ -374,28 +374,28 @@
"features_title": "Features",
"home_sections_title": "Home Sections",
"enable_movie_recommendations": "Movie Recommendations",
"enable_series_recommendations": "Series Recommendations",
"enable_promoted_watchlists": "Promoted Watchlists",
"hide_watchlists_tab": "Hide Watchlists Tab",
"home_sections_hint": "Show personalized recommendations and promoted watchlists from Streamystats on the home page.",
"enable_series_recommendations": "시리즈 추천",
"enable_promoted_watchlists": "추천 관심 목록",
"hide_watchlists_tab": "관심 목록 탭 숨기기",
"home_sections_hint": "홈 페이지에서 Streamystats의 개인 맞춤 추천 및 추천 관심 목록을 표시합니다.",
"recommended_movies": "Recommended Movies",
"recommended_series": "Recommended Series",
"recommended_series": "추천 시리즈",
"toasts": {
"saved": "Saved",
"refreshed": "Settings refreshed from server",
"disabled": "Streamystats disabled"
"refreshed": "서버에서 설정을 새로고침했습니다",
"disabled": "Streamystats 비활성화됨"
},
"refresh_from_server": "Refresh Settings from Server"
"refresh_from_server": "서버에서 설정 새로고침"
},
"kefinTweaks": {
"watchlist_enabler": "Enable our Watchlist integration",
"watchlist_button": "Toggle Watchlist integration"
"watchlist_enabler": "관심 목록 통합 기능 활성화",
"watchlist_button": "관심 목록 연동 켜기/끄기"
}
},
"storage": {
"storage_title": "Storage",
"app_usage": "App {{usedSpace}}%",
"device_usage": "Device {{availableSpace}}%",
"app_usage": " {{usedSpace}}",
"device_usage": "디바이스 {{availableSpace}}%",
"size_used": "{{used}} of {{total}} Used",
"delete_all_downloaded_files": "Delete All Downloaded Files",
"music_cache_title": "Music Cache",
@@ -403,10 +403,10 @@
"enable_music_cache": "Enable Music Cache",
"clear_music_cache": "Clear Music Cache",
"music_cache_size": "{{size}} cached",
"music_cache_cleared": "Music cache cleared",
"music_cache_cleared": "음악 캐시가 삭제되었습니다",
"delete_all_downloaded_songs": "Delete All Downloaded Songs",
"downloaded_songs_size": "{{size}} downloaded",
"downloaded_songs_deleted": "Downloaded songs deleted"
"downloaded_songs_deleted": "다운로드한 노래가 삭제되었습니다"
},
"intro": {
"title": "Intro",
@@ -434,7 +434,7 @@
},
"sessions": {
"title": "Sessions",
"no_active_sessions": "No Active Sessions"
"no_active_sessions": "세션 비활성화"
},
"downloads": {
"downloads_title": "Downloads",
@@ -610,6 +610,12 @@
"downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Next Up",
"no_items_to_display": "No Items to Display",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "Nee",
"downloaded_file_cancel": "Annuleren"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Volgende",
"no_items_to_display": "Geen items om te tonen",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Neste opp",
"no_items_to_display": "Ingen elementer å vise",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "Nie",
"downloaded_file_cancel": "Anuluj"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Następne",
"no_items_to_display": "Brak elementów do wyświetlenia",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "Não",
"downloaded_file_cancel": "Cancelar"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "A Seguir",
"no_items_to_display": "Nenhum item para exibir",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "Nu",
"downloaded_file_cancel": "Anulează"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Urmează",
"no_items_to_display": "Niciun element de afișat",

View File

@@ -12,25 +12,25 @@
"failed_to_initiate_quick_connect": "Не удалось инициировать быстрое подключение",
"got_it": "Принято",
"connection_failed": "Соединение не удалось",
"could_not_connect_to_server": "Не удалось подключиться к серверу. Пожалуйста проверьте URL и ваше интернет соединение.",
"could_not_connect_to_server": "Не удалось подключиться к серверу. Пожалуйста, проверьте URL и ваше интернет-соединение.",
"an_unexpected_error_occured": "Возникла непредвиденная ошибка",
"change_server": "Поменять сервер",
"invalid_username_or_password": "Неправильное имя пользователя или пароль",
"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": "Сервер получил слишком много запросов, попробуйте позже.",
"there_is_a_server_error": "Возникла ошибка сервера",
"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 до последней версии"
},
"server": {
"enter_url_to_jellyfin_server": "Укажите URL на ваш Jellyfin сервер",
"server_url_placeholder": "http(s)://your-server.com",
"connect_button": "Подключиться",
"previous_servers": "предыдущие серверы",
"previous_servers": "Предыдущие серверы",
"clear_button": "Очистить",
"swipe_to_remove": "Swipe to remove",
"swipe_to_remove": "Смахните для удаления",
"search_for_local_servers": "Поиск локальных серверов",
"searching": "Поиск...",
"servers": "Сервера",
@@ -39,7 +39,7 @@
"please_login_again": "Ваша сессия истекла. Пожалуйста, войдите снова.",
"remove_saved_login": "Удалить сохраненный аккаунт",
"remove_saved_login_description": "Ваши сохранённые данные для входа от этого сервера будут удалены. Вам придётся ввести ваши логин и пароль ещё раз.",
"accounts_count": "{{count}} аккаунтов",
"accounts_count": "Аккаунтов: {{count}}",
"select_account": "Выбрать аккаунт",
"add_account": "Добавить аккаунт",
"remove_account_description": "Данные для входа {{username}} будут удалены."
@@ -58,14 +58,14 @@
"cancel_button": "Отмена"
},
"pin": {
"enter_pin": "Введите PIN",
"enter_pin_for": "Введите PIN для {{username}}",
"enter_pin": "Введите PIN-код",
"enter_pin_for": "Введите PIN-код для {{username}}",
"enter_4_digits": "Введите 4 цифры",
"invalid_pin": "Некорректный PIN",
"setup_pin": "Установить PIN",
"confirm_pin": "Подтвердите PIN",
"invalid_pin": "Некорректный PIN-код",
"setup_pin": "Установить PIN-код",
"confirm_pin": "Подтвердите PIN-код",
"pins_dont_match": "PIN-коды не совпадают",
"forgot_pin": "Забыли PIN?",
"forgot_pin": "Забыли PIN-код?",
"forgot_pin_desc": "Ваши данные для входа будут удалены"
},
"password": {
@@ -84,7 +84,7 @@
"server_unreachable": "Сервер недоступен",
"server_unreachable_message": "Не удалось соединиться с сервером.\nПожалуйста, проверьте настройки сети.",
"oops": "Упс!",
"error_message": "Что-то пошло не так.\nПожалуйста выйдите и зайдите снова.",
"error_message": "Что-то пошло не так.\nПожалуйста, выйдите и зайдите снова.",
"continue_watching": "Продолжить",
"next_up": "Далее",
"continue_and_next_up": "Продолжить и Далее",
@@ -93,13 +93,13 @@
"suggested_episodes": "Предложенные серии",
"intro": {
"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_description": "Streamyfin имеет множество функций и интегрируется с широким спектром программ, которое вы можете найти в меню настроек:",
"jellyseerr_feature_description": "Подключитесь к Jellyseerr и запрашивайте фильмы прямо в приложении.",
"downloads_feature_title": "Загрузки",
"downloads_feature_description": "Скачивайте фильмы и сериалы для просмотра без интернета. Используйте стандартный способ или установите сервер оптимизации для загрузки файлов в фоновом режиме.",
"chromecast_feature_description": "Транслируйте фильмы и сериалы на ваши устройста с поддержкой Chromecast.",
"chromecast_feature_description": "Транслируйте фильмы и сериалы на ваши устройства с поддержкой Chromecast.",
"centralised_settings_plugin_title": "Плагин для централизованной настройки",
"centralised_settings_plugin_description": "Настраивайте параметры из централизованного места на сервере Jellyfin. Все настройки клиента для всех пользователей будут синхронизированы автоматически.",
"done_button": "Готово",
@@ -129,7 +129,7 @@
"auto_switch_enabled": "Переключаться дома автоматически",
"auto_switch_description": "Автоматически переключаться на локальный URL при присоединении к домашней WiFi сети",
"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",
"home_wifi_networks": "Домашние WiFi сети",
"add_current_network": "Добавить \"{{ssid}}\"",
@@ -160,28 +160,28 @@
},
"quick_connect": {
"quick_connect_title": "Быстрое подключение",
"authorize_button": "Авторизировать через быстрое подключение",
"authorize_button": "Авторизовать через быстрое подключение",
"enter_the_quick_connect_code": "Введите код для быстрого подключения...",
"success": "Успех",
"quick_connect_autorized": "Быстрое подключение авторизовано",
"error": "Ошибка",
"invalid_code": "Неверный код",
"authorize": "Авторизировать"
"authorize": "Авторизовать"
},
"media_controls": {
"media_controls_title": "Медиа-контроль",
"media_controls_title": "Управление воспроизведением",
"forward_skip_length": "Шаг перемотки вперёд",
"rewind_length": "Шаг перемотки назад",
"seconds_unit": "c"
},
"gesture_controls": {
"gesture_controls_title": "Управление жестами",
"horizontal_swipe_skip": "Горизонтальный свайп для перемотки",
"horizontal_swipe_skip_description": "Проведите влево/вправо, когда элементы управления скрыты, чтобы пропустить",
"left_side_brightness": "Управление яркостью левой стороны",
"left_side_brightness_description": "Смахните вверх/вниз на левой стороне для настройки яркости",
"horizontal_swipe_skip": "Проведите влево/вправо для перемотки",
"horizontal_swipe_skip_description": "Проведите влево/вправо, когда элементы управления скрыты, чтобы перемотать",
"left_side_brightness": "Управление яркостью слева",
"left_side_brightness_description": "Проведите вверх/вниз на левой стороне для настройки яркости",
"right_side_volume": "Управление громкостью справа",
"right_side_volume_description": "Свайп вверх/вниз с правой стороны для настройки громкости",
"right_side_volume_description": "Проведите вверх/вниз с правой стороны для настройки громкости",
"hide_volume_slider": "Скрыть индикатор громкости",
"hide_volume_slider_description": "Скрывает индикатор громкости в плеере",
"hide_brightness_slider": "Скрыть индикатор яркости",
@@ -205,7 +205,7 @@
},
"subtitles": {
"subtitle_title": "Субтитры",
"subtitle_hint": "Настройки отображения субтитров",
"subtitle_hint": "Настройки отображения субтитров.",
"subtitle_language": "Язык субтитров",
"subtitle_mode": "Режим субтитров",
"set_subtitle_track": "Устанавливать субтитры из предыдущего элемента",
@@ -271,9 +271,9 @@
"margin": "Отступ снизу"
},
"video_player": {
"title": "Видеоплеер",
"video_player": "Видеоплеер",
"video_player_description": "Выберите видеоплеер в iOS.",
"title": "Видео плеер",
"video_player": "Видео плеер",
"video_player_description": "Выберите видео плеер в iOS.",
"ksplayer": "KSPlayer",
"vlc": "VLC"
},
@@ -294,12 +294,12 @@
"UNKNOWN": "Неизвестное"
},
"safe_area_in_controls": "Безопасная зона в элементах управления",
"video_player": "Видеоплеер",
"video_player": "Видео плеер",
"video_players": {
"VLC_3": "VLC 3",
"VLC_4": "VLC 4 (Экспериментальный + PiP)"
},
"show_custom_menu_links": "Показать ссылки кастомного меню",
"show_custom_menu_links": "Показать ссылки пользовательского меню",
"show_large_home_carousel": "Показывать большую карусель (beta)",
"hide_libraries": "Скрыть библиотеки",
"select_liraries_you_want_to_hide": "Выберите Библиотеки, которое хотите спрятать из вкладки Библиотеки и домашней страницы.",
@@ -307,7 +307,7 @@
"default_quality": "Качество по умолчанию",
"default_playback_speed": "Скорость воспроизведения по умолчанию",
"auto_play_next_episode": "Автоматически воспроизводить следующий эпизод",
"max_auto_play_episode_count": "Максимальное количество автовоспроизведения эпизодов",
"max_auto_play_episode_count": "Максимальное количество авто воспроизводимых эпизодов",
"disabled": "Отключено"
},
"downloads": {
@@ -319,9 +319,9 @@
"playback_description": "Настройте воспроизведение музыки.",
"prefer_downloaded": "Предпочитать скачанные песни",
"caching_title": "Кеширование",
"caching_description": "Автоматически предкешировать следующие треки для стабильного воспроизведения.",
"caching_description": "Автоматически кешировать следующие треки для стабильного воспроизведения.",
"lookahead_enabled": "Включить предкеширование",
"lookahead_count": "Сколько предкешировать",
"lookahead_count": "Сколько треков предкешировать",
"max_cache_size": "Максимальное число предкешированных треков"
},
"plugins": {
@@ -329,8 +329,8 @@
"jellyseerr": {
"jellyseerr_warning": "Эта интеграция находится на ранней стадии. Ожидайте изменений.",
"server_url": "URL сервера",
"server_url_hint": "Пример: http(s)://your-host.url\n(Добавьте порт если необходимо)",
"server_url_placeholder": "Jellyseerr URL...",
"server_url_hint": "Пример: http(s)://your-host.url\n(добавьте порт если необходимо)",
"server_url_placeholder": "Seerr URL...",
"password": "Пароль",
"password_placeholder": "Введите пароль для пользователя Jellyfin {{username}}",
"login_button": "Войти",
@@ -349,7 +349,7 @@
}
},
"marlin_search": {
"enable_marlin_search": "Включить Marlin Search ",
"enable_marlin_search": "Включить Marlin Search",
"url": "URL-адрес",
"server_url_placeholder": "http(s)://domain.org:port",
"marlin_search_hint": "Введите URL для Marlin сервера. URL должен включать http or https и опционально порт.",
@@ -399,13 +399,13 @@
"size_used": "{{used}} из {{total}} использовано",
"delete_all_downloaded_files": "Удалить все загруженные файлы",
"music_cache_title": "Кеш музыки",
"music_cache_description": "Автоматически прекешировать песни по мере прослушивания для плавного воспроизведения и поддержки отсутствия интернета",
"music_cache_description": "Автоматически кешировать песни по мере прослушивания для плавного воспроизведения и поддержки отсутствия интернета",
"enable_music_cache": "Кешировать музыку",
"clear_music_cache": "Очистить кеш музыки",
"music_cache_size": "{{size}} кешировано",
"music_cache_size": "Кешировано: {{size}}",
"music_cache_cleared": "Кеш музыки очищен",
"delete_all_downloaded_songs": "Удалить все скачанные песни",
"downloaded_songs_size": "{{size}} скачано",
"downloaded_songs_size": "Скачано: {{size}}",
"downloaded_songs_deleted": "Скачанные песни удалены"
},
"intro": {
@@ -415,7 +415,7 @@
},
"logs": {
"logs_title": "Логи",
"export_logs": "Экспорт журналов",
"export_logs": "Сохранить логи",
"click_for_more_info": "Нажмите для получения дополнительной информации",
"level": "Уровень",
"no_logs_available": "Логи не доступны",
@@ -453,7 +453,7 @@
"no_active_downloads": "Нет активных загрузок",
"active_downloads": "Активные",
"new_app_version_requires_re_download": "Новая версия приложения требует повторной загрузки",
"new_app_version_requires_re_download_description": "Новая версия приложения требует повторной загрузки. Пожалуйста удалите всё и попробуйте заново.",
"new_app_version_requires_re_download_description": "Новая версия приложения требует повторной загрузки контента. Пожалуйста, удалите весь скачанный контент и попробуйте заново.",
"back": "Назад",
"delete": "Удалить",
"something_went_wrong": "Что-то пошло не так",
@@ -465,29 +465,29 @@
"failed_to_delete_all_movies": "Возникла ошибка при удалении всех фильмов",
"deleted_all_tvseries_successfully": "Все сериалы были успешно удалены!",
"failed_to_delete_all_tvseries": "Возникла ошибка при удалении всех сериалов",
"deleted_media_successfully": "Другие носители успешно удалены!",
"failed_to_delete_media": "Не удалось удалить другой файл",
"download_deleted": "Удалено",
"deleted_media_successfully": "Остальные медиафайлы успешно удалены!",
"failed_to_delete_media": "Не удалось удалить остальные медиафайлы",
"download_deleted": "Загруженный контент удалён",
"download_cancelled": "Загрузка отменена",
"could_not_delete_download": "Не удалось удалить загрузку",
"download_paused": "На паузе",
"could_not_pause_download": "Не удалось приостановить загрузку",
"download_resumed": "Продолжено",
"could_not_resume_download": "Не удалось продолжить загрузку",
"could_not_resume_download": "Не удалось возобновить загрузку",
"download_completed": "Завершено",
"download_failed": "Не удалось загрузить",
"download_failed_for_item": "Загрузка {{item}} провалилась с ошибкой: {{error}}",
"download_completed_for_item": "{{item}} успешно загружен",
"download_started_for_item": "Загрузка началась для {{item}}",
"download_started_for_item": "Загрузка {{item}} началась",
"failed_to_start_download": "Не удалось начать загрузку",
"item_already_downloading": "{{item}} уже загружается",
"all_files_deleted": "Все загрузки удалены",
"files_deleted_by_type": "{{count}} {{type}} удалён(о)",
"files_deleted_by_type": "Удалено: {{count}} {{type}}",
"all_files_folders_and_jobs_deleted_successfully": "Все файлы, папки, и задачи были успешно удалены",
"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": "В загрузки",
"file_deleted": "{{item}} удалён"
"file_deleted": "Удалено: {{item}}"
}
}
},
@@ -511,7 +511,7 @@
},
"search": {
"search": "Поиск...",
"x_items": "{{count}} элементов",
"x_items": "Элементов: {{count}}",
"library": "Библиотека",
"discover": "Найти новое",
"no_results": "Ничего не найдено",
@@ -529,14 +529,14 @@
"request_series": "Запросить сериалы",
"recently_added": "Недавно добавлено",
"recent_requests": "Недавно запрошено",
"plex_watchlist": "Список просмотра с Plex",
"plex_watchlist": "Список просмотра Plex",
"trending": "В тренде",
"popular_movies": "Популярные фильмы",
"movie_genres": "Популярные жанры",
"upcoming_movies": "Предстоящие фильмы",
"studios": "Студии",
"popular_tv": "Популярные сериалы",
"tv_genres": "жанры сериалов",
"tv_genres": "Жанры сериалов",
"upcoming_tv": "Предстоящие сериалы",
"networks": "Сети",
"tmdb_movie_keyword": "TMDB Ключевые слова фильмов",
@@ -556,7 +556,7 @@
"movies": "Фильмы",
"series": "Сериалы",
"boxsets": "Коллекции",
"items": "элементы"
"items": "Элементы"
},
"options": {
"display": "Отображать",
@@ -565,7 +565,7 @@
"image_style": "Стиль изображения",
"poster": "Постер",
"cover": "Обложка",
"show_titles": "Показывать загаловки",
"show_titles": "Показывать заголовки",
"show_stats": "Показывать статистику"
},
"filters": {
@@ -574,7 +574,7 @@
"sort_by": "Сортировка",
"filter_by": "Фильтр",
"sort_order": "Порядок",
"tags": "Тэги"
"tags": "Теги"
}
},
"favorites": {
@@ -610,6 +610,12 @@
"downloaded_file_no": "Нет",
"downloaded_file_cancel": "Отмена"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Далее",
"no_items_to_display": "Нет элементов для отображения",
@@ -624,7 +630,7 @@
"no_similar_items_found": "Похожие элементы не найдены",
"video": "Видео",
"more_details": "Больше деталей",
"media_options": "Media Options",
"media_options": "Опции медиа",
"quality": "Качество",
"audio": "Звук",
"subtitles": "Субтитры",
@@ -685,12 +691,12 @@
"currently_streaming_on": "Сейчас доступно на",
"advanced": "Продвинутое",
"request_as": "Запросить как",
"tags": "Тэги",
"tags": "Теги",
"quality_profile": "Профиль качества",
"root_folder": "Корневая папка",
"season_all": "Сезон (все)",
"season_number": "Сезон {{season_number}}",
"number_episodes": "{{episode_number}} серий",
"number_episodes": "Серий: {{episode_number}}",
"born": "Рожден",
"appearances": "Появления",
"approve": "Одобрить",
@@ -700,11 +706,11 @@
"toasts": {
"jellyseer_does_not_meet_requirements": "Сервер Jellyseerr не соответствует минимальным требованиям версии! Пожалуйста, обновите до версии не ниже 2.0.0",
"jellyseerr_test_failed": "Тест Jellyseerr не пройден. Попробуйте еще раз.",
"failed_to_test_jellyseerr_server_url": "Не удалось проверить URL-адрес сервера jellyseerr",
"failed_to_test_jellyseerr_server_url": "Не удалось проверить URL-адрес сервера Seerr",
"issue_submitted": "Проблема отправлена!",
"requested_item": "Запрошено {{item}}!",
"you_dont_have_permission_to_request": "У вас нет разрешения на запрос!",
"something_went_wrong_requesting_media": "Что-то пошло не так при запросе медиафайлов!",
"something_went_wrong_requesting_media": "Что-то пошло не так при запросе медиа!",
"request_approved": "Запрос одобрен!",
"request_declined": "Запрос отклонён!",
"failed_to_approve_request": "Не удалось одобрить запрос",
@@ -801,7 +807,7 @@
"name_label": "Название",
"name_placeholder": "Введите название списка",
"description_label": "Описание",
"description_placeholder": "Введите описание (не обязательно)",
"description_placeholder": "Введите описание (необязательно)",
"is_public_label": "Публичный",
"is_public_description": "Разрешить остальным пользователям видеть этот список",
"allowed_type_label": "Тип контента",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "Nej",
"downloaded_file_cancel": "Avbryt"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Näst på tur",
"no_items_to_display": "Inga Artiklar Att Visa",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Next Up",
"no_items_to_display": "No Items to Display",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "wej",
"no_items_to_display": "Doch pagh HochlaH",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "Hayır",
"downloaded_file_cancel": "Vazgeç"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Sıradaki",
"no_items_to_display": "Görüntülenecek öğe yok",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Далі",
"no_items_to_display": "Немає елементів для відображення",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Tiếp theo",
"no_items_to_display": "Không có nội dung để hiển thị",

View File

@@ -610,6 +610,12 @@
"downloaded_file_no": "No",
"downloaded_file_cancel": "Cancel"
},
"chapters": {
"title": "Chapters",
"chapter_number": "Chapter {{number}}",
"open": "Open chapters",
"close": "Close chapters"
},
"item_card": {
"next_up": "Next Up",
"no_items_to_display": "No Items to Display",

View File

@@ -341,14 +341,6 @@ export const pluginSettingsAtom = atom<PluginLockableSettings | undefined>(
loadPluginSettings(),
);
const hasMeaningfulSettingValue = (value: unknown) =>
value !== undefined && value !== null && value !== "";
const getEffectiveSettingValue = <K extends keyof Settings>(
settings: Partial<Settings> | null | undefined,
settingsKey: K,
) => settings?.[settingsKey] ?? defaultValues[settingsKey];
export const useSettings = () => {
const api = useAtomValue(apiAtom);
const [_settings, setSettings] = useAtom(settingsAtom);
@@ -389,13 +381,12 @@ export const useSettings = () => {
for (const [key, setting] of Object.entries(newPluginSettings)) {
if (setting && !setting.locked && setting.value !== undefined) {
const settingsKey = key as keyof Settings;
const effectiveValue = getEffectiveSettingValue(
_settings,
settingsKey,
);
// Apply if forceOverride is true, or if neither persisted settings
// nor app defaults provide a meaningful value.
if (forceOverride || !hasMeaningfulSettingValue(effectiveValue)) {
// Apply if forceOverride is true, or if user hasn't explicitly set this value
if (
forceOverride ||
_settings[settingsKey] === undefined ||
_settings[settingsKey] === ""
) {
(updates as any)[settingsKey] = setting.value;
}
}
@@ -447,22 +438,28 @@ export const useSettings = () => {
// We do not want to save over users pre-existing settings in case admin ever removes/unlocks a setting.
// If admin sets locked to false but provides a value,
// use persisted settings first, then app defaults, and only fallback on the
// plugin value when neither provides a meaningful value.
// use user settings first and fallback on admin setting if required.
const settings: Settings = useMemo(() => {
const unlockedPluginDefaults: Partial<Settings> = {};
const overrideSettings = Object.entries(pluginSettings ?? {}).reduce<
Partial<Settings>
>((acc, [key, setting]) => {
if (setting) {
const { value, locked } = setting;
const settingsKey = key as keyof Settings;
const effectiveValue = getEffectiveSettingValue(_settings, settingsKey);
// Make sure we override default settings with plugin settings when they are not locked.
if (
!locked &&
value !== undefined &&
_settings?.[settingsKey] !== value
) {
(unlockedPluginDefaults as any)[settingsKey] = value;
}
(acc as any)[settingsKey] = locked
? value
: hasMeaningfulSettingValue(effectiveValue)
? effectiveValue
: value;
: (_settings?.[settingsKey] ?? value);
}
return acc;
}, {});