mirror of
https://github.com/movie-web/movie-web.git
synced 2024-12-27 12:01:50 +01:00
Merge branch 'dev' into mediasession
This commit is contained in:
commit
a2a3066bc7
1
.github/workflows/linting_testing.yml
vendored
1
.github/workflows/linting_testing.yml
vendored
@ -71,5 +71,4 @@ jobs:
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
push: false
|
||||
platforms: linux/amd64,linux/arm64
|
||||
context: .
|
||||
|
10
package.json
10
package.json
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "movie-web",
|
||||
"version": "4.2.5",
|
||||
"version": "4.3.3",
|
||||
"private": true,
|
||||
"homepage": "https://movie-web.app",
|
||||
"scripts": {
|
||||
@ -29,14 +29,16 @@
|
||||
"@formkit/auto-animate": "^0.8.1",
|
||||
"@headlessui/react": "^1.7.17",
|
||||
"@ladjs/country-language": "^1.0.3",
|
||||
"@movie-web/providers": "^2.0.5",
|
||||
"@movie-web/providers": "^2.1.1",
|
||||
"@noble/hashes": "^1.3.3",
|
||||
"@plasmohq/messaging": "^0.6.1",
|
||||
"@react-spring/web": "^9.7.3",
|
||||
"@scure/bip39": "^1.2.2",
|
||||
"@sozialhelden/ietf-language-tags": "^5.4.2",
|
||||
"@types/node-forge": "^1.3.10",
|
||||
"classnames": "^2.3.2",
|
||||
"core-js": "^3.34.0",
|
||||
"detect-browser": "^5.3.0",
|
||||
"dompurify": "^3.0.6",
|
||||
"flag-icons": "^7.1.0",
|
||||
"focus-trap-react": "^10.2.3",
|
||||
@ -62,6 +64,7 @@
|
||||
"react-sticky-el": "^2.1.0",
|
||||
"react-turnstile": "^1.1.2",
|
||||
"react-use": "^17.4.2",
|
||||
"semver": "^7.5.4",
|
||||
"slugify": "^1.6.6",
|
||||
"subsrt-ts": "^2.1.2",
|
||||
"zustand": "^4.4.7"
|
||||
@ -86,6 +89,7 @@
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
"@types/react-stickynode": "^4.0.3",
|
||||
"@types/react-transition-group": "^4.4.10",
|
||||
"@types/semver": "^7.5.6",
|
||||
"@typescript-eslint/eslint-plugin": "^6.15.0",
|
||||
"@typescript-eslint/parser": "^6.15.0",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
@ -114,7 +118,7 @@
|
||||
"tailwindcss-themer": "^4.0.0",
|
||||
"type-fest": "^4.8.3",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.0.10",
|
||||
"vite": "^5.0.12",
|
||||
"vite-plugin-checker": "^0.6.2",
|
||||
"vite-plugin-package-version": "^1.1.0",
|
||||
"vite-plugin-pwa": "^0.17.4",
|
||||
|
149
pnpm-lock.yaml
generated
149
pnpm-lock.yaml
generated
@ -22,11 +22,14 @@ dependencies:
|
||||
specifier: ^1.0.3
|
||||
version: 1.0.3
|
||||
'@movie-web/providers':
|
||||
specifier: ^2.0.5
|
||||
version: 2.0.5
|
||||
specifier: ^2.1.1
|
||||
version: 2.1.1
|
||||
'@noble/hashes':
|
||||
specifier: ^1.3.3
|
||||
version: 1.3.3
|
||||
'@plasmohq/messaging':
|
||||
specifier: ^0.6.1
|
||||
version: 0.6.1(react@18.2.0)
|
||||
'@react-spring/web':
|
||||
specifier: ^9.7.3
|
||||
version: 9.7.3(react-dom@18.2.0)(react@18.2.0)
|
||||
@ -45,6 +48,9 @@ dependencies:
|
||||
core-js:
|
||||
specifier: ^3.34.0
|
||||
version: 3.34.0
|
||||
detect-browser:
|
||||
specifier: ^5.3.0
|
||||
version: 5.3.0
|
||||
dompurify:
|
||||
specifier: ^3.0.6
|
||||
version: 3.0.6
|
||||
@ -120,6 +126,9 @@ dependencies:
|
||||
react-use:
|
||||
specifier: ^17.4.2
|
||||
version: 17.4.2(react-dom@18.2.0)(react@18.2.0)
|
||||
semver:
|
||||
specifier: ^7.5.4
|
||||
version: 7.5.4
|
||||
slugify:
|
||||
specifier: ^1.6.6
|
||||
version: 1.6.6
|
||||
@ -188,6 +197,9 @@ devDependencies:
|
||||
'@types/react-transition-group':
|
||||
specifier: ^4.4.10
|
||||
version: 4.4.10
|
||||
'@types/semver':
|
||||
specifier: ^7.5.6
|
||||
version: 7.5.6
|
||||
'@typescript-eslint/eslint-plugin':
|
||||
specifier: ^6.15.0
|
||||
version: 6.15.0(@typescript-eslint/parser@6.15.0)(eslint@8.56.0)(typescript@5.3.3)
|
||||
@ -196,7 +208,7 @@ devDependencies:
|
||||
version: 6.15.0(eslint@8.56.0)(typescript@5.3.3)
|
||||
'@vitejs/plugin-react':
|
||||
specifier: ^4.2.1
|
||||
version: 4.2.1(vite@5.0.10)
|
||||
version: 4.2.1(vite@5.0.12)
|
||||
autoprefixer:
|
||||
specifier: ^10.4.16
|
||||
version: 10.4.16(postcss@8.4.32)
|
||||
@ -256,7 +268,7 @@ devDependencies:
|
||||
version: 0.5.9(prettier@3.1.1)
|
||||
rollup-plugin-visualizer:
|
||||
specifier: ^5.11.0
|
||||
version: 5.11.0(@rollup/wasm-node@4.9.4)
|
||||
version: 5.11.0(@rollup/wasm-node@4.9.6)
|
||||
tailwind-scrollbar:
|
||||
specifier: ^3.0.5
|
||||
version: 3.0.5(tailwindcss@3.4.0)
|
||||
@ -273,20 +285,20 @@ devDependencies:
|
||||
specifier: ^5.3.3
|
||||
version: 5.3.3
|
||||
vite:
|
||||
specifier: ^5.0.10
|
||||
version: 5.0.10(@types/node@20.10.5)
|
||||
specifier: ^5.0.12
|
||||
version: 5.0.12(@types/node@20.10.5)
|
||||
vite-plugin-checker:
|
||||
specifier: ^0.6.2
|
||||
version: 0.6.2(eslint@8.56.0)(typescript@5.3.3)(vite@5.0.10)
|
||||
version: 0.6.2(eslint@8.56.0)(typescript@5.3.3)(vite@5.0.12)
|
||||
vite-plugin-package-version:
|
||||
specifier: ^1.1.0
|
||||
version: 1.1.0(vite@5.0.10)
|
||||
version: 1.1.0(vite@5.0.12)
|
||||
vite-plugin-pwa:
|
||||
specifier: ^0.17.4
|
||||
version: 0.17.4(vite@5.0.10)(workbox-build@7.0.0)(workbox-window@7.0.0)
|
||||
version: 0.17.4(vite@5.0.12)(workbox-build@7.0.0)(workbox-window@7.0.0)
|
||||
vite-plugin-static-copy:
|
||||
specifier: ^1.0.0
|
||||
version: 1.0.0(vite@5.0.10)
|
||||
version: 1.0.0(vite@5.0.12)
|
||||
vitest:
|
||||
specifier: ^1.1.0
|
||||
version: 1.1.0(@types/node@20.10.5)(jsdom@23.0.1)
|
||||
@ -1921,8 +1933,8 @@ packages:
|
||||
engines: {node: '>= 14'}
|
||||
dev: false
|
||||
|
||||
/@movie-web/providers@2.0.5:
|
||||
resolution: {integrity: sha512-cefPTFXE7ctYeiibjk4HcNL3anRZ3lgYDAaJdzFzUrvkcSdxonP8GgGfDfPwmWWKip9dbP8Xv5aeauV/wrfaag==}
|
||||
/@movie-web/providers@2.1.1:
|
||||
resolution: {integrity: sha512-g2CA/w3YlGw3b3v6yDSgUIUdym4rFs4CzZOo/OlyL4HtsFH9mk182ukt7HYSxgddCEJRjl81LZZc3/pLRIGcMA==}
|
||||
dependencies:
|
||||
cheerio: 1.0.0-rc.12
|
||||
crypto-js: 4.2.0
|
||||
@ -1980,6 +1992,18 @@ packages:
|
||||
tslib: 2.6.2
|
||||
dev: true
|
||||
|
||||
/@plasmohq/messaging@0.6.1(react@18.2.0):
|
||||
resolution: {integrity: sha512-/nn1k8SG5z++o/NnZu+byHWcC9MhPLxfmvj+AP3buqMn7uwfYDcYWURLuMW2Knw08HBg+wku2v1Ltt4evN0nzA==}
|
||||
peerDependencies:
|
||||
react: ^16.8.6 || ^17 || ^18
|
||||
peerDependenciesMeta:
|
||||
react:
|
||||
optional: true
|
||||
dependencies:
|
||||
nanoid: 5.0.3
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@react-spring/animated@9.7.3(react@18.2.0):
|
||||
resolution: {integrity: sha512-5CWeNJt9pNgyvuSzQH+uy2pvTg8Y4/OisoscZIR8/ZNLIOI+CatFBhGZpDGTF/OzdNFsAoGk3wiUYTwoJ0YIvw==}
|
||||
peerDependencies:
|
||||
@ -2033,7 +2057,7 @@ packages:
|
||||
engines: {node: '>=14.0.0'}
|
||||
dev: false
|
||||
|
||||
/@rollup/plugin-babel@5.3.1(@babel/core@7.23.6)(@rollup/wasm-node@4.9.4):
|
||||
/@rollup/plugin-babel@5.3.1(@babel/core@7.23.6)(@rollup/wasm-node@4.9.6):
|
||||
resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
peerDependencies:
|
||||
@ -2046,36 +2070,36 @@ packages:
|
||||
dependencies:
|
||||
'@babel/core': 7.23.6
|
||||
'@babel/helper-module-imports': 7.22.15
|
||||
'@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.9.4)
|
||||
rollup: /@rollup/wasm-node@4.9.4
|
||||
'@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.9.6)
|
||||
rollup: /@rollup/wasm-node@4.9.6
|
||||
dev: true
|
||||
|
||||
/@rollup/plugin-node-resolve@11.2.1(@rollup/wasm-node@4.9.4):
|
||||
/@rollup/plugin-node-resolve@11.2.1(@rollup/wasm-node@4.9.6):
|
||||
resolution: {integrity: sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
peerDependencies:
|
||||
rollup: npm:@rollup/wasm-node
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.9.4)
|
||||
'@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.9.6)
|
||||
'@types/resolve': 1.17.1
|
||||
builtin-modules: 3.3.0
|
||||
deepmerge: 4.3.1
|
||||
is-module: 1.0.0
|
||||
resolve: 1.22.4
|
||||
rollup: /@rollup/wasm-node@4.9.4
|
||||
rollup: /@rollup/wasm-node@4.9.6
|
||||
dev: true
|
||||
|
||||
/@rollup/plugin-replace@2.4.2(@rollup/wasm-node@4.9.4):
|
||||
/@rollup/plugin-replace@2.4.2(@rollup/wasm-node@4.9.6):
|
||||
resolution: {integrity: sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==}
|
||||
peerDependencies:
|
||||
rollup: npm:@rollup/wasm-node
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.9.4)
|
||||
'@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.9.6)
|
||||
magic-string: 0.25.9
|
||||
rollup: /@rollup/wasm-node@4.9.4
|
||||
rollup: /@rollup/wasm-node@4.9.6
|
||||
dev: true
|
||||
|
||||
/@rollup/pluginutils@3.1.0(@rollup/wasm-node@4.9.4):
|
||||
/@rollup/pluginutils@3.1.0(@rollup/wasm-node@4.9.6):
|
||||
resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==}
|
||||
engines: {node: '>= 8.0.0'}
|
||||
peerDependencies:
|
||||
@ -2084,7 +2108,7 @@ packages:
|
||||
'@types/estree': 0.0.39
|
||||
estree-walker: 1.0.1
|
||||
picomatch: 2.3.1
|
||||
rollup: /@rollup/wasm-node@4.9.4
|
||||
rollup: /@rollup/wasm-node@4.9.6
|
||||
dev: true
|
||||
|
||||
/@rollup/wasm-node@4.9.4:
|
||||
@ -2095,6 +2119,16 @@ packages:
|
||||
'@types/estree': 1.0.5
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
dev: true
|
||||
|
||||
/@rollup/wasm-node@4.9.6:
|
||||
resolution: {integrity: sha512-B3FpAkroTE6q+MRHzv8XLBgPbxdjJiy5UnduZNQ/4lxeF1JT2O/OAr0JPpXeRG/7zpKm/kdqU/4m6AULhmnSqw==}
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
'@types/estree': 1.0.5
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
/@scure/base@1.1.5:
|
||||
resolution: {integrity: sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ==}
|
||||
@ -2309,8 +2343,8 @@ packages:
|
||||
/@types/scheduler@0.16.3:
|
||||
resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==}
|
||||
|
||||
/@types/semver@7.5.1:
|
||||
resolution: {integrity: sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==}
|
||||
/@types/semver@7.5.6:
|
||||
resolution: {integrity: sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==}
|
||||
dev: true
|
||||
|
||||
/@types/trusted-types@2.0.3:
|
||||
@ -2429,7 +2463,7 @@ packages:
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0)
|
||||
'@types/json-schema': 7.0.12
|
||||
'@types/semver': 7.5.1
|
||||
'@types/semver': 7.5.6
|
||||
'@typescript-eslint/scope-manager': 6.15.0
|
||||
'@typescript-eslint/types': 6.15.0
|
||||
'@typescript-eslint/typescript-estree': 6.15.0(typescript@5.3.3)
|
||||
@ -2452,7 +2486,7 @@ packages:
|
||||
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
|
||||
dev: true
|
||||
|
||||
/@vitejs/plugin-react@4.2.1(vite@5.0.10):
|
||||
/@vitejs/plugin-react@4.2.1(vite@5.0.12):
|
||||
resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==}
|
||||
engines: {node: ^14.18.0 || >=16.0.0}
|
||||
peerDependencies:
|
||||
@ -2463,7 +2497,7 @@ packages:
|
||||
'@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.23.6)
|
||||
'@types/babel__core': 7.20.5
|
||||
react-refresh: 0.14.0
|
||||
vite: 5.0.10(@types/node@20.10.5)
|
||||
vite: 5.0.12(@types/node@20.10.5)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
@ -3307,6 +3341,10 @@ packages:
|
||||
resolution: {integrity: sha512-M1Ob1zPSIvlARiJUkKqvAZ3VAqQY6Jcuth/pBKQ2b1dX/Qx0OnJ8Vux6J2H5PTMQeRzWrrbTu70VxBfv/OPDJA==}
|
||||
dev: false
|
||||
|
||||
/detect-browser@5.3.0:
|
||||
resolution: {integrity: sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==}
|
||||
dev: false
|
||||
|
||||
/didyoumean@1.2.2:
|
||||
resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==}
|
||||
dev: true
|
||||
@ -5008,7 +5046,6 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
yallist: 4.0.0
|
||||
dev: true
|
||||
|
||||
/magic-string@0.25.9:
|
||||
resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==}
|
||||
@ -5054,7 +5091,7 @@ packages:
|
||||
'@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.23.6)
|
||||
'@babel/types': 7.23.6
|
||||
kleur: 4.1.5
|
||||
rollup: /@rollup/wasm-node@4.9.4
|
||||
rollup: /@rollup/wasm-node@4.9.6
|
||||
unplugin: 1.5.1
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@ -5156,6 +5193,12 @@ packages:
|
||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||
hasBin: true
|
||||
|
||||
/nanoid@5.0.3:
|
||||
resolution: {integrity: sha512-I7X2b22cxA4LIHXPSqbBCEQSL+1wv8TuoefejsX4HFWyC6jc5JG7CEaxOltiKjc1M+YCS2YkrZZcj4+dytw9GA==}
|
||||
engines: {node: ^18 || >=20}
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/nanoid@5.0.4:
|
||||
resolution: {integrity: sha512-vAjmBf13gsmhXSgBrtIclinISzFFy22WwCYoyilZlsrRXNIHSwgFQ1bEdjRwMT3aoadeIF6HMuDRlOxzfXV8ig==}
|
||||
engines: {node: ^18 || >=20}
|
||||
@ -5976,7 +6019,7 @@ packages:
|
||||
glob: 7.2.3
|
||||
dev: true
|
||||
|
||||
/rollup-plugin-terser@7.0.2(@rollup/wasm-node@4.9.4):
|
||||
/rollup-plugin-terser@7.0.2(@rollup/wasm-node@4.9.6):
|
||||
resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==}
|
||||
deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser
|
||||
peerDependencies:
|
||||
@ -5984,12 +6027,12 @@ packages:
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.23.5
|
||||
jest-worker: 26.6.2
|
||||
rollup: /@rollup/wasm-node@4.9.4
|
||||
rollup: /@rollup/wasm-node@4.9.6
|
||||
serialize-javascript: 4.0.0
|
||||
terser: 5.19.3
|
||||
dev: true
|
||||
|
||||
/rollup-plugin-visualizer@5.11.0(@rollup/wasm-node@4.9.4):
|
||||
/rollup-plugin-visualizer@5.11.0(@rollup/wasm-node@4.9.6):
|
||||
resolution: {integrity: sha512-exM0Ms2SN3AgTzMeW7y46neZQcyLY7eKwWAop1ZoRTCZwyrIRdMMJ6JjToAJbML77X/9N8ZEpmXG4Z/Clb9k8g==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
@ -6001,7 +6044,7 @@ packages:
|
||||
dependencies:
|
||||
open: 8.4.2
|
||||
picomatch: 2.3.1
|
||||
rollup: /@rollup/wasm-node@4.9.4
|
||||
rollup: /@rollup/wasm-node@4.9.6
|
||||
source-map: 0.7.4
|
||||
yargs: 17.7.2
|
||||
dev: true
|
||||
@ -6115,7 +6158,6 @@ packages:
|
||||
hasBin: true
|
||||
dependencies:
|
||||
lru-cache: 6.0.0
|
||||
dev: true
|
||||
|
||||
/serialize-javascript@4.0.0:
|
||||
resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==}
|
||||
@ -6849,7 +6891,7 @@ packages:
|
||||
debug: 4.3.4
|
||||
pathe: 1.1.1
|
||||
picocolors: 1.0.0
|
||||
vite: 5.0.10(@types/node@20.10.5)
|
||||
vite: 5.0.12(@types/node@20.10.5)
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- less
|
||||
@ -6861,7 +6903,7 @@ packages:
|
||||
- terser
|
||||
dev: true
|
||||
|
||||
/vite-plugin-checker@0.6.2(eslint@8.56.0)(typescript@5.3.3)(vite@5.0.10):
|
||||
/vite-plugin-checker@0.6.2(eslint@8.56.0)(typescript@5.3.3)(vite@5.0.12):
|
||||
resolution: {integrity: sha512-YvvvQ+IjY09BX7Ab+1pjxkELQsBd4rPhWNw8WLBeFVxu/E7O+n6VYAqNsKdK/a2luFlX/sMpoWdGFfg4HvwdJQ==}
|
||||
engines: {node: '>=14.16'}
|
||||
peerDependencies:
|
||||
@ -6907,22 +6949,22 @@ packages:
|
||||
strip-ansi: 6.0.1
|
||||
tiny-invariant: 1.3.1
|
||||
typescript: 5.3.3
|
||||
vite: 5.0.10(@types/node@20.10.5)
|
||||
vite: 5.0.12(@types/node@20.10.5)
|
||||
vscode-languageclient: 7.0.0
|
||||
vscode-languageserver: 7.0.0
|
||||
vscode-languageserver-textdocument: 1.0.8
|
||||
vscode-uri: 3.0.7
|
||||
dev: true
|
||||
|
||||
/vite-plugin-package-version@1.1.0(vite@5.0.10):
|
||||
/vite-plugin-package-version@1.1.0(vite@5.0.12):
|
||||
resolution: {integrity: sha512-TPoFZXNanzcaKCIrC3e2L/TVRkkRLB6l4RPN/S7KbG7rWfyLcCEGsnXvxn6qR7fyZwXalnnSN/I9d6pSFjHpEA==}
|
||||
peerDependencies:
|
||||
vite: '>=2.0.0-beta.69'
|
||||
dependencies:
|
||||
vite: 5.0.10(@types/node@20.10.5)
|
||||
vite: 5.0.12(@types/node@20.10.5)
|
||||
dev: true
|
||||
|
||||
/vite-plugin-pwa@0.17.4(vite@5.0.10)(workbox-build@7.0.0)(workbox-window@7.0.0):
|
||||
/vite-plugin-pwa@0.17.4(vite@5.0.12)(workbox-build@7.0.0)(workbox-window@7.0.0):
|
||||
resolution: {integrity: sha512-j9iiyinFOYyof4Zk3Q+DtmYyDVBDAi6PuMGNGq6uGI0pw7E+LNm9e+nQ2ep9obMP/kjdWwzilqUrlfVRj9OobA==}
|
||||
engines: {node: '>=16.0.0'}
|
||||
peerDependencies:
|
||||
@ -6933,14 +6975,14 @@ packages:
|
||||
debug: 4.3.4
|
||||
fast-glob: 3.3.2
|
||||
pretty-bytes: 6.1.1
|
||||
vite: 5.0.10(@types/node@20.10.5)
|
||||
vite: 5.0.12(@types/node@20.10.5)
|
||||
workbox-build: 7.0.0
|
||||
workbox-window: 7.0.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/vite-plugin-static-copy@1.0.0(vite@5.0.10):
|
||||
/vite-plugin-static-copy@1.0.0(vite@5.0.12):
|
||||
resolution: {integrity: sha512-kMlrB3WDtC5GzFedNIPkpjnOAr8M11PfWOiUaONrUZ3AqogTsOmIhTt6w7Fh311wl8pN81ld7sfuOEogFJ9N8A==}
|
||||
engines: {node: ^18.0.0 || >=20.0.0}
|
||||
peerDependencies:
|
||||
@ -6950,11 +6992,11 @@ packages:
|
||||
fast-glob: 3.3.1
|
||||
fs-extra: 11.1.1
|
||||
picocolors: 1.0.0
|
||||
vite: 5.0.10(@types/node@20.10.5)
|
||||
vite: 5.0.12(@types/node@20.10.5)
|
||||
dev: true
|
||||
|
||||
/vite@5.0.10(@types/node@20.10.5):
|
||||
resolution: {integrity: sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw==}
|
||||
/vite@5.0.12(@types/node@20.10.5):
|
||||
resolution: {integrity: sha512-4hsnEkG3q0N4Tzf1+t6NdN9dg/L3BM+q8SWgbSPnJvrgH2kgdyzfVJwbR1ic69/4uMJJ/3dqDZZE5/WwqW8U1w==}
|
||||
engines: {node: ^18.0.0 || >=20.0.0}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
@ -6984,7 +7026,7 @@ packages:
|
||||
'@types/node': 20.10.5
|
||||
esbuild: 0.19.10
|
||||
postcss: 8.4.32
|
||||
rollup: /@rollup/wasm-node@4.9.4
|
||||
rollup: /@rollup/wasm-node@4.9.6
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
dev: true
|
||||
@ -7034,7 +7076,7 @@ packages:
|
||||
strip-literal: 1.3.0
|
||||
tinybench: 2.5.1
|
||||
tinypool: 0.8.1
|
||||
vite: 5.0.10(@types/node@20.10.5)
|
||||
vite: 5.0.12(@types/node@20.10.5)
|
||||
vite-node: 1.1.0(@types/node@20.10.5)
|
||||
why-is-node-running: 2.2.2
|
||||
transitivePeerDependencies:
|
||||
@ -7246,9 +7288,9 @@ packages:
|
||||
'@babel/core': 7.23.6
|
||||
'@babel/preset-env': 7.23.6(@babel/core@7.23.6)
|
||||
'@babel/runtime': 7.23.6
|
||||
'@rollup/plugin-babel': 5.3.1(@babel/core@7.23.6)(@rollup/wasm-node@4.9.4)
|
||||
'@rollup/plugin-node-resolve': 11.2.1(@rollup/wasm-node@4.9.4)
|
||||
'@rollup/plugin-replace': 2.4.2(@rollup/wasm-node@4.9.4)
|
||||
'@rollup/plugin-babel': 5.3.1(@babel/core@7.23.6)(@rollup/wasm-node@4.9.6)
|
||||
'@rollup/plugin-node-resolve': 11.2.1(@rollup/wasm-node@4.9.6)
|
||||
'@rollup/plugin-replace': 2.4.2(@rollup/wasm-node@4.9.6)
|
||||
'@surma/rollup-plugin-off-main-thread': 2.2.3
|
||||
ajv: 8.12.0
|
||||
common-tags: 1.8.2
|
||||
@ -7257,8 +7299,8 @@ packages:
|
||||
glob: 7.2.3
|
||||
lodash: 4.17.21
|
||||
pretty-bytes: 5.6.0
|
||||
rollup: /@rollup/wasm-node@4.9.4
|
||||
rollup-plugin-terser: 7.0.2(@rollup/wasm-node@4.9.4)
|
||||
rollup: /@rollup/wasm-node@4.9.6
|
||||
rollup-plugin-terser: 7.0.2(@rollup/wasm-node@4.9.6)
|
||||
source-map: 0.8.0-beta.0
|
||||
stringify-object: 3.3.0
|
||||
strip-comments: 2.0.1
|
||||
@ -7425,7 +7467,6 @@ packages:
|
||||
|
||||
/yallist@4.0.0:
|
||||
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
||||
dev: true
|
||||
|
||||
/yaml@2.3.2:
|
||||
resolution: {integrity: sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==}
|
||||
|
@ -9,12 +9,14 @@ import en from "@/assets/locales/en.json";
|
||||
import es from "@/assets/locales/es.json";
|
||||
import et from "@/assets/locales/et.json";
|
||||
import fa from "@/assets/locales/fa.json";
|
||||
import fi from "@/assets/locales/fi-FI.json";
|
||||
import fr from "@/assets/locales/fr.json";
|
||||
import gl from "@/assets/locales/gl.json";
|
||||
import gu from "@/assets/locales/gu.json";
|
||||
import he from "@/assets/locales/he.json";
|
||||
import hi from "@/assets/locales/hi.json";
|
||||
import id from "@/assets/locales/id.json";
|
||||
import is from "@/assets/locales/is-IS.json";
|
||||
import it from "@/assets/locales/it.json";
|
||||
import ja from "@/assets/locales/ja.json";
|
||||
import ko from "@/assets/locales/ko.json";
|
||||
@ -22,10 +24,12 @@ import lv from "@/assets/locales/lv.json";
|
||||
import minion from "@/assets/locales/minion.json";
|
||||
import ne from "@/assets/locales/ne.json";
|
||||
import nl from "@/assets/locales/nl.json";
|
||||
import nv from "@/assets/locales/nv.json";
|
||||
import pa from "@/assets/locales/pa.json";
|
||||
import pirate from "@/assets/locales/pirate.json";
|
||||
import pl from "@/assets/locales/pl.json";
|
||||
import ptbr from "@/assets/locales/pt-BR.json";
|
||||
import ptpt from "@/assets/locales/pt-PT.json";
|
||||
import ro from "@/assets/locales/ro.json";
|
||||
import ru from "@/assets/locales/ru.json";
|
||||
import sl from "@/assets/locales/sl.json";
|
||||
@ -64,6 +68,7 @@ export const locales = {
|
||||
tok,
|
||||
hi,
|
||||
"pt-BR": ptbr,
|
||||
"pt-PT": ptpt,
|
||||
uk,
|
||||
bg,
|
||||
bn,
|
||||
@ -76,9 +81,13 @@ export const locales = {
|
||||
sl,
|
||||
ta,
|
||||
"zh-HANT": zhhant,
|
||||
is,
|
||||
ru,
|
||||
gl,
|
||||
pa,
|
||||
ro,
|
||||
fi,
|
||||
nv,
|
||||
};
|
||||
|
||||
export type Locales = keyof typeof locales;
|
||||
|
@ -394,11 +394,6 @@
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"language": "لغة التطبيق",
|
||||
"languageDescription": "اللغة المطبقة على كامل التطبيق.",
|
||||
"title": "اللغة"
|
||||
},
|
||||
"reset": "إعادة تعيين",
|
||||
"save": "حفظ",
|
||||
"sidebar": {
|
||||
|
@ -181,14 +181,43 @@
|
||||
"disclaimer": "ডাউনলোড সরাসরি প্রদানকারী থেকে নেওয়া হয়. কিভাবে ডাউনলোড দেওয়া হয় তার উপর মুভি-ওয়েবের নিয়ন্ত্রণ নেই।",
|
||||
"downloadPlaylist": "প্লেলিস্ট ডাউনলোড করুন",
|
||||
"downloadSubtitle": "বর্তমান সাবটাইটেল ডাউনলোড করুন",
|
||||
"downloadVideo": "ভিডিও ডাউনলোড"
|
||||
"downloadVideo": "ভিডিও ডাউনলোড",
|
||||
"hlsDisclaimer": "ডাউনলোড সরাসরি প্রদানকারী থেকে নেওয়া হয়. কিভাবে ডাউনলোড দেওয়া হয় তার উপর মুভি-ওয়েবের নিয়ন্ত্রণ নেই। অনুগ্রহ করে মনে রাখবেন যে আপনি একটি HLS প্লেলিস্ট ডাউনলোড করছেন, এটি উন্নত মাল্টিমিডিয়া স্ট্রিমিংয়ের সাথে পরিচিত ব্যবহারকারীদের জন্য।",
|
||||
"onAndroid": {
|
||||
"1": "অ্যান্ড্রয়েডে ডাউনলোড করতে, ডাউনলোড বোতামে ক্লিক করুন তারপর, নতুন পৃষ্ঠায়, ভিডিওতে <bold>ট্যাপ করুন এবং ধরে রাখুন</bold>, তারপরে <bold>সংরক্ষণ করুন</bold> নির্বাচন করুন।",
|
||||
"shortTitle": "ডাউনলোড/অ্যান্ড্রয়েড",
|
||||
"title": "অ্যান্ড্রয়েডে ডাউনলোড হচ্ছে"
|
||||
},
|
||||
"onIos": {
|
||||
"1": "iOS-এ ডাউনলোড করতে, ডাউনলোড বোতামে ক্লিক করুন তারপর, নতুন পৃষ্ঠায়, <bold><ios_share /></bold>-এ ক্লিক করুন, তারপর <bold>ফাইলে সংরক্ষণ করুন <ios_files /></bold>।",
|
||||
"shortTitle": "ডাউনলোড / iOS",
|
||||
"title": "iOS এ ডাউনলোড হচ্ছে"
|
||||
},
|
||||
"onPc": {
|
||||
"1": "পিসিতে, ডাউনলোড বোতামে ক্লিক করুন তারপর, নতুন পৃষ্ঠায়, ভিডিওটিতে ডান ক্লিক করুন এবং <bold>ভিডিওটিকে এই হিসাবে সংরক্ষণ করুন</bold> নির্বাচন করুন",
|
||||
"shortTitle": "ডাউনলোড/পিসি",
|
||||
"title": "পিসিতে ডাউনলোড হচ্ছে"
|
||||
},
|
||||
"title": "ডাউনলোড করুন"
|
||||
},
|
||||
"episodes": {
|
||||
"button": "পর্বগুলি",
|
||||
"emptyState": "এই মরসুমে কোন পর্ব নেই, পরে আবার চেক করুন!",
|
||||
"episodeBadge": "E{{episode}}",
|
||||
"loadingError": "ঋতু লোড করার সময় ত্রুটি৷",
|
||||
"loadingList": "লোড হচ্ছে..।",
|
||||
"loadingTitle": "লোড হচ্ছে..।"
|
||||
"loadingTitle": "লোড হচ্ছে..।",
|
||||
"unairedEpisodes": "এই সিজনের এক বা একাধিক পর্ব অক্ষম করা হয়েছে কারণ সেগুলি এখনও সম্প্রচার করা হয়নি।"
|
||||
},
|
||||
"playback": {
|
||||
"speedLabel": "প্লেব্যাক গতি",
|
||||
"title": "প্লেব্যাক সেটিংস"
|
||||
},
|
||||
"quality": {
|
||||
"automaticLabel": "স্বয়ংক্রিয় গুণমান",
|
||||
"hint": "আপনি বিভিন্ন গুণমানের বিকল্প পেতে <0>উৎস পরিবর্তন</0> করে দেখতে পারেন।",
|
||||
"iosNoQuality": "অ্যাপল-সংজ্ঞায়িত সীমাবদ্ধতার কারণে, এই উৎসের জন্য গুণমান নির্বাচন iOS-এ উপলব্ধ নয়। বিভিন্ন মানের বিকল্প পেতে আপনি <0>অন্য উৎসে স্যুইচ করার</0> চেষ্টা করতে পারেন।",
|
||||
"title": "গুণমান"
|
||||
},
|
||||
"settings": {
|
||||
"downloadItem": "ডাউনলোড করুন",
|
||||
@ -228,6 +257,29 @@
|
||||
"title": "সাবটাইটেল",
|
||||
"unknownLanguage": "অজানা"
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"api": {
|
||||
"text": "API মেটাডেটা লোড করা যায়নি, অনুগ্রহ করে আপনার ইন্টারনেট সংযোগ পরীক্ষা করুন।",
|
||||
"title": "API মেটাডেটা লোড করতে ব্যর্থ হয়েছে"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "ব্যর্থ",
|
||||
"homeButton": "বাড়িতে যেতে",
|
||||
"text": "TMDB থেকে মিডিয়ার মেটাডেটা লোড করা যায়নি। আপনার ইন্টারনেট সংযোগে TMDB ডাউন বা ব্লক করা আছে কিনা তা অনুগ্রহ করে চেক করুন।",
|
||||
"title": "মেটাডেটা লোড করতে ব্যর্থ হয়েছে"
|
||||
},
|
||||
"notFound": {
|
||||
"badge": "পাওয়া যায়নি",
|
||||
"homeButton": "বাড়িতে ফিরে যাও",
|
||||
"text": "আপনার অনুরোধ করা মিডিয়া আমরা খুঁজে পাইনি। হয় এটি সরানো হয়েছে অথবা আপনি URL-এর সাথে হেরফের করেছেন।"
|
||||
}
|
||||
},
|
||||
"turnstile": {
|
||||
"description": "ডানদিকে ক্যাপচা সম্পূর্ণ করে আপনি যে মানুষ তা যাচাই করুন। সিনেমা-ওয়েবকে নিরাপদ রাখতেই এই!",
|
||||
"error": "আপনার মানবতা যাচাই করতে ব্যর্থ হয়েছে. অনুগ্রহপূর্বক আবার চেষ্টা করুন।",
|
||||
"title": "আপনি যে মানুষ তা আমাদের যাচাই করতে হবে।",
|
||||
"verifyingHumanity": "আপনার মানবতা যাচাই করা হচ্ছে..।"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@
|
||||
},
|
||||
"actions": {
|
||||
"copied": "S'ha copiat",
|
||||
"copy": "Cipia"
|
||||
"copy": "Copia"
|
||||
},
|
||||
"auth": {
|
||||
"createAccount": "Encara no teniu un compte? <0>Creeu un compte.</0>",
|
||||
@ -108,7 +108,7 @@
|
||||
"sectionTitle": "Continueu mirant"
|
||||
},
|
||||
"mediaList": {
|
||||
"stopEditing": "Atura l'edició"
|
||||
"stopEditing": "Deixa d'editar"
|
||||
},
|
||||
"search": {
|
||||
"allResults": "Això és tot el que tenim!",
|
||||
@ -390,30 +390,25 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "Si voleu connectar-vos a un rerefons personalitzat per a emmagatzemar les vostres dades, activeu-ho i proporcioneu l'URL.",
|
||||
"description": "Si voleu connectar-vos a un rerefons personalitzat per a emmagatzemar les vostres dades, activeu-ho i proporcioneu l'URL. <0>Instruccions.</0>",
|
||||
"label": "Servidor personalitzat",
|
||||
"urlLabel": "URL del servidor personalitzat"
|
||||
},
|
||||
"title": "Connexions",
|
||||
"workers": {
|
||||
"addButton": "Afig un «worker»",
|
||||
"description": "Per fer funcionar l'aplicació, tot el trànsit s'encamina a través de servidors intermediaris. Activeu-ho si voleu portar els vostres propis «workers».",
|
||||
"description": "Per fer funcionar l'aplicació, tot el trànsit s'encamina a través de servidors intermediaris. Activeu-ho si voleu portar els vostres propis «workers».<0>Instruccions.</0>",
|
||||
"emptyState": "Encara no hi ha «workers», afegiu-ne un a continuació",
|
||||
"label": "Utilitza «workers» intermediaris personalitzats",
|
||||
"urlLabel": "URL dels «workers»",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"language": "Llengua de l'aplicació",
|
||||
"languageDescription": "La llengua s'aplica a tota l'aplicació.",
|
||||
"title": "Llengua"
|
||||
},
|
||||
"reset": "Restableix",
|
||||
"save": "Desa",
|
||||
"sidebar": {
|
||||
"info": {
|
||||
"appVersion": "Versió de l'aplicacií",
|
||||
"appVersion": "Versió de l'aplicació",
|
||||
"backendUrl": "URL del rerefons",
|
||||
"backendVersion": "Versió del rerefons",
|
||||
"hostname": "Nom de l'amfitrió",
|
||||
|
@ -95,6 +95,7 @@
|
||||
"about": "O nás",
|
||||
"dmca": "DMCA",
|
||||
"login": "Přihlásit se",
|
||||
"onboarding": "Nastavení",
|
||||
"pagetitle": "{{title}} - movie-web",
|
||||
"register": "Zaregistrovat se",
|
||||
"settings": "Nastavení"
|
||||
@ -165,6 +166,64 @@
|
||||
"message": "Dívali jsme se všude: pod koši, ve skříni, za proxy, ale nakonec jsme nemohli najít stránku, kterou hledáte.",
|
||||
"title": "Tuto stránku se nepodařilo najít"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "Zrušit",
|
||||
"confirm": "Použít výchozí nastavení",
|
||||
"description": "Výchozí nastavení nemá nejlepší streamy a může být strašně pomalá.",
|
||||
"title": "Jste si jist?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "Zpět",
|
||||
"explainer": "Pomocí rozšíření prohlížeče můžete získat nejlepší streamy, které nabízíme. S pouhou instalací.",
|
||||
"extensionHelp": "Pokud jste rozšíření nainstalovali, ale nebylo zjištěno. <bold>Otevřete rozšíření pomocí nabídky rozšíření ve vašem prohlížeči</bold> a postupujte podle pokynů na obrazovce.",
|
||||
"status": {
|
||||
"disallowed": "Rozšíření není pro tuto stránku povoleno",
|
||||
"disallowedAction": "Povolit rozšíření",
|
||||
"failed": "Nezdařilo se získávání stavu",
|
||||
"loading": "Čekání na instalaci rozšíření",
|
||||
"outdated": "Verze rozšíření je příliš stará",
|
||||
"success": "Rozšíření funguje podle očekávání!"
|
||||
},
|
||||
"submit": "Pokračovat",
|
||||
"title": "Začněme s rozšířením"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "Zpět",
|
||||
"explainer": "Pomocí metody proxy můžete získat streamy ve skvělé kvalitě vytvořením proxy serveru.",
|
||||
"input": {
|
||||
"errorConnection": "Nelze se připojit k proxy",
|
||||
"errorInvalidUrl": "Adresa URL není platná",
|
||||
"errorNotProxy": "Byla očekávaná proxy, ale byla předána webová stránka",
|
||||
"label": "Proxy URL",
|
||||
"placeholder": "https://"
|
||||
},
|
||||
"link": "Naučit se vytvořit proxy",
|
||||
"submit": "Předložit proxy",
|
||||
"title": "Pojďme uďelat novou proxy"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "Abyste získali co nejlepší streamy, musíte zvolit, kterou streamovací metodu chcete použít.",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "Nechci zdroje s dobrou kvalitou,<0 /> <1>použít výchozí nastavení</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "Nainstalujte si rozšíření",
|
||||
"description": "Nainstalujte si rozšíření prohlížeče a získejte přístup k nejlepším zdrojům.",
|
||||
"quality": "Nejlepší kvalita",
|
||||
"title": "Rozšíření prohlížeče"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "Nastavit proxy",
|
||||
"description": "Nastavte si proxy během 5 minut, pro získání přístupu k skvělým zdrojům.",
|
||||
"quality": "Dobrá kvalita",
|
||||
"title": "Vlastní proxy"
|
||||
}
|
||||
},
|
||||
"title": "Pojďme vám nastavit movie-web"
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "Zavřít"
|
||||
},
|
||||
@ -182,7 +241,7 @@
|
||||
"downloadPlaylist": "Stáhnout playlist",
|
||||
"downloadSubtitle": "Stáhnout aktuální titulky",
|
||||
"downloadVideo": "Stáhnout video",
|
||||
"hlsDisclaimer": "Stahování probíhá přímo u poskytovatele. movie-web nemá kontrolu nad tím, jak jsou stahování poskytovány. Vezměte prosím na vědomí, že stahujete HLS playlist, který je určen pro uživatele obeznámené s pokročilým streamováním médií.",
|
||||
"hlsDisclaimer": "Stahování probíhá přímo u poskytovatele. movie-web nemá kontrolu nad tím, jak jsou stahování poskytovány.<br /><br />Vezměte prosím na vědomí, že stahujete HLS playlist,<bold> který není doporučen stahovat pokud nejste obeznámeni s pokročilým streamováním médií</bold>. Raději skuste jiný zdroj pro jiný formát.",
|
||||
"onAndroid": {
|
||||
"1": "Na Androidu klikněte na tlačítko stahování, poté na nové stránce <bold>klepněte a podržte</bold> na videu a poté vyberte <bold>uložit</bold>.",
|
||||
"shortTitle": "Stahování / Android",
|
||||
@ -263,6 +322,17 @@
|
||||
"text": "Metadata API nelze načíst, zkontrolujte prosím vaše připojení k internetu.",
|
||||
"title": "Nepodařilo se načíst API metadata"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "Odstraněno",
|
||||
"text": "Toto média není dostupné, kvůli oznámení o zastavení šíření nebo nároku na autorská práva.",
|
||||
"title": "Média byla odstraněna"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "Chybí povolení",
|
||||
"button": "Použít rozšíření",
|
||||
"text": "Máte rozšíření, ale k jeho použití potřebujeme vaše povolení.",
|
||||
"title": "Konfigurace rozšíření"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "Neúspěšný",
|
||||
"homeButton": "Jít domů",
|
||||
@ -390,24 +460,49 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "Pokud se chcete připojit k vlastnímu backendu pr ukládání dat, povolte toto a zadejte URL adresu.",
|
||||
"description": "Pokud se chcete připojit k vlastnímu backendu pro ukládání dat, povolte toto a zadejte URL adresu. <0>Instrukce.</0>",
|
||||
"label": "Vlastní server",
|
||||
"urlLabel": "URL adresa vlastního serveru"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "Proveďte nastavení",
|
||||
"errorStatus": {
|
||||
"description": "Vypadá to, že jedna nebo více položek v tomto nastavení potřebuje vaši pozornost.",
|
||||
"title": "Něco potřebuje vaši pozornost"
|
||||
},
|
||||
"itemError": "S tímto nastavením je něco špatně. Projděte znovu nastavením abyste to opravili.",
|
||||
"items": {
|
||||
"default": "Výchozí nastavení",
|
||||
"extension": "Rozšíření",
|
||||
"proxy": "Vlastní proxy"
|
||||
},
|
||||
"redoSetup": "Proveďte znovu nastavení",
|
||||
"successStatus": {
|
||||
"description": "Všechny věci jsou připraveny, abyste mohli začít sledovat svá oblíbená média.",
|
||||
"title": "Všechno je nastaveno!"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "Prosím klikněte na vedlejší tlačítko abyste začali proces nastavování.",
|
||||
"title": "Neprošli jste nastavením"
|
||||
}
|
||||
},
|
||||
"title": "Spojení",
|
||||
"workers": {
|
||||
"addButton": "Přidat nového pracovníka",
|
||||
"description": "Aby byla aplikace funkční, veškerá trafika prochází přes proxy. Povolte toto, pokud chcete používat svoje vlastní pracovníky.",
|
||||
"description": "Aby byla aplikace funkční, veškerá trafika prochází přes proxy. Povolte toto, pokud chcete používat svoje vlastní pracovníky. <0>Instrukce.</0>",
|
||||
"emptyState": "Zatím žádní pracovníci, přidej jednoho dolů",
|
||||
"label": "Použít vlastní proxy pracovníky",
|
||||
"urlLabel": "URL adresy pracovníků",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"preferences": {
|
||||
"language": "Jazyk aplikace",
|
||||
"languageDescription": "Jazyk použitý na celou aplikaci.",
|
||||
"title": "Lokální"
|
||||
"languageDescription": "Jazyk aplikován na celou aplikaci.",
|
||||
"thumbnail": "Generovat miniatury",
|
||||
"thumbnailDescription": "Videa většinou nemají miniatury. Toto nastavení můžete povolit, ale mohou zpomalit vaše video.",
|
||||
"thumbnailLabel": "Generovat miniatury",
|
||||
"title": "Preference"
|
||||
},
|
||||
"reset": "Resetovat",
|
||||
"save": "Uložit",
|
||||
|
@ -95,6 +95,7 @@
|
||||
"about": "Über",
|
||||
"dmca": "DMCA",
|
||||
"login": "Anmelden",
|
||||
"onboarding": "Einrichtung",
|
||||
"pagetitle": "{{title}} - movie-web",
|
||||
"register": "Registrieren",
|
||||
"settings": "Einstellungen"
|
||||
@ -165,6 +166,66 @@
|
||||
"message": "Wir haben überall gesucht: Unter den Eimern, im Schrank, hinter dem Proxy. Wir konnten die gesuchte Seite nicht finden.",
|
||||
"title": "Diese Seite wurde nicht gefunden"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "Abbrechen",
|
||||
"confirm": "Standard-Setup verwenden",
|
||||
"description": "Das Standard-Setup verfügt nicht über die besten Streams und kann unerträglich langsam sein.",
|
||||
"title": "Sicher?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "Zurück gehen",
|
||||
"explainer": "Mit der Browser-Erweiterung kannst du die besten Streams benutzen, die wir zu bieten haben. Mit nur einer einfachen Installation.",
|
||||
"explainerIos": "Leider ist die Browser-Extension unter iOS nicht unterstützt. Klicken Sie auf <bold>Zurück</bold>, um eine andere Option auszuwählen.",
|
||||
"extensionHelp": "Falls du die Erweiterung installiert hast, aber sie aber nicht erkannt wird, <bold>öffne die Erweiterung über das Erweiterungsmenü Ihres Browsers</bold> und befolge die Schritte auf dem Bildschirm.",
|
||||
"linkChrome": "Chrome Erweiterung installieren",
|
||||
"linkFirefox": "Firefox Erweiterung installieren",
|
||||
"notDetecting": "Auf Chrome Installiert, aber die Website erkennt es nicht? Versuche, die Seite wieder zu laden!",
|
||||
"notDetectingAction": "Seite neuladen",
|
||||
"status": {
|
||||
"disallowed": "Browser-Erweiterung ist für diese Website nicht aktiviert",
|
||||
"disallowedAction": "Browser-Erweiterung aktivieren",
|
||||
"failed": "Statusanforderung fehlgeschlagen",
|
||||
"loading": "Wartet dass du die Erweiterung installierst",
|
||||
"outdated": "Erweiterungsversion zu alt",
|
||||
"success": "Die Browser-Erweiterung funktioniert wie erwartet!"
|
||||
},
|
||||
"submit": "Weiter"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "Zurück gehen",
|
||||
"explainer": "Mit der Proxy-Methode kannst du Streams mit guter Qualität benutzen, indem du einen eigenen Proxy einstellst.",
|
||||
"input": {
|
||||
"errorConnection": "Es konnte keine Verbindung zum Proxy hergestellt werden",
|
||||
"errorInvalidUrl": "Keine gültige URL",
|
||||
"errorNotProxy": "Ein Proxy wurde erwartet, aber eine Website wurde eingegeben",
|
||||
"label": "Proxy-URL",
|
||||
"placeholder": "https://"
|
||||
},
|
||||
"link": "Erfahre, wie man einen Proxy einstellt",
|
||||
"submit": "Proxy einreichen"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "Um die bestmöglichen Streams zu erhalten, müssen Sie auswählen, welche Streaming-Methode Sie verwenden möchten.",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "Ich möchte keine Streams mit guter Qualität. <0 /> <1>Standardeinstellung benutzen</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "Browser-Erweitung installieren",
|
||||
"description": "Installiere die Browser-Erweitung, um Zugriff auf die besten Quellen zu bekommen.",
|
||||
"quality": "Beste Qualität",
|
||||
"title": "Browser extension"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "Proxy einstellen",
|
||||
"description": "Richte in nur 5 Minuten einen Proxy ein und erhalte Zugriff auf großartige Quellen.",
|
||||
"quality": "Gute Qualität",
|
||||
"title": "Eigene Proxy"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "Schließen"
|
||||
},
|
||||
@ -182,7 +243,7 @@
|
||||
"downloadPlaylist": "Playlist herunterladen",
|
||||
"downloadSubtitle": "Aktuelle Untertitel herunterladen",
|
||||
"downloadVideo": "Video herunterladen",
|
||||
"hlsDisclaimer": "movie-web hat keinen Einfluss darauf, wie Downloads bereitgestellt werden. Downloads werden direkt vom Anbieter bezogen. Bitte beachte, dass du eine HLS-Wiedergabeliste herunterlädst, diese ist für Nutzer gedacht, die mit fortgeschrittenem Multimedia-Streaming vertraut sind.",
|
||||
"hlsDisclaimer": "movie-web hat keinen Einfluss darauf, wie Downloads bereitgestellt werden. Downloads werden direkt vom Anbieter bezogen. <br /><br />Bitte beachte, dass du eine HLS-Wiedergabeliste herunterlädst, <bold>dies ist nicht empfohlen für Nutzer die nicht mit Erweiterten Streaming Formaten vertraut sind</bold>. Probiere andere Anbieter für andere Formate.",
|
||||
"onAndroid": {
|
||||
"1": "Um auf Android Herunterzuladen, tippe auf den Download-Button, <bold>tippe und halte</bold> auf der neuen Seite auf das Video und wähle <bold>Speichern</bold> aus.",
|
||||
"shortTitle": "Download / Android",
|
||||
@ -263,6 +324,17 @@
|
||||
"text": "API Metadaten konnten nicht geladen werden, überprüfe deine Netzwerkverbindung.",
|
||||
"title": "API Metadaten konnten nicht geladen werden"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "Entfernt",
|
||||
"text": "Das Video ist aufgrund einer Takedown-Anfrage oder eines Urheberrechtsanspruchs nicht mehr verfügbar.",
|
||||
"title": "Video wurde entfernt"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "Berechtigung fehlt",
|
||||
"button": "Verwende Erweiterung",
|
||||
"text": "Du hast die Browser-Erweiterung, aber wir brauchen deine Berechtigung um mit der Erweiterung zu starten.",
|
||||
"title": "Konfiguriere die Erweiterung"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "Fehlgeschlagen",
|
||||
"homeButton": "Zurück zur Startseite",
|
||||
@ -390,24 +462,49 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "Falls du dich mit einem anderen Server verbinden willst, um deine Daten zu speichern. Aktiviere dies und gebe die URL an.",
|
||||
"description": "Falls du dich mit einem anderen Server verbinden willst, um deine Daten zu speichern. Aktiviere dies und gebe die URL an. <0>Anweisungen.</0>",
|
||||
"label": "Eigener Server",
|
||||
"urlLabel": "Eigene Server-URL"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "Einrichten",
|
||||
"errorStatus": {
|
||||
"description": "Es scheint so, als bräuchte eine oder mehrere Schritte in dieser Einrichtung deine Aufmerksamkeit.",
|
||||
"title": "Etwas braucht deine Aufmerksamkeit"
|
||||
},
|
||||
"itemError": "Mit diesem Setup stimmt etwas nicht. Führen Sie das Setup erneut durch, um das Problem zu beheben.",
|
||||
"items": {
|
||||
"default": "Standard Einstellungen",
|
||||
"extension": "Erweiterung",
|
||||
"proxy": "Eigene Proxy"
|
||||
},
|
||||
"redoSetup": "Erneut einrichten",
|
||||
"successStatus": {
|
||||
"description": "Alles ist bereit, damit du deine Lieblingsserien und Filme ansehen kannst.",
|
||||
"title": "Alles eingerichtet!"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "Klicken Sie bitte auf den Button rechts, um die Setup zu starten.",
|
||||
"title": "Du hast das Setup noch nicht durchgeführt"
|
||||
}
|
||||
},
|
||||
"title": "Verbindung",
|
||||
"workers": {
|
||||
"addButton": "Neuen Worker hinzufügen",
|
||||
"description": "Damit die App funktioniert werden alle Anfrage durch einen Proxy geleitet. Aktiviere dies, falls du deinen eigenen Worker verwenden willst.",
|
||||
"description": "Damit die App funktioniert werden alle Anfrage durch einen Proxy geleitet. Aktiviere dies, falls du deinen eigenen Worker verwenden willst. <0>Anweisungen.</0>",
|
||||
"emptyState": "Keine Worker vorhanden, füge einen unten hinzu",
|
||||
"label": "Verwenden deinen eigenen Worker-Proxys",
|
||||
"urlLabel": "Worker-URLs",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"preferences": {
|
||||
"language": "App-Sprache",
|
||||
"languageDescription": "Sprache für die ganze App.",
|
||||
"title": "Sprache"
|
||||
"thumbnail": "Miniaturansichten generieren",
|
||||
"thumbnailDescription": "Meistens haben Videos keine Miniaturansicht. Du kannst diese Einstellung anmachen, um sie automatisch zu generieren, aber sie können dein Video langsamer machen.",
|
||||
"thumbnailLabel": "Miniaturansichten generieren",
|
||||
"title": "Einstellungen"
|
||||
},
|
||||
"reset": "Zurücksetzen",
|
||||
"save": "Speichern",
|
||||
|
@ -404,11 +404,6 @@
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"language": "Γλώσσα εφαρμογής",
|
||||
"languageDescription": "Γλώσσα που εφαρμόζεται σε ολόκληρη την εφαρμογή.",
|
||||
"title": "Τοποθεσία"
|
||||
},
|
||||
"reset": "Επαναφορά",
|
||||
"save": "Αποθήκευση",
|
||||
"sidebar": {
|
||||
|
@ -95,6 +95,7 @@
|
||||
"about": "About",
|
||||
"dmca": "DMCA",
|
||||
"login": "Login",
|
||||
"onboarding": "Setup",
|
||||
"pagetitle": "{{title}} - movie-web",
|
||||
"register": "Register",
|
||||
"settings": "Settings"
|
||||
@ -127,11 +128,15 @@
|
||||
},
|
||||
"morning": {
|
||||
"default": "What would you like to watch this morning?",
|
||||
"extra": ["I hear Before Sunrise is good"]
|
||||
"extra": [
|
||||
"I hear Before Sunrise is good"
|
||||
]
|
||||
},
|
||||
"night": {
|
||||
"default": "What would you like to watch tonight?",
|
||||
"extra": ["Tired? I hear The Exorcist is good."]
|
||||
"extra": [
|
||||
"Tired? I hear The Exorcist is good."
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -161,16 +166,73 @@
|
||||
"message": "We looked everywhere: under the bins, in the closet, behind the proxy but ultimately couldn't find the page you are looking for.",
|
||||
"title": "Couldn't find that page"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "Cancel",
|
||||
"confirm": "Use default setup",
|
||||
"description": "The default setup does not have the best streams and can be unbearably slow.",
|
||||
"title": "Are you sure?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "Go back",
|
||||
"explainer": "Using the browser extension, you can get the best streams we have to offer. With just a simple install.",
|
||||
"explainerIos": "Unfortunately, the browser extension is not supported on iOS, Press <bold>Go back</bold> to choose another option.",
|
||||
"extensionHelp": "If you've installed the extension but it's not detected, <bold>open the extension through your browsers extension menu</bold> and follow the steps on screen.",
|
||||
"linkChrome": "Install Chrome extension",
|
||||
"linkFirefox": "Install Firefox extension",
|
||||
"notDetecting": "Installed on Chrome, but the site isn't detecting it? Try reloading the page!",
|
||||
"notDetectingAction": "Reload page",
|
||||
"status": {
|
||||
"disallowed": "Extension is not enabled for this page",
|
||||
"disallowedAction": "Enable extension",
|
||||
"failed": "Failed to request status",
|
||||
"loading": "Waiting for you to install the extension",
|
||||
"outdated": "Extension version too old",
|
||||
"success": "Extension is working as expected!"
|
||||
},
|
||||
"submit": "Continue",
|
||||
"title": "Let's start with an extension"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "Go back",
|
||||
"explainer": "With the proxy method, you can get great quality streams by making a self-service proxy.",
|
||||
"input": {
|
||||
"errorConnection": "Could not connect to proxy",
|
||||
"errorInvalidUrl": "Not a valid URL",
|
||||
"errorNotProxy": "Expected a proxy but got a website",
|
||||
"label": "Proxy URL",
|
||||
"placeholder": "https://"
|
||||
},
|
||||
"link": "Learn how to make a proxy",
|
||||
"submit": "Submit proxy",
|
||||
"title": "Let's make a new proxy"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "To get the best streams possible, you will need to choose which streaming method you want to use.",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "I don't want good quality streams,<0 /> <1>use the default setup</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "Install extension",
|
||||
"description": "Install browser extension and gain access to the best sources.",
|
||||
"quality": "Best quality",
|
||||
"title": "Browser extension"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "Setup proxy",
|
||||
"description": "Setup a proxy in just 5 minutes and gain access to great sources.",
|
||||
"quality": "Good quality",
|
||||
"title": "Custom proxy"
|
||||
}
|
||||
},
|
||||
"title": "Let's get you setup with movie-web"
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "Close"
|
||||
},
|
||||
"player": {
|
||||
"turnstile": {
|
||||
"verifyingHumanity": "Verifying your humanity...",
|
||||
"title": "We need to verify that you're human.",
|
||||
"description": "Please verify that you are human by completing the Captcha on the right. This is to keep movie-web safe!",
|
||||
"error": "Failed to verify your humanity. Please try again."
|
||||
},
|
||||
"back": {
|
||||
"default": "Back to home",
|
||||
"short": "Back"
|
||||
@ -179,59 +241,12 @@
|
||||
"enabled": "Casting to device..."
|
||||
},
|
||||
"menus": {
|
||||
"settings": {
|
||||
"videoSection": "Video settings",
|
||||
"experienceSection": "Viewing experience",
|
||||
"enableSubtitles": "Enable Subtitles",
|
||||
"subtitleItem": "Subtitle settings",
|
||||
"sourceItem": "Video sources",
|
||||
"playbackItem": "Playback settings",
|
||||
"downloadItem": "Download",
|
||||
"qualityItem": "Quality"
|
||||
},
|
||||
"episodes": {
|
||||
"button": "Episodes",
|
||||
"loadingTitle": "Loading...",
|
||||
"loadingList": "Loading...",
|
||||
"loadingError": "Error loading season",
|
||||
"emptyState": "There are no episodes in this season, check back later!",
|
||||
"episodeBadge": "E{{episode}}",
|
||||
"unairedEpisodes": "One or more episodes in this season have been disabled because they haven't been aired yet."
|
||||
},
|
||||
"sources": {
|
||||
"title": "Sources",
|
||||
"unknownOption": "Unknown",
|
||||
"noStream": {
|
||||
"title": "No stream",
|
||||
"text": "This source has no streams for this movie or show."
|
||||
},
|
||||
"noEmbeds": {
|
||||
"title": "No embeds found",
|
||||
"text": "We were unable to find any embeds, please try a different source."
|
||||
},
|
||||
"failed": {
|
||||
"title": "Failed to scrape",
|
||||
"text": "There was an error while trying to find any videos, please try a different source."
|
||||
}
|
||||
},
|
||||
"subtitles": {
|
||||
"title": "Subtitles",
|
||||
"customizeLabel": "Customize",
|
||||
"settings": {
|
||||
"fixCapitals": "Fix capitalization",
|
||||
"delay": "Subtitle delay",
|
||||
"backlink": "Custom subtitles"
|
||||
},
|
||||
"customChoice": "Select subtitle from file",
|
||||
"offChoice": "Off",
|
||||
"unknownLanguage": "Unknown"
|
||||
},
|
||||
"downloads": {
|
||||
"disclaimer": "Downloads are taken directly from the provider. movie-web does not have control over how the downloads are provided.",
|
||||
"downloadSubtitle": "Download current subtitle",
|
||||
"downloadPlaylist": "Download playlist",
|
||||
"downloadSubtitle": "Download current subtitle",
|
||||
"downloadVideo": "Download video",
|
||||
"hlsDisclaimer": "Downloads are taken directly from the provider. movie-web does not have control over how the downloads are provided. Please note that you are downloading an HLS playlist, this is intended for users familiar with advanced multimedia streaming.",
|
||||
"hlsDisclaimer": "Downloads are taken directly from the provider. movie-web does not have control over how the downloads are provided.<br /><br />Please note that you are downloading an HLS playlist, <bold>it is not recommended to download if you are not familiar with advanced streaming formats</bold>. Try different sources for different formats.",
|
||||
"onAndroid": {
|
||||
"1": "To download on Android, click the download button then, on the new page, <bold>tap and hold</bold> on the video, then select <bold>save</bold>.",
|
||||
"shortTitle": "Download / Android",
|
||||
@ -249,6 +264,15 @@
|
||||
},
|
||||
"title": "Download"
|
||||
},
|
||||
"episodes": {
|
||||
"button": "Episodes",
|
||||
"emptyState": "There are no episodes in this season, check back later!",
|
||||
"episodeBadge": "E{{episode}}",
|
||||
"loadingError": "Error loading season",
|
||||
"loadingList": "Loading...",
|
||||
"loadingTitle": "Loading...",
|
||||
"unairedEpisodes": "One or more episodes in this season have been disabled because they haven't been aired yet."
|
||||
},
|
||||
"playback": {
|
||||
"speedLabel": "Playback speed",
|
||||
"title": "Playback settings"
|
||||
@ -258,19 +282,68 @@
|
||||
"hint": "You can try <0>switching source</0> to get different quality options.",
|
||||
"iosNoQuality": "Due to Apple-defined limitations, quality selection is not available on iOS for this source. You can try <0>switching to another source</0> to get different quality options.",
|
||||
"title": "Quality"
|
||||
},
|
||||
"settings": {
|
||||
"downloadItem": "Download",
|
||||
"enableSubtitles": "Enable Subtitles",
|
||||
"experienceSection": "Viewing experience",
|
||||
"playbackItem": "Playback settings",
|
||||
"qualityItem": "Quality",
|
||||
"sourceItem": "Video sources",
|
||||
"subtitleItem": "Subtitle settings",
|
||||
"videoSection": "Video settings"
|
||||
},
|
||||
"sources": {
|
||||
"failed": {
|
||||
"text": "There was an error while trying to find any videos, please try a different source.",
|
||||
"title": "Failed to scrape"
|
||||
},
|
||||
"noEmbeds": {
|
||||
"text": "We were unable to find any embeds, please try a different source.",
|
||||
"title": "No embeds found"
|
||||
},
|
||||
"noStream": {
|
||||
"text": "This source has no streams for this movie or show.",
|
||||
"title": "No stream"
|
||||
},
|
||||
"title": "Sources",
|
||||
"unknownOption": "Unknown"
|
||||
},
|
||||
"subtitles": {
|
||||
"customChoice": "Select subtitle from file",
|
||||
"customizeLabel": "Customize",
|
||||
"offChoice": "Off",
|
||||
"settings": {
|
||||
"backlink": "Custom subtitles",
|
||||
"delay": "Subtitle delay",
|
||||
"fixCapitals": "Fix capitalization"
|
||||
},
|
||||
"title": "Subtitles",
|
||||
"unknownLanguage": "Unknown"
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"api": {
|
||||
"text": "Could not load API metadata, please check your internet connection.",
|
||||
"title": "Failed to load API metadata"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "Removed",
|
||||
"text": "This media is no longer available due to a takedown notice or copyright claim.",
|
||||
"title": "Media has been removed"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "Permission Missing",
|
||||
"button": "Use extension",
|
||||
"text": "You have the browser extension, but we need your permission to get started using the extension.",
|
||||
"title": "Configure the extension"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "Failed",
|
||||
"homeButton": "Go home",
|
||||
"text": "Could not load the media's metadata from TMDB. Please check whether TMDB is down or blocked on your internet connection.",
|
||||
"title": "Failed to load metadata"
|
||||
},
|
||||
"api": {
|
||||
"text": "Could not load API metadata, please check your internet connection.",
|
||||
"title": "Failed to load API metadata"
|
||||
},
|
||||
"notFound": {
|
||||
"badge": "Not found",
|
||||
"homeButton": "Back to home",
|
||||
@ -314,6 +387,12 @@
|
||||
"remaining": "{{timeLeft}} left • Finish at {{timeFinished, datetime}}",
|
||||
"shortRegular": "{{timeWatched}}",
|
||||
"shortRemaining": "-{{timeLeft}}"
|
||||
},
|
||||
"turnstile": {
|
||||
"description": "Please verify that you are human by completing the Captcha on the right. This is to keep movie-web safe!",
|
||||
"error": "Failed to verify your humanity. Please try again.",
|
||||
"title": "We need to verify that you're human.",
|
||||
"verifyingHumanity": "Verifying your humanity..."
|
||||
}
|
||||
},
|
||||
"screens": {
|
||||
@ -384,33 +463,51 @@
|
||||
},
|
||||
"title": "Appearance"
|
||||
},
|
||||
"subtitles": {
|
||||
"title": "Subtitles",
|
||||
"previewQuote": "I must not fear. Fear is the mind-killer.",
|
||||
"textSizeLabel": "Text size",
|
||||
"backgroundLabel": "Background opacity",
|
||||
"colorLabel": "Color"
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "If you would like to connect to a custom backend to store your data, enable this and provide the URL.",
|
||||
"description": "If you would like to connect to a custom backend to store your data, enable this and provide the URL. <0>Instructions.</0>",
|
||||
"label": "Custom server",
|
||||
"urlLabel": "Custom server URL"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "Do setup",
|
||||
"errorStatus": {
|
||||
"description": "It seems that one or more items in this setup need your attention.",
|
||||
"title": "Something needs your attention"
|
||||
},
|
||||
"itemError": "There is something wrong with this setting. Go through setup again to fix it.",
|
||||
"items": {
|
||||
"default": "Default setup",
|
||||
"extension": "Extension",
|
||||
"proxy": "Custom proxy"
|
||||
},
|
||||
"redoSetup": "Redo setup",
|
||||
"successStatus": {
|
||||
"description": "All things are in place for you to start watching your favourite media.",
|
||||
"title": "Everything is set up!"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "Please click the button to the right to start the setup process.",
|
||||
"title": "You haven't gone through setup"
|
||||
}
|
||||
},
|
||||
"title": "Connections",
|
||||
"workers": {
|
||||
"addButton": "Add new worker",
|
||||
"description": "To make the application function, all traffic is routed through proxies. Enable this if you want to bring your own workers.",
|
||||
"description": "To make the application function, all traffic is routed through proxies. Enable this if you want to bring your own workers. <0>Instructions.</0>",
|
||||
"emptyState": "No workers yet, add one below",
|
||||
"label": "Use custom proxy workers",
|
||||
"urlLabel": "Worker URLs",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"preferences": {
|
||||
"language": "Application language",
|
||||
"languageDescription": "Language applied to the entire application.",
|
||||
"title": "Locale"
|
||||
"thumbnail": "Generate thumbnails",
|
||||
"thumbnailDescription": "Most of the time, videos don't have thumbnails. You can enable this setting to generate them on the fly but they can make your video slower.",
|
||||
"thumbnailLabel": "Generate thumbnails",
|
||||
"title": "Preferences"
|
||||
},
|
||||
"reset": "Reset",
|
||||
"save": "Save",
|
||||
@ -428,6 +525,13 @@
|
||||
"userId": "User ID"
|
||||
}
|
||||
},
|
||||
"subtitles": {
|
||||
"backgroundLabel": "Background opacity",
|
||||
"colorLabel": "Color",
|
||||
"previewQuote": "I must not fear. Fear is the mind-killer.",
|
||||
"textSizeLabel": "Text size",
|
||||
"title": "Subtitles"
|
||||
},
|
||||
"unsaved": "You have unsaved changes"
|
||||
}
|
||||
}
|
||||
|
@ -95,6 +95,7 @@
|
||||
"about": "Acerca de",
|
||||
"dmca": "DMCA",
|
||||
"login": "Iniciar sesión",
|
||||
"onboarding": "Configurar",
|
||||
"pagetitle": "{{title}} - movie-web",
|
||||
"register": "Registrarse",
|
||||
"settings": "Configuración"
|
||||
@ -165,6 +166,69 @@
|
||||
"message": "Buscamos en todas partes: debajo de los contenedores, en el armario, detrás del proxy, pero al final no pudimos encontrar la página que estás buscando.",
|
||||
"title": "No se puede encontrar esa página"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "Cancelar",
|
||||
"confirm": "Usar configuración por defecto",
|
||||
"description": "La configuración predeterminada no tiene las mejores transmisiones y puede ser insoportablemente lenta.",
|
||||
"title": "Estás seguro?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "Volver atrás",
|
||||
"explainer": "Usando la extensión de navegador, puedes obtener las mejores transiciones que ofrecemos. Simplemente con una simple instalación.",
|
||||
"explainerIos": "Desafortunadamente, la extensión para el navegador no es compatible con IOS. Pulsa <bold>ir atrás</bold> para elegir otra opción.",
|
||||
"extensionHelp": "Si has instalado la extensión pero no es detectada, <bold>abre la extensión desde la sección en el menú de extensiones</bold> y sigue los pasos de la pantalla.",
|
||||
"linkChrome": "Instalar extensión para Chrome",
|
||||
"linkFirefox": "Instalar extensión para Firefox",
|
||||
"notDetecting": "Instalada en Chrome, pero la página no la está detectado. ¡Prueba a recargar la web!",
|
||||
"notDetectingAction": "Recargar página",
|
||||
"status": {
|
||||
"disallowed": "La extensión no está activada para esta página",
|
||||
"disallowedAction": "Activar extensión",
|
||||
"failed": "No se pudo solicitar el estado",
|
||||
"loading": "Esperando que instales la extensión",
|
||||
"outdated": "La versión de la extensión es muy antigua",
|
||||
"success": "¡La extensión está funcionando como se esperaba!"
|
||||
},
|
||||
"submit": "Continuar",
|
||||
"title": "Vamos a empezar con la extensión"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "Volver atrás",
|
||||
"explainer": "Con el método de proxy, puede obtener una my buena calidad de las transmisiones creando un proxy propio.",
|
||||
"input": {
|
||||
"errorConnection": "No se pudo conectar al proxy",
|
||||
"errorInvalidUrl": "URL no válida",
|
||||
"errorNotProxy": "Esperaba un proxy pero obtuve un sitio web",
|
||||
"label": "URL del Proxy",
|
||||
"placeholder": "https://"
|
||||
},
|
||||
"link": "Aprender a crear un proxy",
|
||||
"submit": "Enviar proxy",
|
||||
"title": "Vamos a crear un nuevo proxy"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "Para conseguir las mejores transmisiones, necesitarás elegir que método de transmisión quieres usar.",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "No quiero buena calidad en las transmisiones,<0 /> <1>usar la configuración por defecto</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "Instalar extensión",
|
||||
"description": "Instala la extensión de navegador y gana acceso a las mejore fuentes.",
|
||||
"quality": "La mejor calidad",
|
||||
"title": "Extensión de navegador"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "Configurar proxy",
|
||||
"description": "Configura un proxy en tan solo 5 minutos y obtén acceso a buenas fuentes.",
|
||||
"quality": "Buena calidad",
|
||||
"title": "Proxy personalizado"
|
||||
}
|
||||
},
|
||||
"title": "Vamos a configurar movie-web"
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "Cerrar"
|
||||
},
|
||||
@ -182,7 +246,7 @@
|
||||
"downloadPlaylist": "Descargar lista de reproducción",
|
||||
"downloadSubtitle": "Descargar subtítulo actual",
|
||||
"downloadVideo": "Descargar vídeo",
|
||||
"hlsDisclaimer": "Las descargas se realizan directamente del proveedor. movie-web no tiene control sobre cómo se proporcionan las descargas. Tenga en cuenta que está descargando una lista de reproducción HLS, dirigida a usuarios familiarizados con la transmisión multimedia avanzada.",
|
||||
"hlsDisclaimer": "Las descargas se realizan directamente del proveedor. movie-web no tiene control sobre cómo se proporcionan las descargas. <br /><br />Tenga en cuenta que está descargando una lista de reproducción HLS, <bold>dirigida a usuarios familiarizados con la transmisión multimedia avanzada.</bold> Prueba con diferentes fuentes para diferentes formatos.",
|
||||
"onAndroid": {
|
||||
"1": "Para descargar en Android, haz clic en el botón de descarga y luego, en la nueva página, <bold>mantén presionado</bold> el vídeo y selecciona <bold>guardar</bold>.",
|
||||
"shortTitle": "Descargar / Android",
|
||||
@ -263,6 +327,17 @@
|
||||
"text": "No ha sido posible cargar la metadata de la API, por favor, comprueba tu conexión a internet.",
|
||||
"title": "No ha sido posible cargar los metadatos de la API"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "Eliminado",
|
||||
"text": "Este contenido no va a estar disponible debido a un aviso de eliminación o un reclamo de derechos de autor.",
|
||||
"title": "El contenido ha sido eliminado"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "Permisos insuficientes",
|
||||
"button": "Usar extensión",
|
||||
"text": "Tienes la extensión de navegador, pero necesitamos tu permiso para empezar a usarla.",
|
||||
"title": "Configura la extensión"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "Error",
|
||||
"homeButton": "Ir al inicio",
|
||||
@ -390,24 +465,49 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "Si deseas conectarte a un backend personalizado para almacenar tus datos, habilita esto y proporciona la URL.",
|
||||
"description": "Si deseas conectarte a un backend personalizado para almacenar tus datos, habilita esto y proporciona la URL. <0>Instrucciones.</0>",
|
||||
"label": "Servidor personalizado",
|
||||
"urlLabel": "URL del servidor personalizado"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "Configurar",
|
||||
"errorStatus": {
|
||||
"description": "Parece que hay uno o más items en esta configuración que requieren de tu atención.",
|
||||
"title": "Algo necesita de tu atención"
|
||||
},
|
||||
"itemError": "Hay algo que no fue bien con esta configuración. Ve otra vez a la configuración para solucionarlo.",
|
||||
"items": {
|
||||
"default": "Configuración por defecto",
|
||||
"extension": "Extensión",
|
||||
"proxy": "Proxy personalizado"
|
||||
},
|
||||
"redoSetup": "Rehacer configuración",
|
||||
"successStatus": {
|
||||
"description": "Todo lo necesario está en su sitio para que empieces a ver tu contenido favorito.",
|
||||
"title": "Todo está configurado!"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "Haga clic en el botón a la derecha para iniciar el proceso de configuración.",
|
||||
"title": "No has pasado por la configuración"
|
||||
}
|
||||
},
|
||||
"title": "Conexiones",
|
||||
"workers": {
|
||||
"addButton": "Agregar nuevo worker",
|
||||
"description": "Para que la aplicación funcione, todo el tráfico se enruta a través de proxies. Habilita esto si quieres usar tus propios workers.",
|
||||
"description": "Para que la aplicación funcione, todo el tráfico se enruta a través de proxies. Habilita esto si quieres usar tus propios workers. <0>Instrucciones.</0>",
|
||||
"emptyState": "Aún no hay workers, agrega uno a continuación",
|
||||
"label": "Usar proxy workers personalizados",
|
||||
"urlLabel": "URL de los workers",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"preferences": {
|
||||
"language": "Idioma de la aplicación",
|
||||
"languageDescription": "Idioma aplicado a toda la aplicación.",
|
||||
"title": "Idioma"
|
||||
"thumbnail": "Generar miniaturas",
|
||||
"thumbnailDescription": "La mayor parte del tiempo, los videos no tienen miniaturas. Puedes activar esta configuración para generarlas sobre la marcha, pero pueden realentizar tu video.",
|
||||
"thumbnailLabel": "Generar miniaturas",
|
||||
"title": "Preferencias"
|
||||
},
|
||||
"reset": "Restablecer",
|
||||
"save": "Guardar",
|
||||
|
@ -404,11 +404,6 @@
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"language": "Rakenduse keel",
|
||||
"languageDescription": "Keel on rakendatud kogu rakendusele.",
|
||||
"title": "Lokaal"
|
||||
},
|
||||
"reset": "Lähtesta",
|
||||
"save": "Salvesta",
|
||||
"sidebar": {
|
||||
|
@ -26,19 +26,19 @@
|
||||
"deviceNamePlaceholder": "تلفن شخصی",
|
||||
"generate": {
|
||||
"description": "جمله امنیتی شما به عنوان نام کاربری و رمز عبور عمل میکند. آن را در جایی ذخیره کنید چون برای ورود به آن نیاز دارید",
|
||||
"next": "جمله امنیتی خود را ذخیره کردهام",
|
||||
"passphraseFrameLabel": "جمله امنیتی",
|
||||
"title": "جمله امنیتی شما"
|
||||
"next": "عبارت عبور امنیتی خود را ذخیره کردهام",
|
||||
"passphraseFrameLabel": "عبارت عبور امنیتی",
|
||||
"title": "عبارت عبور امنیتی شما"
|
||||
},
|
||||
"hasAccount": "حساب کاربری دارید؟ <0>اینجا وارد شوید.</0>",
|
||||
"login": {
|
||||
"description": "لطفاً جمله امنیتی خود را وارد کنید تا وارد حساب کاربری شوید",
|
||||
"description": "لطفاً عبارت عبور امنیتی خود را وارد کنید تا وارد حساب کاربری شوید",
|
||||
"deviceLengthError": "لطفا نامی برای دستگاه انتخاب کنید",
|
||||
"passphraseLabel": "جمله امنیتی 12 کلمهای",
|
||||
"passphrasePlaceholder": "جمله امنیتی",
|
||||
"passphrasePlaceholder": "عبارت عبور امنیتی",
|
||||
"submit": "ورود",
|
||||
"title": "ورود به حساب کاربری",
|
||||
"validationError": "جمله امنیتی نادرست یا ناقص است"
|
||||
"validationError": "عبارت عبور امنیتی نادرست یا ناقص است"
|
||||
},
|
||||
"register": {
|
||||
"information": {
|
||||
@ -52,7 +52,7 @@
|
||||
},
|
||||
"trust": {
|
||||
"failed": {
|
||||
"text": "آیا از صحت تنظیمات مطمئن هستید؟",
|
||||
"text": "درست پیکربندیش کردی؟",
|
||||
"title": "مشکلی در ارتباط با سرور رخ داده"
|
||||
},
|
||||
"host": "شما در حال اتصال به <0>{{hostname}}</0> هستید - لطفا قبل از ایجاد حساب کاربری خود از اعتماد به آن اطمینان حاصل کنید",
|
||||
@ -61,40 +61,41 @@
|
||||
"yes": "بله اعتماد دارم"
|
||||
},
|
||||
"verify": {
|
||||
"description": "لطفا جمله امنیتی که به شما داده شده را مجدد وارد تا کنید تا حساب کاربری ساخته شود",
|
||||
"invalidData": "اطلاعات نادرست است",
|
||||
"noMatch": "جمله امنیتی مطابقت ندارد",
|
||||
"passphraseLabel": "جمله امنیتی 12 کلمه ای شما",
|
||||
"description": "لطفا عبارت عبور که به شما داده شده را مجدد وارد تا کنید تا حساب کاربری ساخته شود",
|
||||
"invalidData": "داده نامعتبر است",
|
||||
"noMatch": "عبارت عبور مطابقت ندارد",
|
||||
"passphraseLabel": "عبارت عبور 12 کلمه ای شما",
|
||||
"recaptchaFailed": "اعتبارسنجی ReCaptcha ناموفق بود",
|
||||
"register": "ساخت حساب کاربری",
|
||||
"title": "جمله امنیتی خود را تایید کنید"
|
||||
"title": "عبارت عبور خود را تایید کنید"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"badge": "مشکلی پیش آمده",
|
||||
"details": "جزئیات خطا",
|
||||
"reloadPage": "صفحه را ریلود کنید",
|
||||
"reloadPage": "صفحه را دوباره بارگذاری کنید",
|
||||
"showError": "نمایش جزئیات خطا",
|
||||
"title": "مشکلی پیش آمده!"
|
||||
"title": "با خطا مواجه شدیم!"
|
||||
},
|
||||
"footer": {
|
||||
"legal": {
|
||||
"disclaimer": "سلب مسئولیت",
|
||||
"disclaimerText": "مووی-وب هیچ فایلی را میزبانی نمیکند، صرفاً به سرویسهای شخص ثالث لینک میدهد. مسائل قانونی باید با میزبانها و ارائهدهندگان فایل مطرح شود. مووی-وب مسئولیتی در قبال هیچ فایل رسانهای که توسط ارائهدهندگان ویدیو نشان داده میشود ندارد."
|
||||
"disclaimerText": "مووی-وب هیچ فایلی را میزبانی نمیکند، صرفاً به سرویسهای ثالث لینک میدهد. مسائل قانونی باید با میزبانها و ارائهدهندگان فایل مطرح شود. مووی-وب مسئولیتی در قبال هیچ فایل رسانهای که توسط ارائهدهندگان ویدیو نشان داده میشود ندارد."
|
||||
},
|
||||
"links": {
|
||||
"discord": "دیسکورد",
|
||||
"dmca": "DMCA",
|
||||
"github": "گیت هاب"
|
||||
},
|
||||
"tagline": "فیلم و سریال مورد علاقهتان را با این برنامه استریم منبع باز تماشا کنید."
|
||||
"tagline": "فیلم و سریال مورد علاقهتان را با این برنامه استریم متن باز تماشا کنید."
|
||||
},
|
||||
"global": {
|
||||
"name": "مووی-وب",
|
||||
"pages": {
|
||||
"about": "درباره ما",
|
||||
"about": "درباره",
|
||||
"dmca": "DMCA",
|
||||
"login": "ورود",
|
||||
"onboarding": "راه اندازی",
|
||||
"pagetitle": "{{title}} - مووی-وب",
|
||||
"register": "ثبت نام",
|
||||
"settings": "تنظیمات"
|
||||
@ -105,36 +106,36 @@
|
||||
"sectionTitle": "علاقه مندی ها"
|
||||
},
|
||||
"continueWatching": {
|
||||
"sectionTitle": "ادامه تماشا"
|
||||
"sectionTitle": "به تماشا ادامه دهید"
|
||||
},
|
||||
"mediaList": {
|
||||
"stopEditing": "توقف ویرایش"
|
||||
"stopEditing": "ویرایش را متوقف کنید"
|
||||
},
|
||||
"search": {
|
||||
"allResults": "همه چیزی بود که داشتیم!",
|
||||
"failed": "چیزی پیدا نشد، دوباره تلاش کنید!",
|
||||
"loading": "در حال جستجو...",
|
||||
"noResults": "متاسفانه چیزی پیدا نکردیم!",
|
||||
"loading": "در حال بارگذاری...",
|
||||
"noResults": "چیزی پیدا نکردیم!",
|
||||
"placeholder": "چه میخواهید تماشا کنید؟",
|
||||
"sectionTitle": "نمایش نتایج"
|
||||
"sectionTitle": "نتایج جستجو"
|
||||
},
|
||||
"titles": {
|
||||
"day": {
|
||||
"default": "امروز چه میخواهید تماشا کنید؟",
|
||||
"default": "دوست دارید امروز بعدازظهر چه چیزی تماشا کنید؟",
|
||||
"extra": [
|
||||
"به دنبال ماجراجویی هستید؟ \"ژوراسیک پارک\" انتخابی عالی است."
|
||||
"به دنبال ماجراجویی هستید؟ \"پارک ژوراسیک\" انتخابی عالی است."
|
||||
]
|
||||
},
|
||||
"morning": {
|
||||
"default": "امروز چه میخواهید تماشا کنید؟",
|
||||
"default": "دوست دارید امروز صبح چه چیزی تماشا کنید؟",
|
||||
"extra": [
|
||||
"فیلم \"پیش از طلوع\" رو میتوانم پیشنهاد کنم"
|
||||
"شنیدم فیلم \"پیش از طلوع\" عالیه"
|
||||
]
|
||||
},
|
||||
"night": {
|
||||
"default": "امشب چه میخواهید تماشا کنید؟",
|
||||
"default": "دوست دارید امشب چه چیزی تماشا کنید؟",
|
||||
"extra": [
|
||||
"روز سختی را گذرانده اید؟ شنیده ام که \"جن گیر\" فیلم خوبی است."
|
||||
"خسته اید؟ شنیده ام که \"جن گیر\" فیلم خوبی است."
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -165,6 +166,69 @@
|
||||
"message": "همه جا را جستجو کردیم: زیر سطلها، در کمد، پشت پروکسی، اما در نهایت نتوانستیم صفحهای که به دنبال آن هستید را پیدا کنیم.",
|
||||
"title": "نتواستیم صفحه را پیدا کنیم"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "لغو کنید",
|
||||
"confirm": "از تنظیمات پیش فرض استفاده کنید",
|
||||
"description": "راهاندازی پیشفرض بهترین جریانها را ندارد و میتواند به طور غیرقابل تحملی کند باشد.",
|
||||
"title": "مطمئنی؟"
|
||||
},
|
||||
"extension": {
|
||||
"back": "برگرد",
|
||||
"explainer": "با استفاده از افزونه مرورگر، میتوانید بهترین جریانهای ارائه شده را دریافت کنید. فقط با یک نصب ساده.",
|
||||
"explainerIos": "متأسفانه افزونه مرورگر در iOS پشتیبانی نمیشود، برای انتخاب گزینه دیگری <bold>Go back</bold> را فشار دهید.",
|
||||
"extensionHelp": "اگر برنامه افزودنی را نصب کرده اید اما شناسایی نشده است.، <bold>افزونه را از طریق منوی افزونه مرورگر خود باز کنید</bold> و مراحل روی صفحه را دنبال کنید.",
|
||||
"linkChrome": "افزونه کروم را نصب کنید",
|
||||
"linkFirefox": "افزونه فایرفاکس را نصب کنید",
|
||||
"notDetecting": "روی کروم نصب شده است، اما سایت آن را شناسایی نمی کند؟ سعی کنید صفحه را دوباره بارگیری کنید!",
|
||||
"notDetectingAction": "بارگذاری مجدد صفحه",
|
||||
"status": {
|
||||
"disallowed": "برنامه افزودنی برای این صفحه فعال نیست",
|
||||
"disallowedAction": "افزونه را فعال کنید",
|
||||
"failed": "درخواست وضعیت ناموفق بود",
|
||||
"loading": "منتظر نصب افزونه هستیم",
|
||||
"outdated": "نسخه افزونه خیلی قدیمی است",
|
||||
"success": "برنامه افزودنی همانطور که انتظار می رود کار می کند!"
|
||||
},
|
||||
"submit": "ادامه دهید",
|
||||
"title": "بیایید با یک افزونه شروع کنیم"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "برگرد",
|
||||
"explainer": "با روش پروکسی می توانید با ساخت یک پراکسی سلف سرویس استریم های با کیفیت عالی دریافت کنید.",
|
||||
"input": {
|
||||
"errorConnection": "نمی توان به پروکسی وصل شد",
|
||||
"errorInvalidUrl": "لینک معتبر نیست",
|
||||
"errorNotProxy": "انتظار یک پروکسی داشتم اما یک وب سایت دریافت کردم",
|
||||
"label": "لینک پروکسی",
|
||||
"placeholder": "https://"
|
||||
},
|
||||
"link": "آموزش ساخت پروکسی",
|
||||
"submit": "پروکسی را ثبت کنید",
|
||||
"title": "بیایید یک پروکسی جدید بسازیم"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "برای دریافت بهترین استریم های ممکن، باید روش پخش جریانی را که می خواهید استفاده کنید، انتخاب کنید.",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "من پخش جریانی با کیفیت خوب نمیخواهم،<0 /> <1>از تنظیمات پیشفرض استفاده کنید</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "افزونه را نصب کنید",
|
||||
"description": "افزونه مرورگر را نصب کنید و به بهترین منابع دسترسی پیدا کنید.",
|
||||
"quality": "بهترین کیفیت",
|
||||
"title": "افزونه مرورگر"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "راه اندازی پروکسی",
|
||||
"description": "یک پروکسی را فقط در 5 دقیقه راه اندازی کنید و به منابع عالی دسترسی پیدا کنید.",
|
||||
"quality": "کیفیت خوب",
|
||||
"title": "پروکسی سفارشی"
|
||||
}
|
||||
},
|
||||
"title": "بیایید با فیلم وب راه اندازی کنیم"
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "بستن"
|
||||
},
|
||||
@ -174,7 +238,7 @@
|
||||
"short": "بازگشت"
|
||||
},
|
||||
"casting": {
|
||||
"enabled": "در حال نمایش روی دستگاه..."
|
||||
"enabled": "ارسال روی دستگاه..."
|
||||
},
|
||||
"menus": {
|
||||
"downloads": {
|
||||
@ -182,7 +246,7 @@
|
||||
"downloadPlaylist": "دانلود لیست پخش",
|
||||
"downloadSubtitle": "دانلود زیرنویس فعلی",
|
||||
"downloadVideo": "دانلود ویدیو",
|
||||
"hlsDisclaimer": "دانلود ها به طور مستقیم از ارائه دهنده گرفته شده است. مووی-وب کنترلی بر نحوه ارائه دانلود ها ندارد. لطفا توجه داشته باشید که شما در حال دانلود یک لیست پخش HLS هستید، این برای کاربرانی هست که آشنایی بیشتری با استریم رسانه ها دارند.",
|
||||
"hlsDisclaimer": "دانلودها مستقیماً از ارائه دهنده گرفته می شوند. movie-web کنترلی بر نحوه ارائه دانلودها ندارد.<br /><br />لطفاً توجه داشته باشید که در حال دانلود یک لیست پخش HLS هستید، <bold>اگر با فرمت های پخش جریانی پیشرفته آشنایی ندارید، دانلود آن توصیه نمی شود. </bold>. منابع مختلف را برای فرمت های مختلف امتحان کنید.",
|
||||
"onAndroid": {
|
||||
"1": "برای دانلود در اندروید، روی دکمه دانلود کلیک کنید و سپس در صفحه جدید، روی ویدیو <bold>ضربه بزنید و نگه دارید</bold>، سپس <bold>ذخیره</bold> را انتخاب کنید.",
|
||||
"shortTitle": "دانلود / اندروید",
|
||||
@ -202,11 +266,12 @@
|
||||
},
|
||||
"episodes": {
|
||||
"button": "قسمت ها",
|
||||
"emptyState": "هنوز هیچ قسمتی در این فصل منتشر نشده، بعدا سر بزنید!",
|
||||
"emptyState": "هنوز هیچ قسمتی در این فصل وجود ندارد، بعدا سر بزنید!",
|
||||
"episodeBadge": "قسمت {{episode}}",
|
||||
"loadingError": "مشکلی در دریافت قسمت ها پیش آمده",
|
||||
"loadingList": "در حال دریافت...",
|
||||
"loadingTitle": "در حال دریافت..."
|
||||
"loadingError": "خطایی در دریافت قسمت ها رخ داده",
|
||||
"loadingList": "در حال بارگذاری...",
|
||||
"loadingTitle": "در حال بارگذاری...",
|
||||
"unairedEpisodes": "یک یا چند قسمت در این فصل غیرفعال شده است به دلیل اینکه هنوز پخش نشده است."
|
||||
},
|
||||
"playback": {
|
||||
"speedLabel": "سرعت پخش",
|
||||
@ -214,13 +279,13 @@
|
||||
},
|
||||
"quality": {
|
||||
"automaticLabel": "کیفیت خودکار",
|
||||
"hint": "شما می توانید با <0>تغییر منبع</0> گزینه های مختلف کیفیت را به دست آورید.",
|
||||
"hint": "شما می توانید با <0>تغییر منبع</0> به گزینه های مختلف کیفیت دسترسی داشته باشید.",
|
||||
"iosNoQuality": "با توجه به محدودیت های تعریف شده توسط اپل، انتخاب کیفیت در iOS برای این منبع در دسترس نیست. شما می توانید با <0>تغییر منبع</0> گزینه های مختلف کیفیت را به دست آورید.",
|
||||
"title": "کیفیت"
|
||||
},
|
||||
"settings": {
|
||||
"downloadItem": "دانلود",
|
||||
"enableSubtitles": "روشن کردن زیرنویس",
|
||||
"enableSubtitles": "فعال کردن زیرنویس",
|
||||
"experienceSection": "تجربه مشاهده",
|
||||
"playbackItem": "تنظیمات پخش",
|
||||
"qualityItem": "کیفیت",
|
||||
@ -234,32 +299,47 @@
|
||||
"title": "دریافت اطلاعات ناموفق بود"
|
||||
},
|
||||
"noEmbeds": {
|
||||
"text": "نتوانستیم اطلاعات را پیدا کنیم، لطفا منبعی دیگر را امتحان کنید.",
|
||||
"text": "نتوانستیم اطلاعات را پیدا کنیم، لطفا منبع دیگری را امتحان کنید.",
|
||||
"title": "اطلاعات پیدا نشد"
|
||||
},
|
||||
"noStream": {
|
||||
"text": "فیلم یا سریال شما در این منبع وجود ندارد.",
|
||||
"title": "استریمی وجود ندارد"
|
||||
},
|
||||
"title": "منبع",
|
||||
"title": "منابع",
|
||||
"unknownOption": "ناشناخته"
|
||||
},
|
||||
"subtitles": {
|
||||
"customChoice": "انتخاب فایل زیرنویس",
|
||||
"customChoice": "انتخاب زیرنویس از فایل",
|
||||
"customizeLabel": "شخصی سازی",
|
||||
"offChoice": "خاموش",
|
||||
"settings": {
|
||||
"backlink": "تنظیمات زیرنویس",
|
||||
"backlink": "زیرنویس سفارشی",
|
||||
"delay": "تاخیر زیرنویس",
|
||||
"fixCapitals": "حروف اول بزرگ (انگلیسی)"
|
||||
"fixCapitals": "تصحیح حروف اول بزرگ (انگلیسی)"
|
||||
},
|
||||
"title": "زیرنویس ها",
|
||||
"unknownLanguage": "ناشناخته"
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"api": {
|
||||
"text": "داده API بارگیری نشد، لطفا اتصال اینترنت خود را بررسی کنید.",
|
||||
"title": "داده API بارگیری نشد"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "حذف شد",
|
||||
"text": "این رسانه به دلیل اعلامیه حذف یا ادعای حق نسخهبرداری دیگر در دسترس نیست.",
|
||||
"title": "رسانه حذف شده است"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "مجوز وجود ندارد",
|
||||
"button": "از افزونه استفاده کنید",
|
||||
"text": "شما افزونه مرورگر را دارید، اما برای شروع استفاده از برنامه افزودنی به اجازه شما نیاز داریم.",
|
||||
"title": "افزونه را پیکربندی کنید"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "ناموفق بود",
|
||||
"badge": "ناموفق",
|
||||
"homeButton": "بازگشت به خانه",
|
||||
"text": "نتوانستیم اطلاعات را از TMDB دریافت کنیم. ممکن است TMDB موقتا غیرفعال باشد یا توسط ارائه دهنده شما فیلتر باشد.",
|
||||
"title": "اطلاعات دریافت نشد"
|
||||
@ -268,7 +348,7 @@
|
||||
"badge": "پیدا نشد",
|
||||
"homeButton": "بازگشت به خانه",
|
||||
"text": "فیلم یا سریالی که شما به دنبالش هستید رو پیدا نکردیم. ممکن است حذف شده باشد یا لینک این صفحه دستکاری شده باشد.",
|
||||
"title": "رسانه ای پیدا نشد."
|
||||
"title": "محتوا ای پیدا نشد."
|
||||
}
|
||||
},
|
||||
"nextEpisode": {
|
||||
@ -278,7 +358,7 @@
|
||||
"playbackError": {
|
||||
"badge": "مشکلی در پخش به وجود آمده",
|
||||
"errors": {
|
||||
"errorAborted": "دریافت رسانه توسط لغو شد.",
|
||||
"errorAborted": "دریافت رسانه توسط کاربر لغو شد.",
|
||||
"errorDecode": "با وجود اینکه قبلا مشخص شده بود که قابل استفاده است، یک خطا در هنگام تلاش برای رمزگشایی رسانه رخ داد که باعث مشکل شد.",
|
||||
"errorGenericMedia": "رسانه ناشناخته است.",
|
||||
"errorNetwork": "با وجود اینکه قبلا در دسترس بود، نوعی خطای شبکه رخ داد که مانع از دریافت رسانه ها شد.",
|
||||
@ -307,6 +387,12 @@
|
||||
"remaining": "{{timeLeft}} مشاهده شده • {{timeFinished, datetime}} دیگر تمام میشود",
|
||||
"shortRegular": "{{timeWatched}}",
|
||||
"shortRemaining": "-{{timeLeft}}"
|
||||
},
|
||||
"turnstile": {
|
||||
"description": "لطفا انسانیت خود را با تموم کردن چالش های کپچا به طور درست ثابت کنید. برای ایمن نگه داشتن مووی-وب!",
|
||||
"error": "انسانیت شما تأیید نشد. لطفا دوباره تلاش کنید.",
|
||||
"title": "ما باید تایید کنیم که شما انسان هستید.",
|
||||
"verifyingHumanity": "تایید کردن انسانیت شما..."
|
||||
}
|
||||
},
|
||||
"screens": {
|
||||
@ -360,7 +446,7 @@
|
||||
"userIcon": "نماد کاربری"
|
||||
},
|
||||
"register": {
|
||||
"cta": "شروع",
|
||||
"cta": "شروع کنید",
|
||||
"text": "پیشرفت تماشای خود را بین دستگاهها به اشتراک بگذارید و آنها را با یکدیگر همگام کنید.",
|
||||
"title": "همگام سازی"
|
||||
},
|
||||
@ -379,24 +465,49 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "اگر می خواهید برای ذخیره داده های خود به یک بک-اند سفارشی متصل شوید، این را فعال و لینک را وارد کنید.",
|
||||
"description": "اگر میخواهید به یک بک-اند سفارشی برای ذخیره داده متصل شوید، با فعال و ارائه کردن این لینک ادامه دهید. <0>دستورالعمل ها.</0>",
|
||||
"label": "سرور سفارشی",
|
||||
"urlLabel": "لینک سرور سفارشی"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "راه اندازی را انجام دهید",
|
||||
"errorStatus": {
|
||||
"description": "به نظر می رسد که یک یا چند مورد در این تنظیم نیاز به توجه شما دارد.",
|
||||
"title": "چیزی به توجه شما نیاز دارد"
|
||||
},
|
||||
"itemError": "مشکلی در این تنظیم وجود دارد. برای رفع آن دوباره تنظیمات را انجام دهید.",
|
||||
"items": {
|
||||
"default": "تنظیم پیش فرض",
|
||||
"extension": "افزونه",
|
||||
"proxy": "پروکسی سفارشی"
|
||||
},
|
||||
"redoSetup": "تنظیم مجدد",
|
||||
"successStatus": {
|
||||
"description": "همه چیز برای شروع تماشای رسانه مورد علاقهتان آماده است.",
|
||||
"title": "همه چیز تنظیم شده است!"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "لطفاً روی دکمه سمت راست کلیک کنید تا فرآیند نصب شروع شود.",
|
||||
"title": "شما راهاندازی را طی نکردهاید"
|
||||
}
|
||||
},
|
||||
"title": "اتصالات",
|
||||
"workers": {
|
||||
"addButton": "اضافه کردن worker جدید",
|
||||
"description": "برای کار کردن برنامه، تمام ترافیک از طریق پروکسی ها هدایت می شود. این کار را انجام دهید اگر می خواهید از worker های خود استفاده کنید.",
|
||||
"description": "برای ایجاد عملکرد برنامه، تمام ترافیک از طریق پروکسی ها هدایت می شود. اگر میخواهید این کار انجام دهید حتما از worker های خودتان استفاده کنید. <0>دستورالعمل ها.</0>",
|
||||
"emptyState": "هنوز هیچ worker ای وجود ندارد، یکی اضافه کنید",
|
||||
"label": "استفاده از worker های پروکسی سفارشی",
|
||||
"urlLabel": "لینک worker ها",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"language": "زبان",
|
||||
"languageDescription": "زبانی در کل برنامه اعمال میشود.",
|
||||
"title": "زبان"
|
||||
"preferences": {
|
||||
"language": "زبان برنامه",
|
||||
"languageDescription": "زبان برای کل برنامه کاربردی است.",
|
||||
"thumbnail": "ایجاد تصاویر کوچک",
|
||||
"thumbnailDescription": "بیشتر اوقات، ویدیوها تصاویر کوچک ندارند. شما می توانید این تنظیم را فعال کنید تا آنها را در لحظه تولید کنید، اما آنها می توانند ویدیوی شما را کندتر کنند.",
|
||||
"thumbnailLabel": "ایجاد تصاویر کوچک",
|
||||
"title": "اولویت ها"
|
||||
},
|
||||
"reset": "بازنشانی",
|
||||
"save": "ذخیره",
|
||||
|
181
src/assets/locales/fi-FI.json
Normal file
181
src/assets/locales/fi-FI.json
Normal file
@ -0,0 +1,181 @@
|
||||
{
|
||||
"about": {
|
||||
"description": "movie-web on verkkosovellus, joka etsii suoratoistoja internetistä. Tiimi pyrkii enimmäkseen minimalistiseen lähestymistapaan sisällön kuluttamiseen.",
|
||||
"faqTitle": "Yleisiä kysymyksiä",
|
||||
"q1": {
|
||||
"body": "movie-web ei isännöi mitään sisältöä. Kun klikkaat jotain katsottavaa, valittua mediaa etsitään internetistä (latausnäytössä ja 'videolähteet'-välilehdellä näet, mitä lähdettä käytät). movie-web ei koskaan lataa mediaa, kaikki tapahtuu tämän hakumekanismin kautta.",
|
||||
"title": "Mistä sisältö tulee?"
|
||||
},
|
||||
"q2": {
|
||||
"body": "Ohjelmaa tai elokuvaa ei voi pyytää, movie-web ei hallinnoi sisältöä. Kaikki sisältö katsotaan internetin lähteistä.",
|
||||
"title": "Missä voin pyytää sarjaa tai elokuvaa?"
|
||||
},
|
||||
"q3": {
|
||||
"body": "Hakutuloksemme perustuvat The Movie Database (TMDB) -tietokantaan, ja ne näkyvät riippumatta siitä, onko sisältöä oikeasti lähteissämme.",
|
||||
"title": "Hakutuloksissa näytetään ohjelma tai elokuva. Miksi en voi toistaa sitä?"
|
||||
},
|
||||
"title": "Tietoja movie-webistä"
|
||||
},
|
||||
"actions": {
|
||||
"copied": "Kopioitu",
|
||||
"copy": "Kopioi"
|
||||
},
|
||||
"auth": {
|
||||
"createAccount": "Eikö sinulla ole vielä tiliä? <0>Luo tili.</0>",
|
||||
"deviceNameLabel": "Laitteen nimi",
|
||||
"deviceNamePlaceholder": "Henkilökohtainen puhelin",
|
||||
"generate": {
|
||||
"description": "Tunnuslauseesi toimii käyttäjätunnuksena ja salasanana. Varmista, että pidät sen turvassa, sillä sinun on annettava se kirjautuaksesi tilillesi",
|
||||
"next": "Olen tallentanut tunnuslauseeni",
|
||||
"passphraseFrameLabel": "Tunnuslause",
|
||||
"title": "Sinun tunnuslause"
|
||||
},
|
||||
"hasAccount": "Onko sinulla jo tili? <0>Kirjaudu sisään tästä.</0>",
|
||||
"login": {
|
||||
"description": "Anna tunnuslauseesi kirjautuaksesi tilillesi",
|
||||
"deviceLengthError": "Anna laitteen nimi",
|
||||
"passphraseLabel": "12-sanainen tunnuslause",
|
||||
"passphrasePlaceholder": "Tunnuslause",
|
||||
"submit": "Kirjaudu sisään",
|
||||
"title": "Kirjaudu tilillesi",
|
||||
"validationError": "Väärä tai puutteellinen tunnuslause"
|
||||
},
|
||||
"register": {
|
||||
"information": {
|
||||
"color1": "Profiilin väri yksi",
|
||||
"color2": "Profiilin väri kaksi",
|
||||
"header": "Anna laitteellesi nimi ja valitse haluamasi värit ja käyttäjäkuvake",
|
||||
"icon": "Käyttäjäkuvake",
|
||||
"next": "Seuraava",
|
||||
"title": "Tilitiedot"
|
||||
}
|
||||
},
|
||||
"trust": {
|
||||
"failed": {
|
||||
"text": "Oletko määrittänyt sen oikein?",
|
||||
"title": "Palvelimeen ei saada yhteyttä"
|
||||
},
|
||||
"host": "Olet muodostamassa yhteyttä <0>{{hostname}}</0> - vahvista, että luotat siihen ennen kuin luot tilin",
|
||||
"no": "Mene takaisin",
|
||||
"title": "Luotatko tähän palvelimeen?",
|
||||
"yes": "Luotan tähän palvelimeen"
|
||||
},
|
||||
"verify": {
|
||||
"description": "Anna aikaisemmin saamasi tunnuslause vahvistaaksesi, että olet tallentanut sen ja luodaksesi tilisi",
|
||||
"invalidData": "Tiedot eivät kelpaa",
|
||||
"noMatch": "Tunnuslause ei täsmää",
|
||||
"passphraseLabel": "12-sanainen tunnuslauseesi",
|
||||
"recaptchaFailed": "ReCaptcha-tarkistus epäonnistui",
|
||||
"register": "Luo tili",
|
||||
"title": "Vahvista tunnuslauseesi"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"badge": "Se hajosi",
|
||||
"details": "Virheen tiedot",
|
||||
"reloadPage": "Lataa sivu uudelleen",
|
||||
"showError": "Näytä virheen tiedot",
|
||||
"title": "Havaitsimme virheen!"
|
||||
},
|
||||
"footer": {
|
||||
"legal": {
|
||||
"disclaimer": "Vastuuvapauslauseke",
|
||||
"disclaimerText": "movie-web ei isännöi tiedostoja, se vain linkittää kolmannen osapuolen palveluihin. Lakiasioista tulee ottaa yhteyttä tiedostoisäntään ja palveluntarjoajiin. movie-web ei ole vastuussa videontarjoajien näyttämistä mediatiedostoista."
|
||||
},
|
||||
"links": {
|
||||
"discord": "Discord",
|
||||
"dmca": "DMCA",
|
||||
"github": "GitHub"
|
||||
},
|
||||
"tagline": "Katso suosikkiohjelmiasi ja elokuviasi tällä avoimen lähdekoodin suoratoistosovelluksella."
|
||||
},
|
||||
"global": {
|
||||
"name": "movie-web",
|
||||
"pages": {
|
||||
"about": "Meistä",
|
||||
"dmca": "DMCA",
|
||||
"login": "Kirjaudu sisään",
|
||||
"pagetitle": "{{title}} - movie-web",
|
||||
"register": "Rekisteröidy",
|
||||
"settings": "Asetukset"
|
||||
}
|
||||
},
|
||||
"home": {
|
||||
"bookmarks": {
|
||||
"sectionTitle": "Kirjanmerkit"
|
||||
},
|
||||
"continueWatching": {
|
||||
"sectionTitle": "Jatka katselua"
|
||||
},
|
||||
"mediaList": {
|
||||
"stopEditing": "Lopeta muokkaaminen"
|
||||
},
|
||||
"search": {
|
||||
"allResults": "Siinä kaikki mitä meillä on!",
|
||||
"failed": "Mediaa ei löytynyt, yritä uudelleen!",
|
||||
"loading": "Ladataan...",
|
||||
"noResults": "Emme löytäneet mitään!",
|
||||
"placeholder": "Mitä haluat katsoa?",
|
||||
"sectionTitle": "Hakutulokset"
|
||||
},
|
||||
"titles": {
|
||||
"day": {
|
||||
"default": "Mitä haluaisit katsoa tänä iltapäivänä?",
|
||||
"extra": [
|
||||
"Onko seikkailunhaluinen olo? Jurassic Park saattaa olla täydellinen valinta."
|
||||
]
|
||||
},
|
||||
"morning": {
|
||||
"default": "Mitä haluaisit katsoa tänä aamuna?",
|
||||
"extra": [
|
||||
"Kuulen, että Rakkautta ennen aamua (Before Sunrise) on hyvä"
|
||||
]
|
||||
},
|
||||
"night": {
|
||||
"default": "Mitä haluaisit katsoa tänä iltana?",
|
||||
"extra": [
|
||||
"Väsynyt? Kuulin, että Manaaja (The Exorcist) on hyvä."
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"media": {
|
||||
"episodeDisplay": "K{{season}} J{{episode}}",
|
||||
"types": {
|
||||
"movie": "Elokuva",
|
||||
"show": "Sarja"
|
||||
}
|
||||
},
|
||||
"navigation": {
|
||||
"banner": {
|
||||
"offline": "Tarkista Internet-yhteytesi"
|
||||
},
|
||||
"menu": {
|
||||
"about": "Meistä",
|
||||
"donation": "Lahjoita",
|
||||
"logout": "Kirjaudu ulos",
|
||||
"register": "Synkronoi pilveen",
|
||||
"settings": "Asetukset",
|
||||
"support": "Tuki"
|
||||
}
|
||||
},
|
||||
"notFound": {
|
||||
"badge": "Ei löydetty",
|
||||
"goHome": "Takaisin kotiin",
|
||||
"message": "Etsimme kaikkialta: roskakorien alta, kaapista, välityspalvelimen takaa, mutta emme lopulta löytäneet etsimääsi sivua.",
|
||||
"title": "Sivua ei löytynyt"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "Peruuta",
|
||||
"confirm": "Käytä oletuksia",
|
||||
"description": "Oletuksissa ei ole parhaita suoratoistoja ja se voi olla sietämättömän hidasta.",
|
||||
"title": "Oletko varma?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "Mene takaisin",
|
||||
"explainer": "Käyttämällä selainlaajennusta voit saada parhaat tarjoamamme suoratoistot. Yksinkertaisella asennuksella.",
|
||||
"explainerIos": "Valitettavasti selainlaajennusta ei tueta iOS:ssä. Valitse toinen vaihtoehto painamalla <bold>Palaa</bold>."
|
||||
}
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@
|
||||
"title": "Où puis-je demander une série ou un film ?"
|
||||
},
|
||||
"q3": {
|
||||
"body": "Nos résultats de recherche sont fournis et affichés par The Movie Database (TMDB), que nos sources soient propriétaires du contenu ou non.",
|
||||
"body": "Que nos sources soient propriétaires du contenu ou non, The Movie Database (TMDB) fournit et affiche nos résultats de recherche.",
|
||||
"title": "Les résultats de la recherche affichent l'émission ou le film, pourquoi ne puis-je pas le lire ?"
|
||||
},
|
||||
"title": "À propos de movie-web"
|
||||
@ -35,7 +35,7 @@
|
||||
"description": "Veuillez fournir votre passphrase pour accéder à votre compte",
|
||||
"deviceLengthError": "Veuillez saisir un nom d'appareil",
|
||||
"passphraseLabel": "Passphrase de 12 mots",
|
||||
"passphrasePlaceholder": "Passphrase",
|
||||
"passphrasePlaceholder": "Phrase secrète",
|
||||
"submit": "Se connecter",
|
||||
"title": "Se connecter à votre compte",
|
||||
"validationError": "Passphrase incorrecte ou incomplete"
|
||||
@ -95,6 +95,7 @@
|
||||
"about": "À propos",
|
||||
"dmca": "DMCA",
|
||||
"login": "Se connecter",
|
||||
"onboarding": "Setup",
|
||||
"pagetitle": "{{title}} - movie-web",
|
||||
"register": "Créer un compte",
|
||||
"settings": "Paramètres"
|
||||
@ -165,6 +166,69 @@
|
||||
"message": "Nous avons cherché partout : sous les poubelles, dans le placard, derrière le proxy, mais nous n'avons finalement pas trouvé la page que vous cherchez.",
|
||||
"title": "Impossible de trouver cette page"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "Annuler",
|
||||
"confirm": "Utiliser la configuration de départ",
|
||||
"description": "La configuration par défaut n'offre pas les meilleurs flux et peut être insupportablement lente.",
|
||||
"title": "Es-tu sûr ?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "Retour en arrière",
|
||||
"explainer": "En utilisant l'extension de navigateur, vous pouvez obtenir les meilleurs flux que nous avons à offrir. Avec juste une simple installation.",
|
||||
"explainerIos": "Malheureusement, l'extension web n'est pas prise en charge sur iOS, appuyez sur <bold> Retour en arrière </bold> pour choisir une autre option.",
|
||||
"extensionHelp": "Si vous avez installé l'extension mais qu'elle n'est pas détectée, <bold>ouvrez l'extension via le menu des extensions de votre navigateur</bold> et suivez les étapes à l'écran.",
|
||||
"linkChrome": "Installer l'extension Chrome",
|
||||
"linkFirefox": "Installer l'extension Firefox",
|
||||
"notDetecting": "L'extension est installée sur Chrome mais le site ne la détecte pas ? Essayez de rafraîchir la page !",
|
||||
"notDetectingAction": "Rafraîchir la page",
|
||||
"status": {
|
||||
"disallowed": "L'extension n'est pas activée pour cette page",
|
||||
"disallowedAction": "Activer l'extension",
|
||||
"failed": "Échec de la demande de statut",
|
||||
"loading": "En attendant que vous installiez l'extension",
|
||||
"outdated": "Version d'extension trop ancienne",
|
||||
"success": "L'extension fonctionne comme prévu !"
|
||||
},
|
||||
"submit": "Continuer",
|
||||
"title": "Commençons par une extension"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "Retour en arrière",
|
||||
"explainer": "Avec la méthode du proxy, vous pouvez obtenir des flux de bonne qualité en créant un proxy en libre-service.",
|
||||
"input": {
|
||||
"errorConnection": "Impossible de se connecter au proxy",
|
||||
"errorInvalidUrl": "URL non valide",
|
||||
"errorNotProxy": "Je m'attendais à un proxy mais j'ai obtenu un site Web",
|
||||
"label": "URL du proxy",
|
||||
"placeholder": "https://"
|
||||
},
|
||||
"link": "Apprenez à créer un proxy",
|
||||
"submit": "Soumettre le proxy",
|
||||
"title": "Créons un nouveau proxy"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "Pour obtenir les meilleurs flux possibles, vous devrez choisir la méthode de streaming que vous souhaitez utiliser.",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "Je ne veux pas de flux de bonne qualité,<0 /> <1>use the default setup</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "Installer l'extension",
|
||||
"description": "Installez l'extension de navigateur et accédez aux meilleures sources.",
|
||||
"quality": "Meilleur qualité",
|
||||
"title": "Extension du navigateur"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "Configurez le proxy",
|
||||
"description": "Configurez un proxy en seulement 5 minutes et accédez à d'excellentes sources.",
|
||||
"quality": "Bonne qualité",
|
||||
"title": "Proxy personnalisé"
|
||||
}
|
||||
},
|
||||
"title": "Commençons par vous configurer movie-web"
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "Fermer"
|
||||
},
|
||||
@ -182,7 +246,7 @@
|
||||
"downloadPlaylist": "Télécharger la liste de lecture",
|
||||
"downloadSubtitle": "Télécharger les sous-titres",
|
||||
"downloadVideo": "Télécharger la vidéo",
|
||||
"hlsDisclaimer": "Les téléchargements sont pris directement de la source. Movie-Web n'exerce aucun contrôle sur les méthodes des fournisseurs de téléchargement. Veuillez noter que vous téléchargez une liste de lecture HLS, destinée aux utilisateurs habitués au streaming multimédia avancé.",
|
||||
"hlsDisclaimer": "Les téléchargements sont effectués directement auprès du fournisseur. movie-web n'a aucun contrôle sur la façon dont les téléchargements sont fournis.<br /><br />Veuillez noter que vous téléchargez une liste de lecture HLS, <bold>il n'est pas recommandé de la télécharger si vous n'êtes pas familier avec les formats de streaming avancés. </bold>. Essayez différentes sources pour différents formats.",
|
||||
"onAndroid": {
|
||||
"1": "Pour télécharger sur Android, cliquez sur le bouton de téléchargement puis, sur la nouvelle page, <bold>tapez et maintenez </bold> sur la vidéo, puis sélectionnez <bold>enregistrer</bold>.",
|
||||
"shortTitle": "Télécharger / Android",
|
||||
@ -263,6 +327,17 @@
|
||||
"text": "Impossible de charger les métadonnées de l'API, veuillez vérifier votre connexion Internet.",
|
||||
"title": "Échec du chargement des métadonnées de l'API"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "Supprimé",
|
||||
"text": "Ce média n'est plus disponible en raison d'un avis de retrait ou d'une réclamation pour atteinte aux droits d'auteur.",
|
||||
"title": "Le média a été supprimé"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "Autorisation manquante",
|
||||
"button": "Utiliser l'extension",
|
||||
"text": "Vous disposez de l'extension de navigateur, mais nous avons besoin de votre autorisation pour commencer à utiliser l'extension.",
|
||||
"title": "Configurer l'extension"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "Échec",
|
||||
"homeButton": "Revenir à l'accueil",
|
||||
@ -390,24 +465,49 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "Si vous souhaitez vous connecter à un backend personnalisé pour stocker vos données, activez cette option et indiquez l'URL.",
|
||||
"description": "Si vous désirez utiliser un système de stockage externe pour enregistrer vos données, activez cette option et indiquez l'URL. <0>Instructions.</0>",
|
||||
"label": "Serveur personnalisé",
|
||||
"urlLabel": "URL du serveur personnalisé"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "Faire la configuration",
|
||||
"errorStatus": {
|
||||
"description": "Il semble qu'un ou plusieurs éléments de cette configuration nécessitent votre attention.",
|
||||
"title": "Quelque chose nécessite votre attention"
|
||||
},
|
||||
"itemError": "Ce paramètre présente un problème. Résolvez le problème en redémarrant la configuration.",
|
||||
"items": {
|
||||
"default": "Configuration par défaut",
|
||||
"extension": "Extension",
|
||||
"proxy": "Proxy personnalisé"
|
||||
},
|
||||
"redoSetup": "Refaire la configuration",
|
||||
"successStatus": {
|
||||
"description": "Tout est réuni pour que vous puissiez commencer à regarder vos médias préférés.",
|
||||
"title": "Tout est mis en place !"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "Pour commencer le processus de configuration, veuillez cliquer sur le bouton à droite.",
|
||||
"title": "Vous n'avez pas fait la configuration"
|
||||
}
|
||||
},
|
||||
"title": "Connexions",
|
||||
"workers": {
|
||||
"addButton": "Ajouter un nouveau worker",
|
||||
"description": "Pour que l'application fonctionne, tout le trafic est acheminé via des proxys. Activez cette option si vous souhaitez faire appel à vos propres workers.",
|
||||
"description": "Pour que l'application fonctionne, tout le trafic est acheminé via des proxys. Activez cette option si vous souhaitez faire appel à vos propres workers. <0>Instructions.</0>",
|
||||
"emptyState": "Pas encore de workers, ajoutez-en un ci-dessous",
|
||||
"label": "Utiliser des agents proxy personnalisés",
|
||||
"urlLabel": "URLs des workers",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"language": "Langue de l'application",
|
||||
"languageDescription": "Langue appliquée dans l'ensemble de l'app.",
|
||||
"title": "Local"
|
||||
"preferences": {
|
||||
"language": "Language de l'application",
|
||||
"languageDescription": "Langue appliquée à l’ensemble de l’application.",
|
||||
"thumbnail": "Générer des miniatures",
|
||||
"thumbnailDescription": "La plupart du temps, les vidéos n'ont pas de miniatures. Vous pouvez activer ce paramètre pour les générer à la volée, mais ils peuvent ralentir votre vidéo.",
|
||||
"thumbnailLabel": "Générer des miniatures",
|
||||
"title": "Préférences"
|
||||
},
|
||||
"reset": "Réinitialiser",
|
||||
"save": "Sauvegarder",
|
||||
|
@ -95,6 +95,7 @@
|
||||
"about": "Acerca de",
|
||||
"dmca": "DMCA",
|
||||
"login": "Iniciar sesión",
|
||||
"onboarding": "Configuración",
|
||||
"pagetitle": "{{title}} - movie-web",
|
||||
"register": "Rexistrarse",
|
||||
"settings": "Configuración"
|
||||
@ -165,6 +166,69 @@
|
||||
"message": "Prometocho, buscamos en todas partes: debaixo dos contenedores, no armario, detrás do proxy, pero ao final non puidemos atopar a páxina que estabas buscando.",
|
||||
"title": "Non atopei a páxona que estabas a buscar"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "Cancelar",
|
||||
"confirm": "Usar configuración por defecto",
|
||||
"description": "A configuración por defecto non ten a mellor calidade e pode ser moi lenta.",
|
||||
"title": "Estás seguro?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "Volver atrás",
|
||||
"explainer": "Usando a extensión de navegador, podes obter os mellores streams á mellor calidade. Cunha simple instalación.",
|
||||
"explainerIos": "Por desgraza, a extensión de navegador non é soportada en iOS. Pulsa <bold>volver atrás</bold> para escoller outra opción.",
|
||||
"extensionHelp": "Se instalaches a extensión pero non é detectada, <bold>abre a extensión dende o menú de extensións do navegador</bold> e sigue os pasos na pantalla.",
|
||||
"linkChrome": "Instalar extensión de Chrome",
|
||||
"linkFirefox": "Instalar extensión de Firefox",
|
||||
"notDetecting": "Instalada en Chrome, pero o sitio web non a está a detectar? Proba recargando a páxina!",
|
||||
"notDetectingAction": "Recargar a páxina",
|
||||
"status": {
|
||||
"disallowed": "A extensión non está habilitada para esta páxina",
|
||||
"disallowedAction": "Activar extensión",
|
||||
"failed": "Error ao solicitar estado",
|
||||
"loading": "Esperando a que instales a extensión",
|
||||
"outdated": "A versión da extensión é moi vella",
|
||||
"success": "A extensión funciona como se esperaba!"
|
||||
},
|
||||
"submit": "Continuar",
|
||||
"title": "Vamos a empezar coa extensión"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "Vover atrás",
|
||||
"explainer": "Có método do proxy, podes obter streams de boa calidade creando un proxy hosteado por ti mesmo.",
|
||||
"input": {
|
||||
"errorConnection": "Non foi posible a conexión có proxy",
|
||||
"errorInvalidUrl": "URL non válida",
|
||||
"errorNotProxy": "Estaba previsto obter o proxy pero obtuven unha páxina web",
|
||||
"label": "URL do proxy",
|
||||
"placeholder": "https://"
|
||||
},
|
||||
"link": "Aprender a configurar o proxy",
|
||||
"submit": "Validar proxy",
|
||||
"title": "Vamos crear un novo proxy"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "Para obter a maior calidade posible, terás que elexir que método de streaming queres usar.",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "Non quero streams de boa calidade, <0 /> <1>usarei a configuración por defecto</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "Instalar extensión",
|
||||
"description": "Instala a extensión de navegador e obtén acceso ás mellores fontes.",
|
||||
"quality": "A mellor calidade",
|
||||
"title": "Extensión de navegador"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "Configurar proxy",
|
||||
"description": "Configura un proxy en só 5 minutos e gaña acceso ás mellores fontes.",
|
||||
"quality": "Boa calidade",
|
||||
"title": "Proxy personalizado"
|
||||
}
|
||||
},
|
||||
"title": "Vamos a empezar coa configuración de movie-web"
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "Cerrar"
|
||||
},
|
||||
@ -263,6 +327,17 @@
|
||||
"text": "Non puiden cargar os metadatos da API, por favor, comproba a túa conexión a internet.",
|
||||
"title": "Non foi posible cargar os metadatos da API"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "Agochado",
|
||||
"text": "Este contido non está dispoñible debido a unha reclamación dos dereitos de autor.",
|
||||
"title": "Os contidos foron retirados"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "Non hai permisos suficientes",
|
||||
"button": "Usar extensión",
|
||||
"text": "Si que tes a extensión de navegador, pero precisamos do teu permiso para empezar a usala.",
|
||||
"title": "Configura a extensión"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "Erro",
|
||||
"homeButton": "Ir ao inicio",
|
||||
@ -390,24 +465,49 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "Se che gustaría conectar un servidor personalizado de backend para almacenar os teus datos, activa esto e indica a URL.",
|
||||
"description": "Se che gustaría conectar un servidor personalizado de backend para almacenar os teus datos, activa esto e indica a URL. <0>Instruccións.</0>",
|
||||
"label": "Servidor personalizado",
|
||||
"urlLabel": "Servidor personalizado URL"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "Configurar",
|
||||
"errorStatus": {
|
||||
"description": "Parece que hay un ou varios puntos que precisan da tua atención.",
|
||||
"title": "Hai algo que require da túa atención"
|
||||
},
|
||||
"itemError": "Hai un erro nesta configuración. Volve atrás para solucionalo.",
|
||||
"items": {
|
||||
"default": "Configuración por defecto",
|
||||
"extension": "Extensión",
|
||||
"proxy": "Proxy personalizado"
|
||||
},
|
||||
"redoSetup": "Retroceder na configuración",
|
||||
"successStatus": {
|
||||
"description": "Todo está no seu sitio para que podas empezar a ver os teus contidos favoritos.",
|
||||
"title": "Todo está configurado!"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "Por favor, preme no botón para empezar o proceso de configuración.",
|
||||
"title": "Non empezaches ningunha configuración"
|
||||
}
|
||||
},
|
||||
"title": "Conexións",
|
||||
"workers": {
|
||||
"addButton": "Añadir novo",
|
||||
"description": "Para facer que a aplicación funcione, todo o tráfico é organizado en proxies. Activa esta opción se queres empregar os teus propios workers.",
|
||||
"description": "Para facer que a aplicación funcione, todo o tráfico é organizado en proxies. Activa esta opción se queres empregar os teus propios workers. <0>Instruccións.</0>",
|
||||
"emptyState": "Non hai workers aínda, engade un abaixo",
|
||||
"label": "Usar proxy workers personalizados",
|
||||
"urlLabel": "URLs dos workers",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"language": "Lingua da aplicación",
|
||||
"languageDescription": "Lingua empregada en toda aplicación.",
|
||||
"title": "Local"
|
||||
"preferences": {
|
||||
"language": "Linguaxe da aplicación",
|
||||
"languageDescription": "Lingua aplicada a toda a aplicación.",
|
||||
"thumbnail": "Xerar miniaturas",
|
||||
"thumbnailDescription": "Na maioría das veces, os videos non teñen miniaturas. Podes activar esta configuración para xeralas ao momento, pero podes realentizar o video.",
|
||||
"thumbnailLabel": "Xerar miniaturas",
|
||||
"title": "Preferencias"
|
||||
},
|
||||
"reset": "Reinicio",
|
||||
"save": "Gardar",
|
||||
|
@ -95,6 +95,7 @@
|
||||
"about": "વિશે",
|
||||
"dmca": "DMCA",
|
||||
"login": "પ્રવેશ કરો",
|
||||
"onboarding": "સ્થાપના",
|
||||
"pagetitle": "{{title}} - મૂવી-વેબ",
|
||||
"register": "નોંધણી કરો",
|
||||
"settings": "સેટિંગ્સ"
|
||||
@ -165,6 +166,69 @@
|
||||
"message": "અમે બધે જોયું: ડબ્બાની નીચે, કબાટમાં, પ્રોક્સીની પાછળ, પરંતુ આખરે તમે જે page શોધી રહ્યાં છો તે શોધી શક્યા નહીં.",
|
||||
"title": "page શોધી શક્યું નથી"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "રદ કરો",
|
||||
"confirm": "ડિફૉલ્ટ સેટઅપનો ઉપયોગ કરો",
|
||||
"description": "ડિફૉલ્ટ સેટઅપમાં શ્રેષ્ઠ સ્ટ્રીમ્સ નથી અને તે અસહ્ય રીતે ધીમું હોઈ શકે છે.",
|
||||
"title": "શું તમને ખાતરી છે?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "પાછા જાવ",
|
||||
"explainer": "બ્રાઉઝર એક્સ્ટેંશનનો ઉપયોગ કરીને, તમે શ્રેષ્ઠ સ્ટ્રીમ મેળવી શકો છો જે અમે ઓફર કરીએ છીએ. માત્ર એક સરળ ઇન્સ્ટોલ સાથે.",
|
||||
"explainerIos": "કમનસીબે, બ્રાઉઝર એક્સ્ટેંશન iOS પર સમર્થિત નથી, બીજો વિકલ્પ પસંદ કરવા માટે <bold>Go back</bold> દબાવો.",
|
||||
"extensionHelp": "જો તમે એક્સ્ટેંશન ઇન્સ્ટોલ કર્યું છે પરંતુ તે શોધાયેલ નથી, તો <bold>તમારા બ્રાઉઝર એક્સ્ટેંશન મેનૂ દ્વારા એક્સ્ટેંશન ખોલો</bold> અને સ્ક્રીન પરના પગલાંને અનુસરો.",
|
||||
"linkChrome": "Chrome એક્સ્ટેંશન ઇન્સ્ટોલ કરો",
|
||||
"linkFirefox": "Firefox એક્સ્ટેંશન ઇન્સ્ટોલ કરો",
|
||||
"notDetecting": "Chrome પર ઇન્સ્ટોલ કરેલું છે, પરંતુ સાઇટ તેને શોધી રહી નથી? પૃષ્ઠને ફરીથી લોડ કરવાનો પ્રયાસ કરો!",
|
||||
"notDetectingAction": "પૃષ્ઠ ફરીથી લોડ કરો",
|
||||
"status": {
|
||||
"disallowed": "આ પૃષ્ઠ માટે એક્સ્ટેંશન સક્ષમ નથી",
|
||||
"disallowedAction": "એક્સ્ટેંશન સક્ષમ કરો",
|
||||
"failed": "સ્થિતિની વિનંતી કરવામાં નિષ્ફળ",
|
||||
"loading": "તમે એક્સ્ટેંશન ઇન્સ્ટોલ કરવા માટે રાહ જોઈ રહ્યાં છો",
|
||||
"outdated": "એક્સ્ટેંશન સંસ્કરણ ખૂબ જૂનું છે",
|
||||
"success": "એક્સ્ટેંશન અપેક્ષા મુજબ કામ કરી રહ્યું છે!"
|
||||
},
|
||||
"submit": "ચાલુ રાખો",
|
||||
"title": "ચાલો એક્સ્ટેંશનથી શરૂઆત કરીએ"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "પાછા જાવ",
|
||||
"explainer": "પ્રોક્સી પદ્ધતિ સાથે, તમે સ્વ-સેવા પ્રોક્સી બનાવીને ઉત્તમ ગુણવત્તાની સ્ટ્રીમ્સ મેળવી શકો છો.",
|
||||
"input": {
|
||||
"errorConnection": "પ્રોક્સી સાથે કનેક્ટ કરી શકાયું નથી",
|
||||
"errorInvalidUrl": "માન્ય URL નથી",
|
||||
"errorNotProxy": "પ્રોક્સીની અપેક્ષા હતી પણ વેબસાઇટ મળી",
|
||||
"label": "પ્રોક્સી URL",
|
||||
"placeholder": "https://"
|
||||
},
|
||||
"link": "પ્રોક્સી કેવી રીતે બનાવવી તે જાણો",
|
||||
"submit": "પ્રોક્સી સબમિટ કરો",
|
||||
"title": "ચાલો એક નવી પ્રોક્સી બનાવીએ"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "શક્ય શ્રેષ્ઠ સ્ટ્રીમ્સ મેળવવા માટે, તમારે કઈ સ્ટ્રીમિંગ પદ્ધતિનો ઉપયોગ કરવો છે તે પસંદ કરવાની જરૂર પડશે.",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "મને સારી ગુણવત્તાની સ્ટ્રીમ જોઈતી નથી,<0 /> <1>ડિફૉલ્ટ સેટઅપનો ઉપયોગ કરો</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "એક્સ્ટેંશન ઇન્સ્ટોલ કરો",
|
||||
"description": "બ્રાઉઝર એક્સ્ટેંશન ઇન્સ્ટોલ કરો અને શ્રેષ્ઠ સ્ત્રોતોની ઍક્સેસ મેળવો.",
|
||||
"quality": "ઉત્તમ ગુણવત્તા",
|
||||
"title": "બ્રાઉઝર એક્સ્ટેંશન"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "પ્રોક્સી સેટઅપ કરો",
|
||||
"description": "માત્ર 5 મિનિટમાં પ્રોક્સી સેટ કરો અને શ્રેષ્ઠ સ્ત્રોતોની ઍક્સેસ મેળવો.",
|
||||
"quality": "સારી ગુણવત્તા",
|
||||
"title": "કસ્ટમ પ્રોક્સી"
|
||||
}
|
||||
},
|
||||
"title": "ચાલો તમને મૂવી-વેબ સાથે સેટઅપ કરાવીએ"
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "બંધ"
|
||||
},
|
||||
@ -182,7 +246,7 @@
|
||||
"downloadPlaylist": "પ્લેલિસ્ટ ડાઉનલોડ કરો",
|
||||
"downloadSubtitle": "વર્તમાન ઉપશીર્ષક ડાઉનલોડ કરો",
|
||||
"downloadVideo": "વિડિઓ ડાઉનલોડ કરો",
|
||||
"hlsDisclaimer": "ડાઉનલોડ સીધા પ્રદાતા પાસેથી લેવામાં આવે છે. મૂવી-વેબ ડાઉનલોડ્સ કેવી રીતે પ્રદાન કરવામાં આવે છે તેના પર નિયંત્રણ નથી. કૃપા કરીને નોંધો કે તમે HLS પ્લેલિસ્ટ ડાઉનલોડ કરી રહ્યાં છો, આ અદ્યતન મલ્ટીમીડિયા સ્ટ્રીમિંગથી પરિચિત વપરાશકર્તાઓ માટે બનાવાયેલ છે.",
|
||||
"hlsDisclaimer": "ડાઉનલોડ સીધા પ્રદાતા પાસેથી લેવામાં આવે છે. કેવી રીતે ડાઉનલોડ્સ પ્રદાન કરવામાં આવે છે તેના પર મૂવી-વેબનું નિયંત્રણ નથી.<br /><br />કૃપા કરીને નોંધ કરો કે તમે HLS પ્લેલિસ્ટ ડાઉનલોડ કરી રહ્યાં છો, <bold>જો તમે અદ્યતન સ્ટ્રીમિંગ ફોર્મેટથી પરિચિત ન હોવ તો તેને ડાઉનલોડ કરવાની ભલામણ કરવામાં આવતી નથી</bold>. વિવિધ ફોર્મેટ માટે વિવિધ સ્ત્રોતો અજમાવો.",
|
||||
"onAndroid": {
|
||||
"1": "Android પર ડાઉનલોડ કરવા માટે, ડાઉનલોડ બટનને ક્લિક કરો પછી, નવા પૃષ્ઠ પર, વિડિઓ પર <bold>ટેપ કરો અને પકડી રાખો</bold>, પછી <bold>સાચવો</bold> પસંદ કરો.",
|
||||
"shortTitle": "ડાઉનલોડ કરો / Android",
|
||||
@ -263,6 +327,17 @@
|
||||
"text": "API મેટાડેટા લોડ કરી શકાયું નથી, કૃપા કરીને તમારું ઇન્ટરનેટ કનેક્શન તપાસો.",
|
||||
"title": "API મેટાડેટા લોડ કરવામાં નિષ્ફળ"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "દૂર",
|
||||
"text": "દૂર કરવાની સૂચના અથવા કૉપિરાઇટ દાવાને કારણે આ મીડિયા હવે ઉપલબ્ધ નથી.",
|
||||
"title": "મીડિયા દૂર કરવામાં આવ્યું છે"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "પરવાનગી ખૂટે છે",
|
||||
"button": "એક્સ્ટેંશનનો ઉપયોગ કરો",
|
||||
"text": "તમારી પાસે બ્રાઉઝર એક્સ્ટેંશન છે, પરંતુ એક્સ્ટેંશનનો ઉપયોગ શરૂ કરવા માટે અમને તમારી પરવાનગીની જરૂર છે.",
|
||||
"title": "એક્સ્ટેંશનને ગોઠવો"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "નિષ્ફળ",
|
||||
"homeButton": "ઘર જાઓ",
|
||||
@ -390,24 +465,49 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "જો તમે તમારો ડેટા સંગ્રહિત કરવા માટે કસ્ટમ બેકએન્ડ સાથે જોડાવા માંગતા હો, તો આને સક્ષમ કરો અને URL પ્રદાન કરો.",
|
||||
"description": "જો તમે તમારો ડેટા સંગ્રહિત કરવા માટે કસ્ટમ બેકએન્ડ સાથે જોડાવા માંગતા હો, તો આને સક્ષમ કરો અને URL પ્રદાન કરો. <0>સૂચનો.</0>",
|
||||
"label": "કસ્ટમ સર્વર",
|
||||
"urlLabel": "કસ્ટમ સર્વર URL"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "સેટઅપ કરો",
|
||||
"errorStatus": {
|
||||
"description": "એવું લાગે છે કે આ સેટઅપમાં એક અથવા વધુ આઇટમ્સ તમારા ધ્યાનની જરૂર છે.",
|
||||
"title": "કંઈક તમારા ધ્યાનની જરૂર છે"
|
||||
},
|
||||
"itemError": "આ સેટિંગમાં કંઈક ખોટું છે. તેને ઠીક કરવા માટે ફરીથી સેટઅપ પર જાઓ.",
|
||||
"items": {
|
||||
"default": "ડિફૉલ્ટ સેટઅપ",
|
||||
"extension": "વિસ્તરણ",
|
||||
"proxy": "કસ્ટમ પ્રોક્સી"
|
||||
},
|
||||
"redoSetup": "સેટઅપ ફરી કરો",
|
||||
"successStatus": {
|
||||
"description": "તમારા મનપસંદ મીડિયાને જોવાનું શરૂ કરવા માટે તમારા માટે બધી વસ્તુઓ છે.",
|
||||
"title": "બધું સુયોજિત છે!"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "કૃપા કરીને સેટઅપ પ્રક્રિયા શરૂ કરવા માટે જમણી બાજુના બટનને ક્લિક કરો.",
|
||||
"title": "તમે સેટઅપમાંથી પસાર થયા નથી"
|
||||
}
|
||||
},
|
||||
"title": "જોડાણો",
|
||||
"workers": {
|
||||
"addButton": "નવો કાર્યકર ઉમેરો",
|
||||
"description": "એપ્લિકેશન કાર્ય કરવા માટે, તમામ ટ્રાફિકને પ્રોક્સીઓ દ્વારા રૂટ કરવામાં આવે છે. જો તમે તમારા પોતાના કામદારોને લાવવા માંગતા હોવ તો આને સક્ષમ કરો.",
|
||||
"description": "એપ્લિકેશન કાર્ય કરવા માટે, તમામ ટ્રાફિકને પ્રોક્સીઓ દ્વારા રૂટ કરવામાં આવે છે. જો તમે તમારા પોતાના કામદારોને લાવવા માંગતા હોવ તો આને સક્ષમ કરો. <0>સૂચનો.</0>",
|
||||
"emptyState": "હજુ સુધી કોઈ કામદારો નથી, નીચે એક ઉમેરો",
|
||||
"label": "કસ્ટમ પ્રોક્સી કાર્યકરોનો ઉપયોગ કરો",
|
||||
"urlLabel": "વર્કર URL",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"preferences": {
|
||||
"language": "એપ્લિકેશન ભાષા",
|
||||
"languageDescription": "સમગ્ર એપ્લિકેશન પર લાગુ ભાષા.",
|
||||
"title": "સ્થળ"
|
||||
"thumbnail": "થંબનેલ્સ બનાવો",
|
||||
"thumbnailDescription": "મોટાભાગે, વીડિયોમાં થંબનેલ્સ હોતા નથી. તમે આ સેટિંગને ફ્લાય પર જનરેટ કરવા માટે સક્ષમ કરી શકો છો પરંતુ તે તમારા વિડિઓને ધીમું બનાવી શકે છે.",
|
||||
"thumbnailLabel": "થંબનેલ્સ બનાવો",
|
||||
"title": "પસંદગીઓ"
|
||||
},
|
||||
"reset": "રીસેટ કરો",
|
||||
"save": "સાચવો",
|
||||
|
@ -23,7 +23,7 @@
|
||||
"auth": {
|
||||
"createAccount": "אין לך עדיין חשבון? <0>צור חשבון.</0>",
|
||||
"deviceNameLabel": "שם המכשיר",
|
||||
"deviceNamePlaceholder": "מכשיר אישי",
|
||||
"deviceNamePlaceholder": "פלאפון אישי",
|
||||
"generate": {
|
||||
"description": "ביטוי הסיסמה שלך משמש כשם המשתמש והסיסמה שלך. אנא הקפד לשמור אותו בטוח מכיוון שתצטרך להזין אותו כדי להתחבר לחשבון שלך",
|
||||
"next": "אני שמרתי את משפט הסיסמה שלי",
|
||||
@ -95,6 +95,7 @@
|
||||
"about": "אודות",
|
||||
"dmca": "זכויות יוצרים",
|
||||
"login": "התחבר",
|
||||
"onboarding": "הכנה",
|
||||
"pagetitle": "{{title}} - movie-web",
|
||||
"register": "הירשם",
|
||||
"settings": "הגדרות"
|
||||
@ -165,6 +166,69 @@
|
||||
"message": "חיפשנו בכל מקום: מתחת לפחים, בארון, מאחורי ה-proxy אבל בסופו של דבר לא מצאנו את הדף שאתה מחפש.",
|
||||
"title": "לא יכולנו למצוא את דף זה"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "בטל",
|
||||
"confirm": "השתמש בהגדרות ברירת המחדל",
|
||||
"description": "הגדרת ברירת המחדל אינה כוללת את הזרמים הטובים ביותר ויכולה להיות איטית בצורה בלתי נסבלת.",
|
||||
"title": "אתה בטוח?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "חזור",
|
||||
"explainer": "באמצעות תוסף הדפדפן, אתה יכול לקבל את הזרמים הטובים ביותר שיש לנו להציע. עם התקנה פשוטה בלבד.",
|
||||
"explainerIos": "לצערנו, התוסף לדפדפן לא תומך בiOS, לחץ <bold>חזור</bold> כדי לבחור אפשרות אחרת.",
|
||||
"extensionHelp": "אם התקנת את התוסף אך הוא לא מזוהה. <bold>פתח את התוסף דרך תפריט התוספות של הדפדפן שלך</bold> ובצע את השלבים שעל המסך.",
|
||||
"linkChrome": "התקן תוסף Chrome",
|
||||
"linkFirefox": "התקן תוסף Firefox",
|
||||
"notDetecting": "מותקן על Chrome, אבל האתר לא מזהה את זה? נסה לטעון את הדף מחדש!",
|
||||
"notDetectingAction": "טען דף מחדש",
|
||||
"status": {
|
||||
"disallowed": "התוסף אינו מפועל עבור דף זה",
|
||||
"disallowedAction": "אפשר תוסף",
|
||||
"failed": "בקשת הסטטוס נכשלה",
|
||||
"loading": "מחכה שתתקין את התוסף",
|
||||
"outdated": "גרסת התוסף ישנה מדי",
|
||||
"success": "התוסף עובד כמצופה!"
|
||||
},
|
||||
"submit": "המשך",
|
||||
"title": "נתחיל עם התוסף"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "חזור",
|
||||
"explainer": "עם שיטת הפרוקסי, אתה יכול לקבל זרמים באיכות מעולה על ידי יצירת פרוקסי בשירות עצמי.",
|
||||
"input": {
|
||||
"errorConnection": "לא ניתן להתחבר לפרוקסי",
|
||||
"errorInvalidUrl": "כתובת לא תקינה",
|
||||
"errorNotProxy": "ציפה לפרוקסי אבל קיבל אתר",
|
||||
"label": "כתובת פרוקסי",
|
||||
"placeholder": "https://"
|
||||
},
|
||||
"link": "למד כיצד ליצור פרוקסי",
|
||||
"submit": "שלח פרוקסי",
|
||||
"title": "בואו ניצור פרוקסי חדש"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "כדי לקבל את הזרמים הכי טובים שאפשר. תצטרך לבחור באיזו שיטת סטרימינג תרצה להשתמש.",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "אני לא רוצה זרמים באיכות טובה,<0 /> <1>השתמש בהגדרת ברירת המחדל</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "התקן תוסף",
|
||||
"description": "התקן תוסף דפדפן וקבל גישה למקורות הטובים ביותר.",
|
||||
"quality": "איכות מעולה",
|
||||
"title": "תוסף הדפדפן"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "הגדר פרוקסי",
|
||||
"description": "הגדר פרוקסי תוך 5 דקות בלבד וקבל גישה למקורות מעולים.",
|
||||
"quality": "איכות טובה",
|
||||
"title": "פרוקסי מותאם אישית"
|
||||
}
|
||||
},
|
||||
"title": "בוא נעשה לך התקנה עם movie-web"
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "סגור"
|
||||
},
|
||||
@ -182,7 +246,7 @@
|
||||
"downloadPlaylist": "הורד פלייליסט",
|
||||
"downloadSubtitle": "הורד את הכתוביות הנוכחיות",
|
||||
"downloadVideo": "הורד וידאו",
|
||||
"hlsDisclaimer": "ההורדות נלקחות ישירות מהספק. ל-movie-web אין שליטה על האופן שבו מסופקות ההורדות. שימו לב שאתם מורידים רשימת השמעה של HLS, זה מיועד למשתמשים שמכירים הזרמת מולטימדיה מתקדמת.",
|
||||
"hlsDisclaimer": "ההורדות נלקחות ישירות מהספק. ל-movie-web אין שליטה על האופן שבו מסופקות ההורדות.<br /><br />שים לב שאתה מוריד רשימת השמעה של HLS, <bold>לא מומלץ להוריד אם אינך מכיר פורמטים מתקדמים של סטרימינג </bold>. נסה מקורות שונים עבור פורמטים שונים.",
|
||||
"onAndroid": {
|
||||
"1": "כדי להוריד באנדרואיד, לחץ על כפתור ההורדה ולאחר מכן, בדף החדש, <bold>הקש והחזק</bold> על הסרטון, ולאחר מכן בחר <bold>שמור</bold>.",
|
||||
"shortTitle": "הורדה / אנדרויד",
|
||||
@ -263,6 +327,17 @@
|
||||
"text": "לא ניתן היה לטעון מטא נתונים של ה-API, אנא בדוק את חיבור האינטרנט שלך.",
|
||||
"title": "טעינת מטא נתונים של ממשק API נכשלה"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "הוסר",
|
||||
"text": "מדיה זו אינה זמינה יותר עקב הודעת הסרה או תביעה בגין זכויות יוצרים.",
|
||||
"title": "מדיה הוסרה"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "הרשאה חסר",
|
||||
"button": "השתמש בתוסף",
|
||||
"text": "יש לך את תוסף הדפדפן, אך אנו זקוקים לאישורך כדי להתחיל להשתמש בתוסף.",
|
||||
"title": "הגדר את התוסף"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "נכשל",
|
||||
"homeButton": "חזור לדף הבית",
|
||||
@ -390,24 +465,49 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "אם תרצה להתחבר ל-backend מותאם אישית כדי לאחסן את הנתונים שלך, הפעל זאת וספק את כתובת האתר.",
|
||||
"description": "אם תרצה להתחבר ל-backend מותאם אישית כדי לאחסן את הנתונים שלך, הפעל זאת וספק את כתובת האתר. <0>הוראות.</0>",
|
||||
"label": "שרת אישי",
|
||||
"urlLabel": "כתובת אתר מותאמת אישית של שרת"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "עשה הגדרה",
|
||||
"errorStatus": {
|
||||
"description": "נראה כי פריט אחד או יותר בהגדרה זו זקוקים לתשומת לבך.",
|
||||
"title": "משהו צריך את תשומת ליבך"
|
||||
},
|
||||
"itemError": "משהו לא בסדר בהגדרה הזו. עבור שוב על ההגדרה כדי לתקן את זה.",
|
||||
"items": {
|
||||
"default": "הגדרת ברירת מחדל",
|
||||
"extension": "תוסף",
|
||||
"proxy": "פרוקסי מותאם אישית"
|
||||
},
|
||||
"redoSetup": "בצע מחדש את ההגדרה",
|
||||
"successStatus": {
|
||||
"description": "כל הדברים נמצאים במקום כדי שתוכל להתחיל לצפות במדיה האהובה עליך.",
|
||||
"title": "הכל מוכן!"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "אנא לחץ על הלחצן מימין כדי להתחיל בתהליך ההגדרה.",
|
||||
"title": "לא עברת את ההגדרה"
|
||||
}
|
||||
},
|
||||
"title": "התחברויות",
|
||||
"workers": {
|
||||
"addButton": "הוסף עובד חדש",
|
||||
"description": "כדי שהאפליקציה תפעל, כל התעבורה מנותבת דרך פרוקסי. הפעל זאת אם אתה רוצה להביא עובדים משלך.",
|
||||
"description": "כדי שהאפליקציה תפעל, כל התעבורה מנותבת דרך פרוקסי. הפעל זאת אם אתה רוצה להביא עובדים משלך. <0>הוראות.</0>",
|
||||
"emptyState": "עדיין אין עובדים, הוסף אחד למטה",
|
||||
"label": "השתמש בעובדי פרוקסי מותאמים אישית",
|
||||
"urlLabel": "כתובות אתרים של עובדים",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"preferences": {
|
||||
"language": "שפת האפליקציה",
|
||||
"languageDescription": "השפה החלה על האפליקציה כולה.",
|
||||
"title": "מקומי"
|
||||
"thumbnail": "צור טאמבניילים",
|
||||
"thumbnailDescription": "לרוב, לסרטונים אין טאמבניילים. אתה יכול להפעיל את ההגדרה הזו כדי ליצור אותם, אבל הם יכולים להפוך את הסרטון שלך לאיטי יותר.",
|
||||
"thumbnailLabel": "צור טאמבניילים",
|
||||
"title": "העדפות"
|
||||
},
|
||||
"reset": "איפוס",
|
||||
"save": "לשמור",
|
||||
|
@ -95,6 +95,7 @@
|
||||
"about": "साइट के बारे में",
|
||||
"dmca": "DMCA",
|
||||
"login": "लॉग इन",
|
||||
"onboarding": "स्थापित करना",
|
||||
"pagetitle": "{{title}} - मूवी-वेब",
|
||||
"register": "नया खाता बनायें",
|
||||
"settings": "सेटिंग्स"
|
||||
@ -165,6 +166,69 @@
|
||||
"message": "हमने हर जगह देखा: डिब्बे के नीचे, कोठरी में, प्रॉक्सी के पीछे लेकिन अंततः वह पेज नहीं मिला जिसे आप ढूंढ रहे थे।",
|
||||
"title": "वह पृष्ठ नहीं मिल सका"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "रद्द करना",
|
||||
"confirm": "डिफ़ॉल्ट सेटअप का उपयोग करें",
|
||||
"description": "डिफ़ॉल्ट सेटअप में सर्वोत्तम स्ट्रीम नहीं हैं और यह असहनीय रूप से धीमा हो सकता है।",
|
||||
"title": "क्या आपको यकीन है?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "वापस जाओ",
|
||||
"explainer": "ब्राउज़र एक्सटेंशन का उपयोग करके, आप हमारे द्वारा प्रदान की जाने वाली सर्वोत्तम स्ट्रीम प्राप्त कर सकते हैं। बस एक साधारण इंस्टालेशन के साथ।",
|
||||
"explainerIos": "दुर्भाग्य से, ब्राउज़र एक्सटेंशन iOS पर समर्थित नहीं है, दूसरा विकल्प चुनने के लिए <bold>वापस जाएं</bold> दबाएं।",
|
||||
"extensionHelp": "यदि आपने एक्सटेंशन इंस्टॉल किया है लेकिन उसका पता नहीं चला है, तो <bold>अपने ब्राउज़र एक्सटेंशन मेनू के माध्यम से एक्सटेंशन खोलें</bold> और स्क्रीन पर दिए गए चरणों का पालन करें।",
|
||||
"linkChrome": "Chrome एक्सटेंशन इंस्टॉल करें",
|
||||
"linkFirefox": "Firefox एक्सटेंशन इंस्टॉल करें",
|
||||
"notDetecting": "Chrome पर इंस्टॉल किया गया है, लेकिन साइट इसका पता नहीं लगा रही है? पृष्ठ को पुनः लोड करने का प्रयास करें!",
|
||||
"notDetectingAction": "पृष्ठ पुनः लोड करें",
|
||||
"status": {
|
||||
"disallowed": "इस पृष्ठ के लिए एक्सटेंशन सक्षम नहीं है",
|
||||
"disallowedAction": "एक्सटेंशन सक्षम",
|
||||
"failed": "स्थिति का अनुरोध करने में विफल",
|
||||
"loading": "आपके द्वारा एक्सटेंशन इंस्टॉल करने की प्रतीक्षा की जा रही है",
|
||||
"outdated": "एक्सटेंशन संस्करण बहुत पुराना है",
|
||||
"success": "एक्सटेंशन अपेक्षा के अनुरूप काम कर रहा है!"
|
||||
},
|
||||
"submit": "जारी रखना",
|
||||
"title": "आइए एक एक्सटेंशन से शुरू करें"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "वापस जाओ",
|
||||
"explainer": "प्रॉक्सी विधि से, आप स्वयं-सेवा प्रॉक्सी बनाकर बढ़िया गुणवत्ता वाली स्ट्रीम प्राप्त कर सकते हैं।",
|
||||
"input": {
|
||||
"errorConnection": "प्रॉक्सी से कनेक्ट नहीं हो सका",
|
||||
"errorInvalidUrl": "मान्य यूआरएल नहीं",
|
||||
"errorNotProxy": "एक प्रॉक्सी की उम्मीद थी लेकिन एक वेबसाइट मिली",
|
||||
"label": "प्रॉक्सी यूआरएल",
|
||||
"placeholder": "https://"
|
||||
},
|
||||
"link": "પ્રોક્સી કેવી રીતે બનાવવી તે જાણો",
|
||||
"submit": "प्रॉक्सी सबमिट करें",
|
||||
"title": "आइए एक नई प्रॉक्सी बनाएं"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "सर्वोत्तम संभव स्ट्रीम प्राप्त करने के लिए, आपको यह चुनना होगा कि आप किस स्ट्रीमिंग विधि का उपयोग करना चाहते हैं।",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "मुझे अच्छी गुणवत्ता वाली स्ट्रीम नहीं चाहिए,<0 /> <1>डिफ़ॉल्ट सेटअप का उपयोग करें</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "एक्सटेंशन इंस्टॉल करें",
|
||||
"description": "ब्राउज़र एक्सटेंशन इंस्टॉल करें और सर्वोत्तम स्रोतों तक पहुंच प्राप्त करें।",
|
||||
"quality": "अच्छी गुणवत्ता",
|
||||
"title": "ब्राउज़र एक्सटेंशन"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "प्रॉक्सी सेटअप करें",
|
||||
"description": "केवल 5 मिनट में एक प्रॉक्सी सेटअप करें और बेहतरीन स्रोतों तक पहुंच प्राप्त करें।",
|
||||
"quality": "अच्छी गुणवत्ता",
|
||||
"title": "कस्टम प्रॉक्सी"
|
||||
}
|
||||
},
|
||||
"title": "आइए आपको मूवी-वेब के साथ सेटअप करवाते हैं"
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "बंद करना"
|
||||
},
|
||||
@ -182,7 +246,7 @@
|
||||
"downloadPlaylist": "प्लेलिस्ट डाउनलोड करें",
|
||||
"downloadSubtitle": "वर्तमान उपशीर्षक डाउनलोड करें",
|
||||
"downloadVideo": "वीडियो डाउनलोड करें",
|
||||
"hlsDisclaimer": "डाउनलोड सीधे प्रदाता से लिए जाते हैं। मूवी-वेब का इस पर नियंत्रण नहीं है कि डाउनलोड कैसे प्रदान किए जाते हैं। कृपया ध्यान दें कि आप एक एचएलएस प्लेलिस्ट डाउनलोड कर रहे हैं, यह उन्नत मल्टीमीडिया स्ट्रीमिंग से परिचित उपयोगकर्ताओं के लिए है।",
|
||||
"hlsDisclaimer": "डाउनलोड सीधे प्रदाता से लिए जाते हैं। मूवी-वेब का इस पर नियंत्रण नहीं है कि डाउनलोड कैसे प्रदान किए जाते हैं।<br /><br />कृपया ध्यान दें कि आप एक HLS प्लेलिस्ट डाउनलोड कर रहे हैं, <bold>यदि आप उन्नत स्ट्रीमिंग प्रारूपों से परिचित नहीं हैं तो इसे डाउनलोड करने की अनुशंसा नहीं की जाती है</bold>। विभिन्न प्रारूपों के लिए अलग-अलग स्रोत आज़माएँ।",
|
||||
"onAndroid": {
|
||||
"1": "एंड्रॉइड पर डाउनलोड करने के लिए, डाउनलोड बटन पर क्लिक करें, फिर नए पेज पर, वीडियो पर <bold>टैप करके रखें</bold>, फिर <bold>save</bold> चुनें।",
|
||||
"shortTitle": "डाउनलोड / एंड्रॉइड",
|
||||
@ -263,6 +327,17 @@
|
||||
"text": "एपीआई मेटाडेटा लोड नहीं हो सका, कृपया अपना इंटरनेट कनेक्शन जांचें।",
|
||||
"title": "एपीआई मेटाडेटा लोड करने में विफल"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "निकाला गया",
|
||||
"text": "निष्कासन नोटिस या कॉपीराइट दावे के कारण यह मीडिया अब उपलब्ध नहीं है।",
|
||||
"title": "मीडिया हटा दिया गया है"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "अनुमति अनुपलब्ध",
|
||||
"button": "एक्सटेंशन का उपयोग करें",
|
||||
"text": "आपके पास ब्राउज़र एक्सटेंशन है, लेकिन एक्सटेंशन का उपयोग शुरू करने के लिए हमें आपकी अनुमति की आवश्यकता है।",
|
||||
"title": "एक्सटेंशन कॉन्फ़िगर करें"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "असफल",
|
||||
"homeButton": "घर जाओ",
|
||||
@ -390,24 +465,49 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "यदि आप अपना डेटा संग्रहीत करने के लिए कस्टम बैकएंड से कनेक्ट करना चाहते हैं, तो इसे सक्षम करें और URL प्रदान करें।",
|
||||
"description": "यदि आप अपना डेटा संग्रहीत करने के लिए कस्टम बैकएंड से कनेक्ट करना चाहते हैं, तो इसे सक्षम करें और URL प्रदान करें। <0>निर्देश।</0>",
|
||||
"label": "कस्टम सर्वर",
|
||||
"urlLabel": "कस्टम सर्वर यूआरएल"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "सेटअप करें",
|
||||
"errorStatus": {
|
||||
"description": "ऐसा लगता है कि इस सेटअप में एक या अधिक आइटम पर आपके ध्यान की आवश्यकता है।",
|
||||
"title": "किसी चीज़ पर आपका ध्यान चाहिए"
|
||||
},
|
||||
"itemError": "इस सेटिंग में कुछ गड़बड़ है। इसे ठीक करने के लिए फिर से सेटअप से गुजरें।",
|
||||
"items": {
|
||||
"default": "डिफ़ॉल्ट सेटअप",
|
||||
"extension": "विस्तार",
|
||||
"proxy": "कस्टम प्रॉक्सी"
|
||||
},
|
||||
"redoSetup": "सेटअप पुनः करें",
|
||||
"successStatus": {
|
||||
"description": "अपना पसंदीदा मीडिया देखना शुरू करने के लिए सभी चीज़ें मौजूद हैं।",
|
||||
"title": "सब कुछ व्यवस्थित है!"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "सेटअप प्रक्रिया शुरू करने के लिए कृपया दाईं ओर बटन पर क्लिक करें।",
|
||||
"title": "आप सेटअप से नहीं गुजरे हैं"
|
||||
}
|
||||
},
|
||||
"title": "सम्बन्ध",
|
||||
"workers": {
|
||||
"addButton": "नया कार्यकर्ता जोड़ें",
|
||||
"description": "एप्लिकेशन को कार्यशील बनाने के लिए, सभी ट्रैफ़िक को प्रॉक्सी के माध्यम से रूट किया जाता है। यदि आप अपने स्वयं के श्रमिकों को लाना चाहते हैं तो इसे सक्षम करें।",
|
||||
"description": "एप्लिकेशन को कार्यशील बनाने के लिए, सभी ट्रैफ़िक को प्रॉक्सी के माध्यम से रूट किया जाता है। यदि आप अपने स्वयं के श्रमिकों को लाना चाहते हैं तो इसे सक्षम करें। <0>निर्देश।</0>",
|
||||
"emptyState": "अभी तक कोई कर्मचारी नहीं, नीचे एक जोड़ें",
|
||||
"label": "कस्टम प्रॉक्सी कार्यकर्ताओं का उपयोग करें",
|
||||
"urlLabel": "कार्यकर्ता यूआरएल",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"preferences": {
|
||||
"language": "अनुप्रयोग भाषा",
|
||||
"languageDescription": "भाषा संपूर्ण अनुप्रयोग पर लागू होती है।",
|
||||
"title": "स्थानीय"
|
||||
"thumbnail": "थंबनेल जनरेट करें",
|
||||
"thumbnailDescription": "अधिकांश समय, वीडियो में थंबनेल नहीं होते हैं। आप उन्हें तुरंत उत्पन्न करने के लिए इस सेटिंग को सक्षम कर सकते हैं लेकिन वे आपके वीडियो को धीमा कर सकते हैं।",
|
||||
"thumbnailLabel": "थंबनेल जनरेट करें",
|
||||
"title": "पसंद"
|
||||
},
|
||||
"reset": "रीसेट",
|
||||
"save": "सेव",
|
||||
|
@ -393,11 +393,6 @@
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"language": "Bahasa aplikasi",
|
||||
"languageDescription": "Bahasa yang akan digunakan di seluruh aplikasi.",
|
||||
"title": "Bahasa"
|
||||
},
|
||||
"reset": "Reset",
|
||||
"save": "Simpan",
|
||||
"sidebar": {
|
||||
|
523
src/assets/locales/is-IS.json
Normal file
523
src/assets/locales/is-IS.json
Normal file
@ -0,0 +1,523 @@
|
||||
{
|
||||
"about": {
|
||||
"description": "movie-web er vefforrit sem leitar á netinu að straumum. Markmið liðsins er naumhyggju nálgun á að horfa á efni.",
|
||||
"faqTitle": "Algengar spurningar",
|
||||
"q1": {
|
||||
"body": "movie-web hýsir ekki neitt efni. Þegar þú ýtir á eitthvað til að horfa á, leitað er á netinu fyrir það efni (Þú getur séð hvaða heimild við erum að nota á hleðslu skjánum og í 'myndbands heimildir' flipanum). Skrár eru aldrei settar in af movie-web, allt er í gegnum leitarvél.",
|
||||
"title": "Hvaðan kemur efnið?"
|
||||
},
|
||||
"q2": {
|
||||
"body": "Þú getur ekki beðið um þætti eða myndir, movie-web stýrir ekki neinu efni. Allt efni er skoðað í gegnum heimildir á netinu.",
|
||||
"title": "Hvar get ég beðið um þætti eða myndir?"
|
||||
},
|
||||
"q3": {
|
||||
"body": "Okkar leitar niðurstöður eru knúnar af The Movie Database (TMDB) og eru sýndar þótt að okkar heimildir hafa ekki efnið.",
|
||||
"title": "Leitarniðurstöðurnar sýna þættina eða myndina, af hverju get ég ekki spilað það?"
|
||||
},
|
||||
"title": "Um movie-web"
|
||||
},
|
||||
"actions": {
|
||||
"copied": "Afritað",
|
||||
"copy": "Afrita"
|
||||
},
|
||||
"auth": {
|
||||
"createAccount": "Hefurðu ekki reikning ennþá? <0>Búðu til reikning.</0>",
|
||||
"deviceNameLabel": "Nafn tækis",
|
||||
"deviceNamePlaceholder": "Einkasími",
|
||||
"generate": {
|
||||
"description": "Þitt lykilorð lætur eins og notandanafn og lykilorð. Vertu viss um að halda því öruggu út að þú munt þurfa að nota það til að komast inn í reikningin þinn",
|
||||
"next": "Ég hef vistað lykilorðið mitt",
|
||||
"passphraseFrameLabel": "Lykilorð",
|
||||
"title": "Þitt lykilorð"
|
||||
},
|
||||
"hasAccount": "Hefurðu reikning nú þegar? <0>Skráðu þig inn hér.</0>",
|
||||
"login": {
|
||||
"description": "Vinsamlegast sláðu inn lykilorðið þitt til þess að skrá þig inn í reikningin þinn",
|
||||
"deviceLengthError": "Vinsamlegast settu inn nafn fyrir tækið þitt",
|
||||
"passphraseLabel": "12-Orða lykilorð",
|
||||
"passphrasePlaceholder": "Lykilorð",
|
||||
"submit": "Skrá inn",
|
||||
"title": "Skráðu þig inn í reikningin þinn",
|
||||
"validationError": "Vitlaust eða óklárað lykilorð"
|
||||
},
|
||||
"register": {
|
||||
"information": {
|
||||
"color1": "Prófíl litur eitt",
|
||||
"color2": "Prófíl litur tvö",
|
||||
"header": "Sláðu inn nafn fyrir tækið þitt og veldu liti og notanda tákn að þínu vali",
|
||||
"icon": "Notanda tákn",
|
||||
"next": "Næst",
|
||||
"title": "Reiknings upplýsingar"
|
||||
}
|
||||
},
|
||||
"trust": {
|
||||
"failed": {
|
||||
"text": "Stilltirðu það rétt?",
|
||||
"title": "Náðist ekki í netþjón"
|
||||
},
|
||||
"host": "Þú ert að tengjast við <0>{{hostname}}</0> - vinsamlegast staðfestu að þú treystir því áður en þú býrð til reikning",
|
||||
"no": "Fara til baka",
|
||||
"title": "Treystir þú þessum netþjóni?",
|
||||
"yes": "Ég treysti þessum netþjóni"
|
||||
},
|
||||
"verify": {
|
||||
"description": "Vinsamlegst sláðu inn lykilorðið þitt frá því áðan til þess að staðfesta að þú hefur vistað það og til að stofna nýjan reikning",
|
||||
"invalidData": "Gögn eru ekki gild",
|
||||
"noMatch": "Lykilorð passar ekki saman",
|
||||
"passphraseLabel": "Þitt 12-orða lykilorð",
|
||||
"recaptchaFailed": "ReCaptcha staðfesting mistókst",
|
||||
"register": "Stofna reikning",
|
||||
"title": "Staðfestu þitt lykilorð"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"badge": "Það bilaði",
|
||||
"details": "Villu upplýsingar",
|
||||
"reloadPage": "Endurhlaðaðu vefsíðuna",
|
||||
"showError": "Sýna villu upplýsingar",
|
||||
"title": "Við lentum í villu!"
|
||||
},
|
||||
"footer": {
|
||||
"legal": {
|
||||
"disclaimer": "Fyrirvari",
|
||||
"disclaimerText": "movie-web hýsir engar skrár, það tengist eingöngu þjónustu þriðja aðila. Lagleg atriði ættu að vera rædd við skráarhýsinga og veitanda. movie-web er ekki ábyrg fyrir neinum skrám sýndar af myndbands veitöndum."
|
||||
},
|
||||
"tagline": "Horfðu á uppáhalds þætti og myndirnar þínar með þessu opna hugbúnaða forriti."
|
||||
},
|
||||
"global": {
|
||||
"pages": {
|
||||
"about": "Um",
|
||||
"login": "Skrá inn",
|
||||
"onboarding": "Setja upp",
|
||||
"register": "Skrá",
|
||||
"settings": "Stillingar"
|
||||
}
|
||||
},
|
||||
"home": {
|
||||
"bookmarks": {
|
||||
"sectionTitle": "Bókamerki"
|
||||
},
|
||||
"continueWatching": {
|
||||
"sectionTitle": "Haltu Áfram Að Horfa"
|
||||
},
|
||||
"mediaList": {
|
||||
"stopEditing": "Hætta að breyta"
|
||||
},
|
||||
"search": {
|
||||
"allResults": "Þetta er allt sem við höfum!",
|
||||
"failed": "Mostókst að finna miðil, reyndu aftur!",
|
||||
"loading": "Hlaðið...",
|
||||
"noResults": "Við gátum ekki fundið neitt!",
|
||||
"placeholder": "Hvað viltu horfa á?",
|
||||
"sectionTitle": "Leitar niðurstöður"
|
||||
},
|
||||
"titles": {
|
||||
"day": {
|
||||
"default": "Hvað myndirðu vilja horfa á þetta kvöldið?",
|
||||
"extra": [
|
||||
"Fynnst þér þú vera ævintýralegur? Jurrasic Park gæti verið fullkomna valið."
|
||||
]
|
||||
},
|
||||
"morning": {
|
||||
"default": "Hvað myndirðu vilja horfa á þessum morgni?",
|
||||
"extra": [
|
||||
"Ég heyrði að Before Sunrise sé góð"
|
||||
]
|
||||
},
|
||||
"night": {
|
||||
"default": "Hvað myndirðu vilja horfa á í nótt?",
|
||||
"extra": [
|
||||
"Þreytt? Ég heyrði að The Exorcist sé góð."
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"media": {
|
||||
"episodeDisplay": "S{{season}} Þ{{episode}}",
|
||||
"types": {
|
||||
"movie": "Mynd",
|
||||
"show": "Þáttur"
|
||||
}
|
||||
},
|
||||
"navigation": {
|
||||
"banner": {
|
||||
"offline": "Athugaðu net tengingu þína"
|
||||
},
|
||||
"menu": {
|
||||
"about": "Um okkur",
|
||||
"donation": "Styrkja",
|
||||
"logout": "Skrá út",
|
||||
"register": "Samstilla við ský",
|
||||
"settings": "Stillingar",
|
||||
"support": "Stuðningur"
|
||||
}
|
||||
},
|
||||
"notFound": {
|
||||
"badge": "Ekki fundið",
|
||||
"goHome": "Aftur heim",
|
||||
"message": "Við leituðum alls staðar: undir ruslafötunum, inn í skápnum, á bakvið proxy þjónin en við gátum ekki fundið síðuna sem þú ert að leita af.",
|
||||
"title": "Gat ekki fundið síðu"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "Hætta við",
|
||||
"confirm": "Nota venjulegu uppsetninguna",
|
||||
"description": "Venjulega uppsetningin hefur ekki bestu streymin og getur verið óþolandi og hæg.",
|
||||
"title": "Ertu viss?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "Til baka",
|
||||
"explainer": "þú getur fengið bestu streymi sem við höfum með því að nota viðbótið. Bara með einfaldri niðurhalningu.",
|
||||
"explainerIos": "Því miður, er viðbótið ekki stytt á iOS, Ýttu á <bold>Til baka</bold> til að velja annan möguleika.",
|
||||
"extensionHelp": "Ef þú hefur hlaðað niður viðbótinu en það er ekki greint, <bold>opnaðu viðbótið í gegnum net viðbóts valmyndina þína</bold> og fylgdu skrefin á skjánum.",
|
||||
"linkChrome": "Sækja Chrome viðbót",
|
||||
"linkFirefox": "Sækja Firefox viðbót",
|
||||
"notDetecting": "Hlaðað niður á Chrome, en síðan er ekki að greina það? Reyndu að endurhlaða síðunna!",
|
||||
"notDetectingAction": "Endurhlaða síðu",
|
||||
"status": {
|
||||
"disallowed": "VIðbót er ekki virkt fyrir þessa síðu",
|
||||
"disallowedAction": "Virkja viðbót",
|
||||
"failed": "Mistókst að biðja um stöðu",
|
||||
"loading": "Bíðandi eftir að þú sækjir viðbótið",
|
||||
"outdated": "Viðbóts útgáfa of gömul",
|
||||
"success": "Viðbót virkar eins og gert ráð fyrir!"
|
||||
},
|
||||
"submit": "Halda áfram",
|
||||
"title": "Byrjum með viðbóti"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "Til baka",
|
||||
"explainer": "Með umboðs aðferðinni, getur þú fengið frábær gæði strauma með því að búa til sjálfsafgreitt umboð.",
|
||||
"input": {
|
||||
"errorConnection": "Gat ekki tengst umboð",
|
||||
"errorInvalidUrl": "Ekki gildur hlekkur",
|
||||
"errorNotProxy": "Bjóst við umboði en fékk heimasíðu",
|
||||
"label": "Umboðs hlekkur"
|
||||
},
|
||||
"link": "Lærðu hvernig þú býrð til umboð",
|
||||
"submit": "Staðfesta umboð",
|
||||
"title": "Búum til nýtt umboð"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "Til þess að fá bestu möguleg streymi, þú verður að velja hvaða streymis aðferð þér langar að nota.",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "Mig langar ekki í strymi með góðum gæðum,<0 /> <1>notaðu venjulegu uppsetninguna</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "Hlaðaðu niður viðbóti",
|
||||
"description": "Hlaðaðu niður viðbótinu og fáðu aðgang að frábærra heimilda.",
|
||||
"quality": "Bestu gæði",
|
||||
"title": "Viðbót"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "Settu upp umboð",
|
||||
"description": "Settu upp umboð á 5 mínútum og fáðu aðgang til frábærra heimilda.",
|
||||
"quality": "Góð gæði",
|
||||
"title": "Sérsniðið umboð"
|
||||
}
|
||||
},
|
||||
"title": "Komum þér í uppsetningu með movie-web"
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "Loka"
|
||||
},
|
||||
"player": {
|
||||
"back": {
|
||||
"default": "Aftur heim",
|
||||
"short": "Til baka"
|
||||
},
|
||||
"casting": {
|
||||
"enabled": "Steypandi í tæki..."
|
||||
},
|
||||
"menus": {
|
||||
"downloads": {
|
||||
"disclaimer": "Niðurhalningar eru teknar beint frá heimildini. movie-web hefur engan kraft yfir hvernig niðurhalningarnar eru gefnar.",
|
||||
"downloadPlaylist": "Hlaða niður spilarlista",
|
||||
"downloadSubtitle": "Hlaða niður nú verandi texta",
|
||||
"downloadVideo": "Hlaða niður myndbandi",
|
||||
"hlsDisclaimer": "Niðurhalningar eru teknar beint frá heimildini. movie-web hefur engan kraft yfir hvernig niðurhalningarnar eru gefnar.<br /><br />Vinsamlegast fattaðu að þú ert að niðurhala HLS spilunarlista, <bold>það er ekki mælt með að niðurhala ef þú kannt ekki mikið á háþróað streymis sniði.</bold>. Reyndu aðrar heimildir fyrir önnur sniði.",
|
||||
"onAndroid": {
|
||||
"1": "Til þess að niðurhala á Android, ýttu á niðurhalningar takkan síðan, á nýju síðunni, <bold>smelltu og haltu niðri</bold> á myndbandinu, veldu síðan <bold>vista</bold>.",
|
||||
"shortTitle": "Hlaða niður / Android",
|
||||
"title": "Að hlaða niður á Android"
|
||||
},
|
||||
"onIos": {
|
||||
"1": "Til þess að niðurhala á iOS, ýttu á niðurhalninga takkan síðan, á nýju síðunni, ýttu á <bold><ios_share /></bold>, síðan <bold>Vista í skrár <ios_files /></bold>.",
|
||||
"shortTitle": "Hlaða niður / iOS",
|
||||
"title": "Að hlaða niður á iOS"
|
||||
},
|
||||
"onPc": {
|
||||
"1": "Á PC, ýttu á niðurhalningar takkan síðan, á nýju síðunni, hægri smelltu á myndbandið og veldu <bold>Vista myndband sem</bold>",
|
||||
"shortTitle": "Hlaða niður / PC",
|
||||
"title": "Að hlaða niður á PC"
|
||||
},
|
||||
"title": "Hlaða niður"
|
||||
},
|
||||
"episodes": {
|
||||
"button": "Þættir",
|
||||
"emptyState": "Það eru engir þættir í þessari seríu, kíktu aftur seinna!",
|
||||
"episodeBadge": "Þ{{episode}}",
|
||||
"loadingError": "Villa að hlaða seríu",
|
||||
"loadingList": "Hleðsla...",
|
||||
"loadingTitle": "Hleðsla...",
|
||||
"unairedEpisodes": "Einn eða fleiri þættir í þessari seríu eru ekki komnir, út að þeir hafa ekki komið út."
|
||||
},
|
||||
"playback": {
|
||||
"speedLabel": "Spilunarhraði",
|
||||
"title": "Spilunar stillingar"
|
||||
},
|
||||
"quality": {
|
||||
"automaticLabel": "Sjálfkrafa gæði",
|
||||
"hint": "Þú getur reynt að <0>skipta um heimild</0>til að fá öðruvísi gæða valkosti.",
|
||||
"iosNoQuality": "Vegna takmörkum á Apple tækjum er ekki hægt að breyta um gæði á iOS með þessari heimild. Þú getur reynt að <0>breyta í aðra heimild</0> til að fá mismunandi gæðastillingar.",
|
||||
"title": "Gæði"
|
||||
},
|
||||
"settings": {
|
||||
"downloadItem": "Niðurhala",
|
||||
"enableSubtitles": "Virkja texta",
|
||||
"experienceSection": "Útsýnis upplifun",
|
||||
"playbackItem": "Spilunar stillingar",
|
||||
"qualityItem": "Gæði",
|
||||
"sourceItem": "Myndbands heimildir",
|
||||
"subtitleItem": "Texta stillingar",
|
||||
"videoSection": "Myndbands stillingar"
|
||||
},
|
||||
"sources": {
|
||||
"failed": {
|
||||
"text": "Það kom upp villa á meðan við vorum að reyna að finna myndbönd, vinsamlegast reyndu að nota aðra heimild.",
|
||||
"title": "Skröpun mistókst"
|
||||
},
|
||||
"noEmbeds": {
|
||||
"text": "Við gátum ekki fundið neina innfellu, vinsamlegast reyndu að nota aðra heimild.",
|
||||
"title": "Engar innifellur fundnar"
|
||||
},
|
||||
"noStream": {
|
||||
"text": "Þessi heimild hefur engin streymi fyrir þessa mynd eða þætti.",
|
||||
"title": "Ekkert streymi"
|
||||
},
|
||||
"title": "Heimildir",
|
||||
"unknownOption": "Óvitað"
|
||||
},
|
||||
"subtitles": {
|
||||
"customChoice": "Veldu texta frá skrá",
|
||||
"customizeLabel": "Sérsníða",
|
||||
"offChoice": "Af",
|
||||
"settings": {
|
||||
"backlink": "Sérsniðir textar",
|
||||
"delay": "Texta seinkun",
|
||||
"fixCapitals": "Lagaðu hástafi"
|
||||
},
|
||||
"title": "Textar",
|
||||
"unknownLanguage": "Óvitað"
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"api": {
|
||||
"text": "Gat ekki hlaðið API lýsigögn, vinsamlegast kíktu á nettenginguna þína.",
|
||||
"title": "Mistókst að hlaða API lýsigögnum"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "Fjarlæga",
|
||||
"text": "Þessi miðill er ekki lengur fáanlegur út af hann hefur verið tekin niður handvirkt eða vegna höfundarréttarbrota.",
|
||||
"title": "Miðill hefur verið fjarlægður"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "Leyfi vantar",
|
||||
"button": "Nota viðbótina",
|
||||
"text": "Þú hefur viðbótina, en við þurfum leyfið þitt til að geta byrjað að nota hana.",
|
||||
"title": "Stilltu viðbótina"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "Mistókst",
|
||||
"homeButton": "Fara heim",
|
||||
"text": "Gat ekki hlaðið lýsingar um miðilin frá TMDB. Vinsamlegast kíktu hvort að TMBD er niðri eða læst á netinu þínu.",
|
||||
"title": "Mistókst að hlaða lýsingum"
|
||||
},
|
||||
"notFound": {
|
||||
"badge": "Ekki fundið",
|
||||
"homeButton": "Aftur heim",
|
||||
"text": "Við gátum ekki fundið miðilin sem þú baðst um. Annað hvort hefur hann verið fjarlægður eða þú hefur átt við hlekkin.",
|
||||
"title": "Gat ekki fundið miðil."
|
||||
}
|
||||
},
|
||||
"nextEpisode": {
|
||||
"cancel": "Hætta við",
|
||||
"next": "Næsti þáttur"
|
||||
},
|
||||
"playbackError": {
|
||||
"badge": "Spilunar villa",
|
||||
"errors": {
|
||||
"errorAborted": "Hætt var við að sækja miðilin út af beiðni notandans.",
|
||||
"errorDecode": "Þrátt fyrir að áður var sagt að þetta væro nothæft, villa kom upp meðan við vorum að reyna að afkóða miðilin, sem leiddi til villu.",
|
||||
"errorGenericMedia": "Óvituð miðla villa átti sér stað.",
|
||||
"errorNetwork": "Einhvernskonar net villa kom up sem kom í veg fyrir að það tókst að sækja miðilin, þrátt fyrir að áður var það hægt.",
|
||||
"errorNotSupported": "Miðillin eða miðla heimildin er ekki studdar."
|
||||
},
|
||||
"homeButton": "Fara heim",
|
||||
"text": "Það kom upp villa meðan reynt var að horfa á miðilin. Vinsamlegast reyndu aftur.",
|
||||
"title": "Spilun myndbands mistóksts!"
|
||||
},
|
||||
"scraping": {
|
||||
"items": {
|
||||
"failure": "Villa kom upp",
|
||||
"notFound": "Hefur ekki myndbandið",
|
||||
"pending": "Leitandi af myndböndum..."
|
||||
},
|
||||
"notFound": {
|
||||
"badge": "Ekki fundið",
|
||||
"detailsButton": "Sýna smáatriði",
|
||||
"homeButton": "Fara heim",
|
||||
"text": "Við höfun leitað í heimildum okkar og getum ekki fundið miðilin sem þú ert að leita að! Við hýsum ekki miðlana og höfum enga stjórn yfir hvað er fáanlegt. Visnamlegast ýttu á 'Sýna smáatriði' fyrir neðan þennan texta fyrir fleiri smáatriði.",
|
||||
"title": "Við gátum ekki fundið þetta"
|
||||
}
|
||||
},
|
||||
"time": {
|
||||
"remaining": "{{timeLeft}} er eftir • Þú klárar {{timeFinished, datetime}}"
|
||||
},
|
||||
"turnstile": {
|
||||
"description": "Vinsamlegast sannreyndu að þú sért manneskja með því að klára Captcha-ið til hægri. Þetta er til þess að halda movie-web öruggu!",
|
||||
"error": "Mistókst að sannreyna að þú sért manneskja. Vinsamlegast reyndu aftur.",
|
||||
"title": "Við þurfum að sannræna að þú ert manneskja.",
|
||||
"verifyingHumanity": "Að sannræna að þú sért manneskja..."
|
||||
}
|
||||
},
|
||||
"screens": {
|
||||
"dmca": {
|
||||
"text": "Velkomin á sambands síðu movie-web! Við virðum hugverkarétt og viljum ræða einhver höfundarréttar áhyggjur fljótt. Ef að þú trúir að höfundarréttur þíns verks hefur verið misnotaður á okkar síðu, vinsamlegast sentu ítarlega DMCA tilkynningu til netfangsing fyrir neðan þennan texta. Vinsamlegast láttu fylgja með lýsingu af höfundaréttavarna efninu, tengiliða upplýsingat þínar, og yfirlýsingu um góða trú. Við erum staðráðin í að leysa þessi mál tafarlaust og þökkum samstarf þitt við að halda movie-web stað sem virðir sköpunargáfu og höfundarrétt."
|
||||
},
|
||||
"loadingApp": "Hlaðandi forriti",
|
||||
"loadingUser": "Hlaðandi þínum reikningi",
|
||||
"loadingUserError": {
|
||||
"logout": "Skrá út",
|
||||
"reset": "Endurstilla sérsniðin netþjón",
|
||||
"text": "Mistókst að hlaða inn reikningnum þínum",
|
||||
"textWithReset": "Mistókst að hlaða inn reikningnum þínum af sérsniðna netþjóninum þínum, villtu fara aftur á venjulega netþjónin?"
|
||||
},
|
||||
"migration": {
|
||||
"failed": "Mistókst að flytja gögnin þín.",
|
||||
"inProgress": "Vinsamlegast bíddu, við erum að flytja gögnin þín. Þetta ætti ekki að taka langan tíma."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"account": {
|
||||
"accountDetails": {
|
||||
"deviceNameLabel": "Nafn tækis",
|
||||
"deviceNamePlaceholder": "Einkasími",
|
||||
"editProfile": "Breyta",
|
||||
"logoutButton": "Skrá út"
|
||||
},
|
||||
"actions": {
|
||||
"delete": {
|
||||
"button": "Eyða reikning",
|
||||
"confirmButton": "Eyða reikning",
|
||||
"confirmDescription": "Ertu viss um að þú villt eyða aðganginum þínum? Öll gögnin þín verða eydd!",
|
||||
"confirmTitle": "Ertu viss?",
|
||||
"text": "Það er ekki hægt að taka þetta til baka. Öll gögn munu verða eydd og ekkert getur verið tekið til baka.",
|
||||
"title": "Eyða reikningi"
|
||||
},
|
||||
"title": "Aðgerðir"
|
||||
},
|
||||
"devices": {
|
||||
"deviceNameLabel": "Nafn tækis",
|
||||
"failed": "Mistókst að hlaða fundum",
|
||||
"removeDevice": "Eyða",
|
||||
"title": "Tæki"
|
||||
},
|
||||
"profile": {
|
||||
"finish": "Klára breytingar",
|
||||
"firstColor": "Reiknings litur eitt",
|
||||
"secondColor": "Reiknings litur tvö",
|
||||
"title": "Breyta mynd reiknings",
|
||||
"userIcon": "Notandatákn"
|
||||
},
|
||||
"register": {
|
||||
"cta": "Byrja",
|
||||
"text": "Deildu áhorfunar tíma á milli tækja og haltu þeimsamstilltum.",
|
||||
"title": "Samstilla við skýið"
|
||||
},
|
||||
"title": "Reikningur"
|
||||
},
|
||||
"appearance": {
|
||||
"activeTheme": "Virkur",
|
||||
"themes": {
|
||||
"blue": "Blár",
|
||||
"default": "Venjulegt",
|
||||
"gray": "Grár",
|
||||
"red": "Rauður",
|
||||
"teal": "Blágló"
|
||||
},
|
||||
"title": "Útlit"
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "Ef þú villt tengjast sérsniðin bakendi til að geyma gögnin þín, virktu þetta og gefðu upp hlekkin. <0>Leiðbeiningar.</0>",
|
||||
"label": "Sérsniðin netþjónn",
|
||||
"urlLabel": "Sérsniðinn netþjóns hlekkur"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "Gera uppsetningu",
|
||||
"errorStatus": {
|
||||
"description": "Það er einn að fleiri hlutir í þessari uppsetningu sem þarf athygli þína.",
|
||||
"title": "Eitthvað þarf athygli þína"
|
||||
},
|
||||
"itemError": "Það er eitthvað rangt við þessa stillingu. Farðu í gegnum uppsetningu aftur til að laga hana.",
|
||||
"items": {
|
||||
"default": "Venjuleg uppsetning",
|
||||
"extension": "Viðbót",
|
||||
"proxy": "Sérsniðið umboð"
|
||||
},
|
||||
"redoSetup": "Endurtaka uppsetningu",
|
||||
"successStatus": {
|
||||
"description": "Allt er á sama stað fyrir þig að byrja að horfa á uppáhalds miðilin þinn.",
|
||||
"title": "Allt er sett upp!"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "Vinsamlegast ýttu á takkan til hægri til að byrja uppsetningu.",
|
||||
"title": "Þú hefur ekki farið í gegnum uppsetningu"
|
||||
}
|
||||
},
|
||||
"title": "Tengingar",
|
||||
"workers": {
|
||||
"addButton": "Bættu við nýjum starfsmanni",
|
||||
"description": "Til að láta forritið virka, allri umboð er beint í gegnum umboð. Virktu þetta ef þú villt koma með þína eigin starfsmenn. <0>Leiðbeiningar.</0>",
|
||||
"emptyState": "Engir starfsmenn komnir, bættu við einum fyir neðan þennan texta",
|
||||
"label": "Notaðu sérsniðaða umboðs starfsmenn",
|
||||
"urlLabel": "Starfsmanna hlekkir"
|
||||
}
|
||||
},
|
||||
"preferences": {
|
||||
"language": "Tungumál forrits",
|
||||
"languageDescription": "Tungumál beitt á allt forritið.",
|
||||
"thumbnail": "Búa til smámyndir",
|
||||
"thumbnailDescription": "Oftast, hafa myndbönd ekki smámyndir. Þú getur látið þessa stillingu gera þær en það gæti gert myndbandið þitt hægara.",
|
||||
"thumbnailLabel": "Gera smámyndir",
|
||||
"title": "Valstillingar"
|
||||
},
|
||||
"reset": "Endurstilla",
|
||||
"save": "Vista",
|
||||
"sidebar": {
|
||||
"info": {
|
||||
"appVersion": "Útgáfa forrits",
|
||||
"backendUrl": "Bakenda hlekkur",
|
||||
"backendVersion": "Bakenda útgáfa",
|
||||
"hostname": "Hýsingarheiti",
|
||||
"insecure": "Óöruggt",
|
||||
"notLoggedIn": "Þú ert ekki skrátt inn",
|
||||
"secure": "Örrugt",
|
||||
"title": "Forrits upplýsingar",
|
||||
"unknownVersion": "Óvitað",
|
||||
"userId": "Notanda kóði"
|
||||
}
|
||||
},
|
||||
"subtitles": {
|
||||
"backgroundLabel": "Bakgrunnar gegnsægi",
|
||||
"colorLabel": "Litur",
|
||||
"previewQuote": "Ég má ekki óttast. Ótti er hugardrepandi.",
|
||||
"textSizeLabel": "Texta stærð",
|
||||
"title": "Textar"
|
||||
},
|
||||
"unsaved": "Þú hefur óvistaðar breytingar"
|
||||
}
|
||||
}
|
@ -95,6 +95,7 @@
|
||||
"about": "Su di movie-web",
|
||||
"dmca": "DMCA",
|
||||
"login": "Accedi",
|
||||
"onboarding": "Setup",
|
||||
"pagetitle": "{{title}} - movie-web",
|
||||
"register": "Registrarsi",
|
||||
"settings": "Impostazioni"
|
||||
@ -120,19 +121,19 @@
|
||||
},
|
||||
"titles": {
|
||||
"day": {
|
||||
"default": "Cosa vorresti vedere questo pomeriggio?",
|
||||
"default": "Cosa vorresti guardare questo pomeriggio?",
|
||||
"extra": [
|
||||
"Senti avventuroso? Jurassic Park potrebbe essere la scelta perfetta."
|
||||
]
|
||||
},
|
||||
"morning": {
|
||||
"default": "Cosa vorresti vedere questa mattina?",
|
||||
"default": "Cosa vorresti guardare questa mattina?",
|
||||
"extra": [
|
||||
"Ho sentito che «Prima Dell'alba» è buono"
|
||||
]
|
||||
},
|
||||
"night": {
|
||||
"default": "Cosa vorresti vedere questa stasera?",
|
||||
"default": "Cosa vorresti guardare questa sera?",
|
||||
"extra": [
|
||||
"Stanco? Ho sentito che L'esorciccio è buono."
|
||||
]
|
||||
@ -165,6 +166,69 @@
|
||||
"message": "Abbiamo cercato ovunque: sotto i bidoni, nell'armadio, dietro il proxy, ma alla fine non siamo riusciti a trovare la pagina che stai cercando.",
|
||||
"title": "Impossibile trovare quella pagina"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "Annulla",
|
||||
"confirm": "Utilizzare setup predefinita",
|
||||
"description": "Il setup predefinita non offre i migliori stream e può essere incredibilmente lento.",
|
||||
"title": "Sei sicuro?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "Torna indietro",
|
||||
"explainer": "Utilizzando l'estensione del browser, è possibile ottenere i stream ottimi che abbiamo da offrire. Basta una semplice installazione.",
|
||||
"explainerIos": "Purtroppo, l'estensione del browser non è supportato su IOS, premere <bold>Torna indietro</bold> per scegliere un'altra opzione.",
|
||||
"extensionHelp": "Se avete installato l'estensione ma non viene rilevata. <bold>Aprire l'estensione attraverso il menu delle estensioni del browser</bold> e seguire i passaggi sullo schermo.",
|
||||
"linkChrome": "Installa l'estensione su Chrome",
|
||||
"linkFirefox": "Installa l'estensione su Firefox",
|
||||
"notDetecting": "Installato su Chrome ma non viene visualizzato? Prova a ricaricare la pagina!",
|
||||
"notDetectingAction": "Ricarica pagina",
|
||||
"status": {
|
||||
"disallowed": "L'estensione non è attivato per questa pagina",
|
||||
"disallowedAction": "Attiva l'estensione",
|
||||
"failed": "Richiesta di stato fallita",
|
||||
"loading": "In attesa di installare l'estensione",
|
||||
"outdated": "Versione dell'estensione troppo vecchia",
|
||||
"success": "L'estensione funziona come previsto!"
|
||||
},
|
||||
"submit": "Continua",
|
||||
"title": "Iniziamo con un'estensione"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "Torna indietro",
|
||||
"explainer": "Con il metodo proxy, è possibile ottenere stream di qualità ottima creando un proxy self-service.",
|
||||
"input": {
|
||||
"errorConnection": "Impossibile connettere al proxy",
|
||||
"errorInvalidUrl": "URL non valido",
|
||||
"errorNotProxy": "Avevamo previsto un proxy, ma abbiamo ottenuto un sito web",
|
||||
"label": "URL proxy",
|
||||
"placeholder": "https://"
|
||||
},
|
||||
"link": "Impare a creare un proxy",
|
||||
"submit": "Invia proxy",
|
||||
"title": "Creiamo un nuovo proxy"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "Per ottenere i migliori streaming possibili. È necessario scegliere il metodo di streaming da utilizzare.",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "Non voglio stream di buona qualità, <0 /> <1>usa setup predefinita</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "Installa l'estensione",
|
||||
"description": "Installate l'estensione del browser per accedere alle migliori sorgenti.",
|
||||
"quality": "Migliore qualità",
|
||||
"title": "Estensione del browser"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "Setup proxy",
|
||||
"description": "Configurate un proxy in soli 5 minuti e ottenete l'accesso a ottimi fonti.",
|
||||
"quality": "Buona qualità",
|
||||
"title": "Proxy personalizzato"
|
||||
}
|
||||
},
|
||||
"title": "Configuriamo movie-web"
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "Chiudi"
|
||||
},
|
||||
@ -182,7 +246,7 @@
|
||||
"downloadPlaylist": "Scarica playlist",
|
||||
"downloadSubtitle": "Scarica sottotitolo attuale",
|
||||
"downloadVideo": "Scarica video",
|
||||
"hlsDisclaimer": "I download vengono effettuati direttamente dal provider. movie-web non ha il controllo sul modo in cui i download vengono forniti. Nota che state scaricando un playlist HLS, questio è destinato agli utenti che conoscono streaming multimediale avanzato.",
|
||||
"hlsDisclaimer": "I download vengono effettuati direttamente dal provider. movie-web non ha il controllo sul modo in cui i download vengono forniti.<br /><br />Nota che se state scaricando un playlist HLS, <bold>non è raccomandato di scaricare se non si ha familiarità con i formati di streaming avanzati</bold>. Prova altri sorgenti per diversi formati.",
|
||||
"onAndroid": {
|
||||
"1": "Per scaricare su Android, fai clic sul pulsante di scaricare, e poi nella nuova paggina, <bold>toccare e tenere premuto</bold> sul video, e selezionare <bold>salva</bold>.",
|
||||
"shortTitle": "Scarica / Android",
|
||||
@ -263,6 +327,17 @@
|
||||
"text": "Impossibile caricare metadati API, verifica la connessione internet.",
|
||||
"title": "Impossibile caricare metadati API"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "Rimosso",
|
||||
"text": "Questa media non è più disponibile a causa di un notizia takedown o un rivendicazione di copyright.",
|
||||
"title": "I media sono stati rimossi"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "Permesso mancato",
|
||||
"button": "Usa l'estensione",
|
||||
"text": "Avete l'estensione del browser, ma serve il vostro permesso per iniziare usare l'estensione.",
|
||||
"title": "Configura l'estensione"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "Fallito",
|
||||
"homeButton": "Vai alla pagina iniziale",
|
||||
@ -390,24 +465,49 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "Se si desideri connettersi a un backend personalizzato per memorizzare i dati, attivare questo e fornire l'URL.",
|
||||
"description": "Se si desideri connettersi a un backend personalizzato per memorizzare i dati, attivare questo e fornire l'URL. <0>Istruzioni.</0>",
|
||||
"label": "Server personalizzato",
|
||||
"urlLabel": "URL del server personalizzato"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "Fare setup",
|
||||
"errorStatus": {
|
||||
"description": "Sembra che uno o più articoli in questo setup serve la vostra attenzione.",
|
||||
"title": "Qualcosa serve la vostra attenzione"
|
||||
},
|
||||
"itemError": "C'è un errore in questo setup. Eseguire nuovamente il setup per correggerlo.",
|
||||
"items": {
|
||||
"default": "Setup predefinita",
|
||||
"extension": "Estensione",
|
||||
"proxy": "Proxy personalizzato"
|
||||
},
|
||||
"redoSetup": "Rifare setup",
|
||||
"successStatus": {
|
||||
"description": "Tutto è pronto per iniziare a guardare i vostri media preferiti.",
|
||||
"title": "Tutto è setup!"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "Fare clic sul pulsante a destra per avviare il setup.",
|
||||
"title": "Non l'avete completato il setup"
|
||||
}
|
||||
},
|
||||
"title": "Connessioni",
|
||||
"workers": {
|
||||
"addButton": "Aggiungere un nuovo lavoratore",
|
||||
"description": "Per far funzionare l'applicazione, tutto il traffico viene instradato attraverso i proxy. Abilitare questa opzione se si desidera portare i propri lavoratori.",
|
||||
"description": "Per far funzionare l'applicazione, tutto il traffico viene instradato attraverso i proxy. Abilitare questa opzione se si desidera portare i propri lavoratori. <0>Istruzioni.</0>",
|
||||
"emptyState": "Non ci sono ancora lavoratori, aggiungetene uno sotto",
|
||||
"label": "Utilizzare proxy worker personalizzati",
|
||||
"urlLabel": "URL dei lavoratori",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"preferences": {
|
||||
"language": "Lingua di applicazione",
|
||||
"languageDescription": "Lingua applicata all'intera applicazione.",
|
||||
"title": "Località"
|
||||
"languageDescription": "Lingua applicato all'intera applicazione.",
|
||||
"thumbnail": "Generare miniature",
|
||||
"thumbnailDescription": "Nella maggior parte dei casi, i video non hanno miniature. È possibile attivare questa impostazione per generarle quando è necessario, ma possono rendere il video più lento.",
|
||||
"thumbnailLabel": "Generare miniature",
|
||||
"title": "Preferenze"
|
||||
},
|
||||
"reset": "Reset",
|
||||
"save": "Salva",
|
||||
|
@ -378,11 +378,6 @@
|
||||
"urlLabel": "워커 URL"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"language": "애플리케이션 언어",
|
||||
"languageDescription": "전체 애플리케이션에 적용되는 언어입니다.",
|
||||
"title": "지"
|
||||
},
|
||||
"reset": "초기화",
|
||||
"save": "저장",
|
||||
"sidebar": {
|
||||
|
@ -372,11 +372,6 @@
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"language": "Lietojumprogrammas valoda",
|
||||
"languageDescription": "Visai lietojumprogrammai lietotā valoda.",
|
||||
"title": "Lokalizācija"
|
||||
},
|
||||
"reset": "Restartēt",
|
||||
"save": "Saglabāt",
|
||||
"sidebar": {
|
||||
|
@ -404,11 +404,6 @@
|
||||
"urlPlaceholder": "banana://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"language": "Banana",
|
||||
"languageDescription": "Banana applied to the entire banana.",
|
||||
"title": "Banana"
|
||||
},
|
||||
"reset": "Banana",
|
||||
"save": "Banana",
|
||||
"sidebar": {
|
||||
|
@ -95,6 +95,7 @@
|
||||
"about": "जानकारी",
|
||||
"dmca": "DMCA",
|
||||
"login": "लग - इन",
|
||||
"onboarding": "सेटअप",
|
||||
"pagetitle": "{{title}} - movie-web",
|
||||
"register": "दर्ता",
|
||||
"settings": "सेटिङ्स्"
|
||||
@ -165,6 +166,69 @@
|
||||
"message": "हामीले जताततै हेर्यौं: डिब्बा मुनि, कोठरीमा, प्रोक्सी पछाडि तर अन्ततः तपाईंले खोजिरहनु भएको पेज फेला पार्न सकेनौं।",
|
||||
"title": "त्यो पेज फेला पार्न सकेन"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "रद्द गर्नुहोस्",
|
||||
"confirm": "डिफल्ट सेटअप प्रयोग गर्नुहोस्",
|
||||
"description": "पूर्वनिर्धारित सेटअपमा उत्कृष्ट स्ट्रिमहरू छैनन् र असहनीय रूपमा ढिलो हुन सक्छ।",
|
||||
"title": "के तपाईँ निश्चित हुनुहुन्छ?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "पछाडी जाउ",
|
||||
"explainer": "ब्राउजर एक्सटेन्सन प्रयोग गरेर, तपाईंले हामीले प्रस्ताव गर्नु पर्ने उत्तम स्ट्रिमहरू प्राप्त गर्न सक्नुहुन्छ। केवल एक साधारण स्थापना संग।",
|
||||
"explainerIos": "दुर्भाग्यवश, ब्राउजर एक्सटेन्सन IOS मा समर्थित छैन, अर्को विकल्प रोज्न <bold>Go back</bold> थिच्नुहोस्।",
|
||||
"extensionHelp": "यदि तपाईंले एक्स्टेन्सन स्थापना गर्नुभएको छ तर यो पत्ता लागेको छैन। <bold>तपाईंको ब्राउजर विस्तार मेनु मार्फत विस्तार खोल्नुहोस्</bold> र स्क्रिनमा चरणहरू पालना गर्नुहोस्।",
|
||||
"linkChrome": "क्रोम एक्सटेन्सन स्थापना गर्नुहोस्",
|
||||
"linkFirefox": "फायरफक्स एक्सटेन्सन स्थापना गर्नुहोस्",
|
||||
"notDetecting": "chrome मा स्थापित तर देखिदैन? पृष्ठ पुन: लोड गर्ने प्रयास गर्नुहोस्!",
|
||||
"notDetectingAction": "पृष्ठ पुन: लोड गर्नुहोस्",
|
||||
"status": {
|
||||
"disallowed": "यो पेजको लागि एक्सटेन्सन सक्षम गरिएको छैन",
|
||||
"disallowedAction": "एक्स्टेन्सन सक्षम गर्नुहोस्",
|
||||
"failed": "स्थिति अनुरोध गर्न असफल",
|
||||
"loading": "तपाइँ एक्सटेन्सन स्थापना गर्न को लागी प्रतिक्षा गर्दै",
|
||||
"outdated": "एक्स्टेन्सन धेरै पुरानो छ",
|
||||
"success": "एक्सटेन्सनले अपेक्षा गरे अनुसार काम गरिरहेको छ!"
|
||||
},
|
||||
"submit": "जारी राख्नुहोस्",
|
||||
"title": "एक्सटेन्सन संग सुरु गरौं"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "पछाडी जाउ",
|
||||
"explainer": "प्रोक्सी विधिको साथ, तपाईं स्वयं-सेवा प्रोक्सी बनाएर उत्कृष्ट गुणस्तर स्ट्रिमहरू प्राप्त गर्न सक्नुहुन्छ।",
|
||||
"input": {
|
||||
"errorConnection": "प्रोक्सीमा कनेक्ट हुन सकेन",
|
||||
"errorInvalidUrl": "मान्य URL होइन",
|
||||
"errorNotProxy": "प्रोक्सीको अपेक्षा गरे तर वेबसाइट पायो",
|
||||
"label": "प्रोक्सी URL",
|
||||
"placeholder": "https://"
|
||||
},
|
||||
"link": "प्रोक्सी कसरी बनाउने सिक्नुहोस्",
|
||||
"submit": "प्रोक्सी पेश गर्नुहोस्",
|
||||
"title": "एउटा नयाँ प्रोक्सी बनाऔं"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "सम्भावित उत्तम स्ट्रिमहरू प्राप्त गर्न,। तपाईंले कुन स्ट्रिमिङ विधि प्रयोग गर्न चाहनुहुन्छ भनेर छनौट गर्न आवश्यक हुनेछ।",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "मलाई राम्रो गुणस्तरका स्ट्रिमहरू चाहिँदैन,<0 /> <1>पूर्वनिर्धारित सेटअप प्रयोग गर्नुहोस्</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "एक्सटेन्सन हाल्नुहोस",
|
||||
"description": "ब्राउजर एक्सटेन्सन हाल्नुहोस र उत्तम स्रोतहरूमा पहुँच प्राप्त गर्नुहोस्।",
|
||||
"quality": "उत्कृस्ट गुणस्तर",
|
||||
"title": "ब्राउजर एक्सटेन्सन"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "सेटअप प्रोक्सी",
|
||||
"description": "केवल 5 मिनेटमा प्रोक्सी सेटअप गर्नुहोस् र उत्कृष्ट स्रोतहरूमा पहुँच प्राप्त गर्नुहोस्।",
|
||||
"quality": "राम्रो क्वालिटी",
|
||||
"title": "आफ्नै प्रोक्सी"
|
||||
}
|
||||
},
|
||||
"title": "तपाईँलाई movie-web सँग सेटअप गरौं"
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "बन्द गर्नुहोस्"
|
||||
},
|
||||
@ -182,7 +246,7 @@
|
||||
"downloadPlaylist": "डाउनलोड प्लेलिस्ट",
|
||||
"downloadSubtitle": "हालको उपशीर्षक डाउनलोड गर्नुहोस्",
|
||||
"downloadVideo": "डाउनलोड भिडियो",
|
||||
"hlsDisclaimer": "डाउनलोडहरू सीधा प्रदायकबाट लिइन्छ। movie-webले डाउनलोडहरू कसरी प्रदान गरिन्छ भन्नेमा नियन्त्रण गर्दैन। कृपया ध्यान दिनुहोस् कि तपाइँ HLS प्लेलिस्ट डाउनलोड गर्दै हुनुहुन्छ, यो उन्नत मल्टिमिडिया स्ट्रिमिङसँग परिचित प्रयोगकर्ताहरूको लागि हो।",
|
||||
"hlsDisclaimer": "डाउनलोडहरू सीधा प्रदायकबाट लिइन्छ। चलचित्र-वेबको डाउनलोडहरू कसरी प्रदान गरिन्छ भन्नेमा नियन्त्रण छैन।<br /><br />कृपया ध्यान दिनुहोस् कि तपाइँ HLS प्लेलिस्ट डाउनलोड गर्दै हुनुहुन्छ, <bold>यदि तपाइँ उन्नत स्ट्रिमिङ ढाँचाहरूसँग परिचित हुनुहुन्न भने यसलाई डाउनलोड गर्न सिफारिस गरिँदैन। </ bold>। विभिन्न ढाँचाहरूको लागि विभिन्न स्रोतहरू प्रयास गर्नुहोस्।",
|
||||
"onAndroid": {
|
||||
"1": "एन्ड्रोइड मा, डाउनलोड बटन क्लिक गर्नुहोस् त्यसपछि, नयाँ पृष्ठमा, भिडियोमा <bold>ट्याप गर्नुहोस् र होल्ड गर्नुहोस्</bold>, त्यसपछि <bold>बचत</bold> चयन गर्नुहोस्।",
|
||||
"shortTitle": "डाउनलोड / एन्ड्रोइड",
|
||||
@ -263,6 +327,17 @@
|
||||
"text": "API मेटाडेटा लोड गर्न सकिएन, कृपया आफ्नो इन्टरनेट जडान जाँच गर्नुहोस्।",
|
||||
"title": "API मेटाडेटा लोड गर्न असफल भयो"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "हटाइयो",
|
||||
"text": "यो मिडिया हटाउने सूचना वा प्रतिलिपि अधिकार दावीको कारणले अब उपलब्ध छैन।",
|
||||
"title": "मिडिया हटाइएको छ"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "अनुमति छैन",
|
||||
"button": "एक्सटेन्सन प्रयोग गर्नुहोस्",
|
||||
"text": "तपाईंसँग ब्राउजर एक्स्टेन्सन छ, तर हामीलाई एक्स्टेन्सन प्रयोग गर्न सुरु गर्न तपाईंको अनुमति चाहिन्छ।",
|
||||
"title": "एक्सटेन्सन कन्फिगर गर्नुहोस्"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "असफल",
|
||||
"homeButton": "होम् जाउँ",
|
||||
@ -390,24 +465,49 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "यदि तपाईं आफ्नो डेटा भण्डारण गर्न अनुकूलन ब्याकइन्डमा जडान गर्न चाहनुहुन्छ भने, यसलाई सक्षम गर्नुहोस् र URL प्रदान गर्नुहोस्।",
|
||||
"description": "यदि तपाईं आफ्नो डेटा भण्डारण गर्न अनुकूलन ब्याकइन्डमा जडान गर्न चाहनुहुन्छ भने, यसलाई सक्षम गर्नुहोस् र URL प्रदान गर्नुहोस्। <0>निर्देशनहरू।</0>",
|
||||
"label": "अनुकूलन सर्भर",
|
||||
"urlLabel": "अनुकूलन सर्भर URL"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "सेटअप गर्नुहोस्",
|
||||
"errorStatus": {
|
||||
"description": "यो सेटअपमा एक वा बढी वस्तुहरू तपाईंको ध्यान आवश्यक छ जस्तो देखिन्छ।",
|
||||
"title": "केहि तपाईंको ध्यान आवश्यक छ"
|
||||
},
|
||||
"itemError": "यस सेटिङमा केही गडबड छ। यसलाई ठीक गर्न फेरि सेटअप गर्नुहोस्।",
|
||||
"items": {
|
||||
"default": "डिफल्ट सेटअप",
|
||||
"extension": "एक्सटेन्सन",
|
||||
"proxy": "आफ्नै प्रोक्सी"
|
||||
},
|
||||
"redoSetup": "पुन: सेटअप गर्नुहोस्",
|
||||
"successStatus": {
|
||||
"description": "तपाइँ तपाइँको मनपर्ने मिडिया हेर्न सुरु गर्न को लागी सबै चीजहरू छन्।",
|
||||
"title": "सबै कुरा मिलाइएको छ!"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "कृपया सेटअप प्रक्रिया सुरु गर्न दायाँ तिरको बटनमा क्लिक गर्नुहोस्।",
|
||||
"title": "तपाईं सेटअप मार्फत जानुभएको छैन"
|
||||
}
|
||||
},
|
||||
"title": "संबन्धहरु",
|
||||
"workers": {
|
||||
"addButton": "नया worker हरु हाल्नुहोस",
|
||||
"description": "एप्लिकेसन प्रकार्य बनाउनको लागि, सबै ट्राफिक प्रोक्सीहरू मार्फत रूट गरिएको छ। यदि तपाईं आफ्नो कामदारहरू ल्याउन चाहनुहुन्छ भने यसलाई सक्षम गर्नुहोस्।",
|
||||
"description": "एप्लिकेसन प्रकार्य बनाउनको लागि, सबै ट्राफिक प्रोक्सीहरू मार्फत रूट गरिएको छ। यदि तपाईं आफ्नो कामदारहरू ल्याउन चाहनुहुन्छ भने यसलाई सक्षम गर्नुहोस्। <0>निर्देशनहरू।</0>",
|
||||
"emptyState": "अहिलेसम्म worker हरु छैनन्, तल एउटा थप्नुहोस्",
|
||||
"label": "आफ्नै proxy workers हरु चलाउनुहोस्",
|
||||
"urlLabel": "Worker URL हरु",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"preferences": {
|
||||
"language": "एपको भाषा",
|
||||
"languageDescription": "सम्पूर्ण अनुप्रयोगमा भाषा लागू गरियो।",
|
||||
"title": "भाषा"
|
||||
"languageDescription": "सम्पूर्ण एप्लिकेसनमा भाषा लागू भयो।",
|
||||
"thumbnail": "थम्बनेलहरू बनाउनुहोस्",
|
||||
"thumbnailDescription": "अधिकांश समय, भिडियोहरूमा थम्बनेलहरू हुँदैनन्। तपाईंले वर्तमानमा नै तिनीहरूलाई उत्पन्न गर्न यो सेटिङ सक्षम गर्न सक्नुहुन्छ तर तिनीहरूले तपाईंको भिडियोलाई सुस्त बनाउन सक्छन्।",
|
||||
"thumbnailLabel": "थम्बनेलहरू बनाउनुहोस्",
|
||||
"title": "प्राथमिकता"
|
||||
},
|
||||
"reset": "रिसेट गर्नुहोस्",
|
||||
"save": "सेभ गर्नुहोस्",
|
||||
|
@ -95,6 +95,7 @@
|
||||
"about": "Over",
|
||||
"dmca": "DMCA",
|
||||
"login": "Login",
|
||||
"onboarding": "Instellen",
|
||||
"pagetitle": "{{title}} - movie-web",
|
||||
"register": "Registreren",
|
||||
"settings": "Instellingen"
|
||||
@ -165,6 +166,69 @@
|
||||
"message": "We hebben echt alles geprobeerd, zelfs tijdrijzen; echter hebben we deze pagina helaas niet kunnen vinden.",
|
||||
"title": "Pagina niet gevonden"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "Annuleren",
|
||||
"confirm": "Gebruik standaardinstallatie",
|
||||
"description": "De standaardinstallatie heeft niet de beste streams en kan onbruikbaar traag zijn.",
|
||||
"title": "Weet je het zeker?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "Terug",
|
||||
"explainer": "Door gebruik te maken van de browserextensie kun je de beste streams krijgen. Met slechts een eenvoudige installatie.",
|
||||
"explainerIos": "Helaas, de browserextensie is niet ondersteund op iOS. Druk op <bold>Terug</bold> om een andere optie te kiezen.",
|
||||
"extensionHelp": "Als je de extensie hebt geïnstalleerd maar niet wordt gedetecteerd, <bold>Open dan de extensie via het extensies menu in je browser</bold> en volg de stappen op het scherm.",
|
||||
"linkChrome": "Installeer de Chrome-extensie",
|
||||
"linkFirefox": "Installeer de Firefox-extensie",
|
||||
"notDetecting": "Geïnstalleerd op Chrome maar wordt niet weergegeven? Probeer de pagina opnieuw te laden!",
|
||||
"notDetectingAction": "Pagina opnieuw laden",
|
||||
"status": {
|
||||
"disallowed": "Extensie is niet ingeschakeld voor deze pagina",
|
||||
"disallowedAction": "Extensie inschakelen",
|
||||
"failed": "Mislukt om status aan te vragen",
|
||||
"loading": "Aan het wachten tot je de extensie hebt geïnstalleerd",
|
||||
"outdated": "Extensieversie te oud",
|
||||
"success": "Extensie werkt zoals verwacht!"
|
||||
},
|
||||
"submit": "Doorgaan",
|
||||
"title": "Laten we beginnen met de extensie"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "Terug",
|
||||
"explainer": "Met de proxy-methode kun je hoogwaardige streams verkrijgen door zelf een proxy op te zetten.",
|
||||
"input": {
|
||||
"errorConnection": "Kon geen verbinding maken met de proxy",
|
||||
"errorInvalidUrl": "Geen geldige URL",
|
||||
"errorNotProxy": "Verwachtte een proxy maar kreeg een website",
|
||||
"label": "Proxy URL",
|
||||
"placeholder": "https://"
|
||||
},
|
||||
"link": "Leer hoe je de proxy kunt instellen",
|
||||
"submit": "Proxy opslaan",
|
||||
"title": "Laten we een nieuwe proxy instellen"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "Om de beste mogelijke streams te krijgen, moet je kiezen welke streamingmethode je wilt gebruiken.",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "Ik wil geen streams van goede kwaliteit, <0 /> <1>Gebruik de standaardinstellingen.</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "Installeer extensie",
|
||||
"description": "Installeer browserextensie en krijg toegang tot de beste bronnen.",
|
||||
"quality": "Beste kwaliteit",
|
||||
"title": "Browserextensie"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "Proxy instellen",
|
||||
"description": "Proxy instellen in slechts 5 minuten en krijg toegang tot geweldige bronnen.",
|
||||
"quality": "Goede kwaliteit",
|
||||
"title": "Eigen proxy"
|
||||
}
|
||||
},
|
||||
"title": "Laten we beginnen met het instellen van movie-web"
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "Sluiten"
|
||||
},
|
||||
@ -182,7 +246,7 @@
|
||||
"downloadPlaylist": "Afspeellijst downloaden",
|
||||
"downloadSubtitle": "Download huidige ondertiteling",
|
||||
"downloadVideo": "Download filmpje",
|
||||
"hlsDisclaimer": "Downloads worden rechtstreeks van de aanbieder gehaald. movie-web heeft geen controle over hoe de downloads worden aangeboden. Houd er rekening mee dat u een HLS-afspeellijst downloadt, deze is bedoeld voor gebruikers die bekend zijn met geavanceerde multimediastreaming.",
|
||||
"hlsDisclaimer": "Downloads worden rechtstreeks van de aanbieder gehaald. movie-web heeft geen controle over de manier waarop de downloads worden aangeboden.<br /><br />Houd er rekening mee dat u nu een HLS-afspeellijst downloadt, het wordt <bold>afgeraden deze te downloaden als u niet bekend bent met geavanceerde streamingbestandstypen</bold>. Probeer verschillende bronnen voor verschillende streamingbestandstypen.",
|
||||
"onAndroid": {
|
||||
"1": "Om te downloaden op Android, klik je op de downloadknop en vervolgens, op de nieuwe pagina, <bold>tap and hold</bold> op de video en selecteer <bold>save</bold>.",
|
||||
"shortTitle": "Download / Android",
|
||||
@ -194,7 +258,7 @@
|
||||
"title": "Downloaden op iOS"
|
||||
},
|
||||
"onPc": {
|
||||
"1": "Klik op de downloadknop op de pc en klik op de nieuwe pagina met de rechtermuisknop op de video en selecteer <bold>Video opslaan als</bold>.",
|
||||
"1": "Klik op de downloadknop op de pc en klik op de nieuwe pagina met de rechtermuisknop op de video en selecteer <bold>Video opslaan als</bold>",
|
||||
"shortTitle": "Download / PC",
|
||||
"title": "Downloaden op PC"
|
||||
},
|
||||
@ -263,6 +327,17 @@
|
||||
"text": "Kan API-metagegevens niet laden. Controleer uw internetverbinding.",
|
||||
"title": "Kan API-metagegevens niet laden"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "Weggehaald",
|
||||
"text": "Deze media is niet langer beschikbaar vanwege een verwijderingsverzoek of auteursrechtenclaim.",
|
||||
"title": "Media is weggehaald"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "Toestemming ontbreekt",
|
||||
"button": "Gebruik de extensie",
|
||||
"text": "Je hebt de browserextensie, maar we hebben jouw toestemming nodig om gebruik te maken van de extensie.",
|
||||
"title": "Configureer de extensie"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "Mislukt",
|
||||
"homeButton": "Ga naar de home-pagina",
|
||||
@ -390,24 +465,49 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "Als je verbinding wilt maken met een eigen backend om je gegevens op te slaan, schakel dan deze optie in en geef de URL op.",
|
||||
"description": "Als je verbinding wilt maken met een eigen backend om je gegevens op te slaan, schakel dan deze optie in en geef de URL op. <0>Instructies.</0>",
|
||||
"label": "Eigen server",
|
||||
"urlLabel": "Eigen server URL"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "Instellen",
|
||||
"errorStatus": {
|
||||
"description": "Het lijkt erop dat één of meer items in deze configuratie jouw aandacht nodig hebben.",
|
||||
"title": "Iets vereist jouw aandacht"
|
||||
},
|
||||
"itemError": "Er is iets mis met deze instelling. Klik op opnieuw instellen om op te lossen.",
|
||||
"items": {
|
||||
"default": "Standaard installatie",
|
||||
"extension": "Extensie",
|
||||
"proxy": "Eigen proxy"
|
||||
},
|
||||
"redoSetup": "Opnieuw instellen",
|
||||
"successStatus": {
|
||||
"description": "In alles is ingesteld, je kunt nu je favoriete media bekijken.",
|
||||
"title": "Alles is ingesteld!"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "Klik op de knop aan de rechterkant om het installatieproces te starten.",
|
||||
"title": "Je hebt de installatieprocedure nog niet doorlopen"
|
||||
}
|
||||
},
|
||||
"title": "Verbindingen",
|
||||
"workers": {
|
||||
"addButton": "Nieuwe worker toevoegen",
|
||||
"description": "Om de applicatie te laten werken, wordt al het verkeer omgeleid via proxies. Schakel dit in als je je eigen workers wilt gebruiken.",
|
||||
"description": "Om de applicatie te laten werken, wordt al het verkeer omgeleid via proxies. Schakel dit in als je je eigen workers wilt gebruiken. <0>Instructies.</0>",
|
||||
"emptyState": "Nog geen workers, voeg er hieronder een toe",
|
||||
"label": "Eigen proxy werker gebruiken",
|
||||
"urlLabel": "Worker URLs",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"preferences": {
|
||||
"language": "Applicatietaal",
|
||||
"languageDescription": "Taal wordt toegepast op de hele applicatie.",
|
||||
"title": "Lokaal"
|
||||
"languageDescription": "Taal toegepast op de gehele applicatie.",
|
||||
"thumbnail": "Genereer miniaturen",
|
||||
"thumbnailDescription": "Meestal hebben video's geen miniaturen. Je kunt deze instelling inschakelen om ze dynamisch te genereren, maar dit kan je video vertragen.",
|
||||
"thumbnailLabel": "Genereer miniaturen",
|
||||
"title": "Voorkeuren"
|
||||
},
|
||||
"reset": "Resetten",
|
||||
"save": "Wijzigingen opslaan",
|
||||
|
12
src/assets/locales/nv.json
Normal file
12
src/assets/locales/nv.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"about": {
|
||||
"description": "movie-web T'áá hwiił yá at'ééh naat'áanii t'áá hwiił yá at'ééh bitsiin. Bee ahéhí bitsííʼííł dóó sinas dziní asdzą́ą́.",
|
||||
"faqTitle": "hastiin nahatʼá",
|
||||
"q1": {
|
||||
"body": "Bee hwiił bitsííʼííł hólǫ́, t'áá hwiił yá at'ééh naat'áanii t'áá hwiił yá at'ééh bitsiin. Hwiił yá at'ééh naat'áanii at'é, bitsííʼííł yá at'ééh naat'áanii t'áá hwiił yá at'ééh bitsiin. Bitsííʼííł yá at'ééh naat'áanii hólǫ́, t'áá hwiił yá at'ééh naat'áanii t'áá hwiił yá at'ééh bitsiin."
|
||||
},
|
||||
"q3": {
|
||||
"body": "Hałáágo áłtsééh hózhǫǫgiisiił Nílchʼi Datasoii (TMDB) yá’át’ééhí dooleeł dįįʼgo doo dįįʼgií nihisin dóó tązhii yisdzohazlą́ą́ʼ."
|
||||
}
|
||||
}
|
||||
}
|
@ -95,6 +95,7 @@
|
||||
"about": "About",
|
||||
"dmca": "DMCA",
|
||||
"login": "Login",
|
||||
"onboarding": "Setup",
|
||||
"pagetitle": "{{title}} - movie-web",
|
||||
"register": "Forge yer account, matey!",
|
||||
"settings": "Settings"
|
||||
@ -120,7 +121,10 @@
|
||||
},
|
||||
"titles": {
|
||||
"day": {
|
||||
"default": "What be yer fancy for this fine afternoon's viewing, me heartie?"
|
||||
"default": "What be yer fancy for this fine afternoon's viewing, me heartie?",
|
||||
"extra": [
|
||||
"Feelin' adventurous? Pirates of the Caribbean might be the perfect choice."
|
||||
]
|
||||
},
|
||||
"morning": {
|
||||
"default": "What be yer fancy for this mornin's viewing, me heartie?",
|
||||
@ -162,6 +166,69 @@
|
||||
"message": "We looked everywhere: under the bins, in the closet, behind the proxy but ultimately couldn't find the treasure map ye be lookin' for.",
|
||||
"title": "Couldn't find that treasure map"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "Cancel",
|
||||
"confirm": "Use default setup",
|
||||
"description": "The default setup does nah 'ave the best streams 'n can be unbearably slow.",
|
||||
"title": "Are ye sure?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "Go back",
|
||||
"explainer": "Usin' the browser extension, ye can get the best streams we 'ave t' offer. Wit' jus' a simple install.",
|
||||
"explainerIos": "Unfortunately, the browser extension ain't supported on iOS, Press <bold>Go back</bold> t' choose another option.",
|
||||
"extensionHelp": "If ye've installed the extension but 'tisn't detected, <bold>open the extension through yer browsers extension menu</bold> 'n follow the steps on screen.",
|
||||
"linkChrome": "Install Chrome extension",
|
||||
"linkFirefox": "Install Firefox extension",
|
||||
"notDetecting": "Installed on Chrome, but the site ain't detecting it? Give the page a good reload!",
|
||||
"notDetectingAction": "Reload page",
|
||||
"status": {
|
||||
"disallowed": "Extension ain't enabled fer this page",
|
||||
"disallowedAction": "Enable extension",
|
||||
"failed": "Failed t' request status",
|
||||
"loading": "Waitin' fer ye t' install the extension",
|
||||
"outdated": "Extension version too ole",
|
||||
"success": "Extension be workin' as expected!"
|
||||
},
|
||||
"submit": "Continue",
|
||||
"title": "Let's start wit' an extension"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "Go back",
|
||||
"explainer": "Wit' the proxy method, ye can get great quality streams by makin' a self-service proxy.",
|
||||
"input": {
|
||||
"errorConnection": "Couldn't connect t' proxy",
|
||||
"errorInvalidUrl": "Ain't a valid URL",
|
||||
"errorNotProxy": "Expected a proxy but got a website",
|
||||
"label": "Proxy URL",
|
||||
"placeholder": "https://"
|
||||
},
|
||||
"link": "Learn how t' make a proxy",
|
||||
"submit": "Submit proxy",
|
||||
"title": "Let's make a new proxy"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "T' get the best streams possible, ye will needs t' choose which streamin' method ye wants t' use.",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "I don't wants good quality streams,<0 /> <1>use the default setup</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "Install extension",
|
||||
"description": "Install browser extension 'n gain access t' the best sources.",
|
||||
"quality": "Best quality",
|
||||
"title": "Browser extension"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "Setup proxy",
|
||||
"description": "Setup a proxy in jus' 5 minutes 'n gain access t' great sources.",
|
||||
"quality": "Good quality",
|
||||
"title": "Custom proxy"
|
||||
}
|
||||
},
|
||||
"title": "Let's get ye setup wit' movie-web"
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "Close"
|
||||
},
|
||||
@ -176,7 +243,10 @@
|
||||
"menus": {
|
||||
"downloads": {
|
||||
"disclaimer": "Downloads be taken directly from the provider. movie-web does not have control over how the downloads be provided.",
|
||||
"downloadPlaylist": "Download playlist",
|
||||
"downloadSubtitle": "Download current subtitle",
|
||||
"downloadVideo": "Download film",
|
||||
"hlsDisclaimer": "Loot are taken directly from the provider. movie-web does nah 'ave control o'er how the loot are provided. <br /><br />Please note that ye be downloadin' an HLS playlist, <bold>'tisn't recommended t' download if ye be nah familiar wit' advanced streamin' formats</bold>. Try different sources fer different formats.",
|
||||
"onAndroid": {
|
||||
"1": "To download on Android, <bold>tap and hold</bold> on the film, then select <bold>save</bold>.",
|
||||
"shortTitle": "Download / Android",
|
||||
@ -200,7 +270,8 @@
|
||||
"episodeBadge": "E{{episode}}",
|
||||
"loadingError": "Error loadin' season",
|
||||
"loadingList": "Loading...",
|
||||
"loadingTitle": "Loading..."
|
||||
"loadingTitle": "Loading...",
|
||||
"unairedEpisodes": "One or more episodes in this season 'ave been disabled 'cause they haven't been shipped yet."
|
||||
},
|
||||
"playback": {
|
||||
"speedLabel": "Playback speed",
|
||||
@ -239,13 +310,34 @@
|
||||
"unknownOption": "Unknown"
|
||||
},
|
||||
"subtitles": {
|
||||
"customChoice": "Select subtitle from file",
|
||||
"customizeLabel": "Tailor it to yer liking",
|
||||
"offChoice": "Off",
|
||||
"settings": {
|
||||
"backlink": "Custom subtitles",
|
||||
"delay": "Subtitle delay",
|
||||
"fixCapitals": "Mend the capital letters"
|
||||
}
|
||||
},
|
||||
"title": "Subtitles",
|
||||
"unknownLanguage": "Unknown"
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"api": {
|
||||
"text": "Could nah load API metadata, please check yer internet connection.",
|
||||
"title": "Failed t' load API metadata"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "Removed",
|
||||
"text": "This media be no longer available due t' a takedown notice or copyright claim.",
|
||||
"title": "Media has been scuttled"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "Permission Missin'",
|
||||
"button": "Use extension",
|
||||
"text": "Ye 'ave the browser extension, but we needs yer permission t' get started usin' the extension.",
|
||||
"title": "Configure the extension"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "Failed",
|
||||
"homeButton": "Go home port",
|
||||
@ -284,6 +376,7 @@
|
||||
},
|
||||
"notFound": {
|
||||
"badge": "Not found",
|
||||
"detailsButton": "Show details",
|
||||
"homeButton": "Go home port",
|
||||
"text": "Oh, me apologies, sweetie! The itty-bitty movie-web did its utmost bestest, but alas, no wucky videos to be spotted anywhere (´⊙ω⊙`) Please don't be angwy, wittle movie-web ish twying so hard. Can ye find it in yer heart to forgive? UwU 💖",
|
||||
"title": "Goo goo gaa gaa"
|
||||
@ -294,12 +387,23 @@
|
||||
"remaining": "{{timeLeft}} left • Finish at {{timeFinished, datetime}}",
|
||||
"shortRegular": "{{timeWatched}}",
|
||||
"shortRemaining": "-{{timeLeft}}"
|
||||
},
|
||||
"turnstile": {
|
||||
"description": "Please verify that ye be human by completin' the Captcha on right. 'tis t' keep movie-web safe!",
|
||||
"error": "Failed t' verify yer piracy. Please try again.",
|
||||
"title": "We needs t' verify that ye're real pirate.",
|
||||
"verifyingHumanity": "Verifyin' yer piracy..."
|
||||
}
|
||||
},
|
||||
"screens": {
|
||||
"dmca": {
|
||||
"text": "Ahoy t' movie-web's DMCA contact page! We respect intellectual property rights 'n wants t' address any copyright concerns swiftly. If ye believe yer copyrighted work has been improperly used on our platform, please send a detailed DMCA notice t' the email below. Please include a description o' the copyrighted material, yer contact details, 'n a statement o' good faith belief. We be committed t' resolvin' these matters promptly 'n appreciate yer cooperation in keepin' movie-web a galleon that respects creativity 'n copyrights.",
|
||||
"title": "DMCA"
|
||||
},
|
||||
"loadingApp": "Loadin' application",
|
||||
"loadingUser": "Loadin' yer pirate profile",
|
||||
"loadingUserError": {
|
||||
"logout": "Logout",
|
||||
"reset": "Reset custom ship",
|
||||
"text": "Failed to load yer pirate profile",
|
||||
"textWithReset": "Failed to load yer pirate profile from yer custom ship, want to reset back to default?"
|
||||
@ -361,24 +465,49 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "To make the application function, all traffic be routed through proxies. Enable this if ye want to bring yer own sailors.",
|
||||
"description": "To make the application function, all traffic be routed through proxies. Enable this if ye want to bring yer own sailors. <0>Instructions.</0>",
|
||||
"label": "Custom ship",
|
||||
"urlLabel": "Custom ship URL"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "Do setup",
|
||||
"errorStatus": {
|
||||
"description": "It seems that one or more items in this setup needs yer attention.",
|
||||
"title": "Somethin' needs yer attention"
|
||||
},
|
||||
"itemError": "Thar be somethin' wrong wit' this settin'. Go through setup again t' fix it.",
|
||||
"items": {
|
||||
"default": "Default setup",
|
||||
"extension": "Extension",
|
||||
"proxy": "Custom proxy"
|
||||
},
|
||||
"redoSetup": "Redo setup",
|
||||
"successStatus": {
|
||||
"description": "All things are in ship fer ye t' start watchin' yer favourite media.",
|
||||
"title": "Everythin' be set up!"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "Please skewer the button t' starb'rd t' start the setup process.",
|
||||
"title": "Ye haven't gone through setup"
|
||||
}
|
||||
},
|
||||
"title": "Connections",
|
||||
"workers": {
|
||||
"addButton": "Recruit new sailor",
|
||||
"description": "To make the application function, all traffic be routed through proxies. Enable this if ye want to bring yer own sailors.",
|
||||
"description": "To make the application function, all traffic be routed through proxies. Enable this if ye want to bring yer own sailors. <0>Instructions.</0>",
|
||||
"emptyState": "No sailors yet, add one below",
|
||||
"label": "Use custom proxy sailors",
|
||||
"urlLabel": "Sailor URLs",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"preferences": {
|
||||
"language": "Application language",
|
||||
"languageDescription": "Language applied to the entire application.",
|
||||
"title": "Locale"
|
||||
"languageDescription": "Language applied t' the entire application.",
|
||||
"thumbnail": "Generate thumbnails",
|
||||
"thumbnailDescription": "Most o' the time, videos don't 'ave thumbnails. Ye can enable this settin' t' generate 'em on the trip but they can make yer video slower.",
|
||||
"thumbnailLabel": "Generate thumbnails",
|
||||
"title": "Preferences"
|
||||
},
|
||||
"reset": "Reset",
|
||||
"save": "Save",
|
||||
@ -396,6 +525,13 @@
|
||||
"userId": "Pirate ID"
|
||||
}
|
||||
},
|
||||
"subtitles": {
|
||||
"backgroundLabel": "Background opacity",
|
||||
"colorLabel": "Color",
|
||||
"previewQuote": "I must not fear. Fear is the mind-killer.",
|
||||
"textSizeLabel": "Text size",
|
||||
"title": "Subtitles"
|
||||
},
|
||||
"unsaved": "Ye have unsaved changes"
|
||||
}
|
||||
}
|
||||
|
@ -95,6 +95,7 @@
|
||||
"about": "Informacje",
|
||||
"dmca": "DMCA",
|
||||
"login": "Zaloguj sie",
|
||||
"onboarding": "Konfiguracja",
|
||||
"pagetitle": "{{title}} - movie-web",
|
||||
"register": "Zarejestruj się",
|
||||
"settings": "Ustawienia"
|
||||
@ -165,6 +166,69 @@
|
||||
"message": "Szukaliśmy wszędzie: w koszu, w szafie, a nawet w piwnicy, ale nie byliśmy w stanie znaleźć strony której szukasz.",
|
||||
"title": "Nie można znaleźć tej strony"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "Anuluj",
|
||||
"confirm": "Użyj domyślnej konfiguracji",
|
||||
"description": "Domyślna konfiguracja nie ma najlepszych strumieni i może być strasznie powolna.",
|
||||
"title": "Jesteś pewien?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "Wstecz",
|
||||
"explainer": "Korzystając z rozszerzenia przeglądarki, możesz uzyskać najlepsze strumienie. Wystarczy prosta instalacja.",
|
||||
"explainerIos": "Niestety, rozszerzenie przeglądarki nie jest obsługiwane w systemie iOS, naciśnij <bold>Wstecz</bold>, aby wybrać inną opcję.",
|
||||
"extensionHelp": "Jeżeli zainstalowałeś rozszerzenie, ale nie zostało ono wykryte. <bold>Otwórz rozszerzenie za pomocą menu rozszerzeń przeglądarki</bold> i postępuj zgodnie z instrukcjami wyświetlanymi na ekranie.",
|
||||
"linkChrome": "Zainstaluj rozszerzenie na Chrome",
|
||||
"linkFirefox": "Zainstaluj rozszerzenie na Firefox",
|
||||
"notDetecting": "Zainstalowano na Chrome, ale się nie wyświetla? Spróbuj odświeżyć stronę!",
|
||||
"notDetectingAction": "Odśwież stronę",
|
||||
"status": {
|
||||
"disallowed": "Rozszerzenie nie jest włączone dla tej strony",
|
||||
"disallowedAction": "Włącz rozszerzenie",
|
||||
"failed": "Nie udało się uzyskać statusu",
|
||||
"loading": "Oczekiwanie na instalację rozszerzenia",
|
||||
"outdated": "Za stara wersja rozszerzenia",
|
||||
"success": "Rozszerzenie działa tak jak powinno!"
|
||||
},
|
||||
"submit": "Kontynuuj",
|
||||
"title": "Zacznijmy od rozszerzenia"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "Wstecz",
|
||||
"explainer": "Za pomocą metody proxy można uzyskać strumienie o doskonałej jakości, tworząc samoobsługowy serwer proxy.",
|
||||
"input": {
|
||||
"errorConnection": "Nie można połączyć się z serwerem proxy",
|
||||
"errorInvalidUrl": "Nieprawidłowy adres URL",
|
||||
"errorNotProxy": "Spodziewano proxy, ale otrzymano stronę internetową",
|
||||
"label": "Adres URL serwera proxy",
|
||||
"placeholder": "https://"
|
||||
},
|
||||
"link": "Dowiedz się, jak utworzyć proxy",
|
||||
"submit": "Prześlij proxy",
|
||||
"title": "Stwórzmy nowe proxy"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "Aby uzyskać najlepsze transmisje strumieniowe. Będziesz musiał wybrać metodę strumieniowania, której chcesz użyć.",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "Nie chcę dobrej jakości strumieni, <0 /> <1>użyj domyślnej konfiguracji</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "Zainstaluj rozszerzenie",
|
||||
"description": "Zainstaluj rozszerzenie przeglądarki i uzyskaj dostęp do najlepszych źródeł.",
|
||||
"quality": "Najlepsza jakość",
|
||||
"title": "Rozszerzenie przeglądarki"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "Skonfiguruj serwer proxy",
|
||||
"description": "Skonfiguruj proxy w 5 minut i uzyskaj dostęp do świetnych źródeł.",
|
||||
"quality": "Dobra jakość",
|
||||
"title": "Niestandardowy serwer proxy"
|
||||
}
|
||||
},
|
||||
"title": "Przejdźmy do konfiguracji z movie-web"
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "Zamknij"
|
||||
},
|
||||
@ -182,7 +246,7 @@
|
||||
"downloadPlaylist": "Pobierz playlistę",
|
||||
"downloadSubtitle": "Pobierz aktualne napisy",
|
||||
"downloadVideo": "Pobierz wideo",
|
||||
"hlsDisclaimer": "Pliki do pobrania są pobierane bezpośrednio od dostawcy. movie-web nie ma kontroli nad sposobem dostarczania plików do pobrania. Należy pamiętać, że pobierana jest playlista HLS, przeznaczona dla użytkowników zaznajomionych z zaawansowanym strumieniowaniem multimediów.",
|
||||
"hlsDisclaimer": "Pliki do pobrania są pobierane bezpośrednio od dostawcy. movie-web nie ma kontroli nad sposobem dostarczania plików do pobrania.<br /><br />Należy pamiętać, że pobierasz playlistę HLS, <bold>nie zaleca się pobierania, jeśli nie jesteś zaznajomiony z zaawansowanymi formatami przesyłania strumieniowego</bold>. Wypróbuj różne źródła dla innych formatów.",
|
||||
"onAndroid": {
|
||||
"1": "Aby pobrać na Androidzie, kliknij przycisk pobierania, a następnie na nowej stronie <bold>dotknij i przytrzymaj</bold> na filmie, a następnie wybierz <bold>zapisz</bold>.",
|
||||
"shortTitle": "Pobierz / Android",
|
||||
@ -206,7 +270,8 @@
|
||||
"episodeBadge": "E{{episode}}",
|
||||
"loadingError": "Błąd podczas ładowania sezonu",
|
||||
"loadingList": "Wczytywanie...",
|
||||
"loadingTitle": "Wczytywanie..."
|
||||
"loadingTitle": "Wczytywanie...",
|
||||
"unairedEpisodes": "Jeden lub więcej odcinków tego sezonu zostało wyłączonych, ponieważ nie zostały jeszcze wyemitowane."
|
||||
},
|
||||
"playback": {
|
||||
"speedLabel": "Szybkość odtwarzania",
|
||||
@ -258,6 +323,21 @@
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"api": {
|
||||
"text": "Nie można załadować metadanych API, sprawdź połączenie internetowe.",
|
||||
"title": "Nie udało się załadować metadanych API"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "Usunięte",
|
||||
"text": "Ten materiał nie jest już dostępny z powodu żądania usunięcia lub roszczenia dotyczącego praw autorskich.",
|
||||
"title": "Media zostały usunięte"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "Brak uprawnień",
|
||||
"button": "Użyj rozszerzenia",
|
||||
"text": "Masz nasze rozszerzenie przeglądarki, ale potrzebujemy pozwolenia, aby zacząć z niego korzystać.",
|
||||
"title": "Skonfiguruj rozszerzenie"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "Nie powiodło się",
|
||||
"homeButton": "Wróć na stronę główną",
|
||||
@ -309,6 +389,7 @@
|
||||
"shortRemaining": "-{{timeLeft}}"
|
||||
},
|
||||
"turnstile": {
|
||||
"description": "Proszę potwierdź że jesteś człowiekiem, wypełniając Captcha po prawej stronie. Ma to zapewnić bezpieczeństwo movie-web!",
|
||||
"error": "Nie udało się zweryfikować Twojego człowieczeństwa. Proszę spróbuj ponownie.",
|
||||
"title": "Musimy sprawdzić, czy jesteś człowiekiem.",
|
||||
"verifyingHumanity": "Sprawdzasz swoje człowieczeństwo..."
|
||||
@ -384,24 +465,49 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "Jeśli chcesz połączyć się z niestandardowym backendem w celu przechowywania danych, włącz tę opcję i podaj adres URL.",
|
||||
"description": "Jeśli chcesz połączyć się z niestandardowym backendem w celu przechowywania danych, włącz tę opcję i podaj adres URL. <0>Instrukcje.</0>",
|
||||
"label": "Serwer niestandardowy",
|
||||
"urlLabel": "Adres URL niestandardowego serwera"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "Konfiguruj",
|
||||
"errorStatus": {
|
||||
"description": "Wygląda na to, że jeden lub więcej elementów tej konfiguracji wymaga Twojej uwagi.",
|
||||
"title": "Coś wymaga twojej uwagi"
|
||||
},
|
||||
"itemError": "Coś jest nie tak z tym ustawieniem. Ponownie przejdź przez konfigurację, aby to naprawić.",
|
||||
"items": {
|
||||
"default": "Domyślna konfiguracja",
|
||||
"extension": "Rozszerzenie",
|
||||
"proxy": "Niestandardowy serwer proxy"
|
||||
},
|
||||
"redoSetup": "Ponów konfigurację",
|
||||
"successStatus": {
|
||||
"description": "Wszystko jest gotowe, abyś mógł zacząć oglądać ulubione media.",
|
||||
"title": "Wszystko jest gotowe!"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "Kliknij przycisk po prawej stronie, aby rozpocząć proces konfiguracji.",
|
||||
"title": "Nie przeszedłeś konfiguracji"
|
||||
}
|
||||
},
|
||||
"title": "Połączenia",
|
||||
"workers": {
|
||||
"addButton": "Dodaj nowego pracownika",
|
||||
"description": "Aby aplikacja działała, cały ruch jest kierowany przez serwery proxy. Włącz tę opcję, jeśli chcesz korzystać z własnych pracowników.",
|
||||
"description": "Aby aplikacja działała, cały ruch jest kierowany przez serwery proxy. Włącz tę opcję, jeśli chcesz korzystać z własnych pracowników. <0>Instrukcje.</0>",
|
||||
"emptyState": "Brak pracowników, dodaj jednego poniżej",
|
||||
"label": "Używaj niestandardowych pracowników proxy",
|
||||
"urlLabel": "Adresy URL pracowników",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"preferences": {
|
||||
"language": "Język aplikacji",
|
||||
"languageDescription": "Język zastosowany do całej aplikacji.",
|
||||
"title": "Ustawienia regionalne"
|
||||
"thumbnail": "Generuj miniatury",
|
||||
"thumbnailDescription": "W większości przypadków filmy nie mają miniatur. Możesz włączyć to ustawienie, aby generować je na bieżąco, ale może to spowolnić wideo.",
|
||||
"thumbnailLabel": "Generuj miniatury",
|
||||
"title": "Preferencje"
|
||||
},
|
||||
"reset": "Reset",
|
||||
"save": "Zapisz",
|
||||
|
@ -95,6 +95,7 @@
|
||||
"about": "Sobre",
|
||||
"dmca": "DMCA",
|
||||
"login": "Entrar",
|
||||
"onboarding": "Configuração",
|
||||
"pagetitle": "{{title}} - movie-web",
|
||||
"register": "Registrar",
|
||||
"settings": "Configurações"
|
||||
@ -122,7 +123,7 @@
|
||||
"day": {
|
||||
"default": "O que você gostaria de assistir esta tarde?",
|
||||
"extra": [
|
||||
"Me sentindo aventureiro? Jurassic Park pode ser a escolha perfeita."
|
||||
"Se sentindo aventureiro? Jurassic Park pode ser a escolha perfeita."
|
||||
]
|
||||
},
|
||||
"morning": {
|
||||
@ -165,6 +166,69 @@
|
||||
"message": "Procuramos em todos os lugares: debaixo das lixeiras, no armário, atrás do proxy, mas no final não conseguimos encontrar a página que você está procurando.",
|
||||
"title": "Não conseguimos encontrar essa página"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "Cancelar",
|
||||
"confirm": "Usar configuração padrão",
|
||||
"description": "A configuração padrão não possui os melhores streams e pode ser insuportavelmente lenta.",
|
||||
"title": "Você tem certeza?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "Voltar",
|
||||
"explainer": "Usando a extensão de navegador, você pode obter os melhores streams que temos a oferecer. Com apenas uma simples instalação.",
|
||||
"explainerIos": "Infelizmente, a extensão de navegador não é suportado no iOS. Pressione <bold>Voltar</bold> para escolher outra opção.",
|
||||
"extensionHelp": "Se você instalou a extensão mas ela não foi detectada, <bold>abra a extensão através do menu de extensões do seu navegador</bold> e siga as instruções na tela.",
|
||||
"linkChrome": "Instalar extensão do Chrome",
|
||||
"linkFirefox": "Instalar extensão do Firefox",
|
||||
"notDetecting": "Instalou no Chrome, mas o site não está detectando? Tente recarregar a página!",
|
||||
"notDetectingAction": "Recarregar página",
|
||||
"status": {
|
||||
"disallowed": "A extensão não está ativada para esta página",
|
||||
"disallowedAction": "Ativar extensão",
|
||||
"failed": "Falha ao solicitar status",
|
||||
"loading": "Aguardando que você instale a extensão",
|
||||
"outdated": "A versão da extensão é muito antiga",
|
||||
"success": "A extensão está funcionado como esperado!"
|
||||
},
|
||||
"submit": "Continuar",
|
||||
"title": "Vamos começar com uma extensão"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "Voltar",
|
||||
"explainer": "Com o método proxy, você pode obter streams de ótima qualidade criando um proxy de autoatendimento.",
|
||||
"input": {
|
||||
"errorConnection": "Não foi possível conectar ao proxy",
|
||||
"errorInvalidUrl": "Não é uma URL válida",
|
||||
"errorNotProxy": "Esperava um proxy, mas recebi um site",
|
||||
"label": "URL do Proxy",
|
||||
"placeholder": "https://"
|
||||
},
|
||||
"link": "Aprenda como criar um proxy",
|
||||
"submit": "Enviar proxy",
|
||||
"title": "Vamos preparar um novo proxy"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "Para obter os melhores streams possíveis, você precisará escolher qual método de streaming deseja usar.",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "Eu não quero streams de boa qualidade, <0 /> <1>use a configuração padrão</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "Instalar extensão",
|
||||
"description": "Instale a extensão de navegador e tenha acesso às melhores fontes.",
|
||||
"quality": "Melhor qualidade",
|
||||
"title": "Extensão de navegador"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "Configurar proxy",
|
||||
"description": "Configure um proxy em apenas 5 minutos e tenha acesso a ótimas fontes.",
|
||||
"quality": "Boa qualidade",
|
||||
"title": "Proxy personalizado"
|
||||
}
|
||||
},
|
||||
"title": "Vamos juntos configurar o movie-web"
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "Fechar"
|
||||
},
|
||||
@ -182,7 +246,7 @@
|
||||
"downloadPlaylist": "Baixar playlist",
|
||||
"downloadSubtitle": "Baixar legenda atual",
|
||||
"downloadVideo": "Baixar vídeo",
|
||||
"hlsDisclaimer": "Os downloads são feitos diretamente do provedor. movie-web não tem controle sobre como os downloads são fornecidos. Por favor, note que você está baixando uma playlist HLS, isso é destinado para usuários familiarizados com streaming multimídia avançado.",
|
||||
"hlsDisclaimer": "Os downloads são feitos diretamente do provedor. movie-web não tem controle sobre como os downloads são fornecidos.<br /><br />Por favor, note que você está baixando uma playlist HLS, <bold>isso é destinado para usuários familiarizados com streaming multimídia avançado.</bold>. Experimente outras fontes para formatos diferentes.",
|
||||
"onAndroid": {
|
||||
"1": "Para baixar no Android, clique no botão de download e, na nova página, <bold>toque e segure</bold> no vídeo, depois selecione <bold>salvar</bold>.",
|
||||
"shortTitle": "Baixar / Android",
|
||||
@ -263,6 +327,17 @@
|
||||
"text": "Não foi possível carregar os metadados da API. Por favor, verifique sua conexão com a internet.",
|
||||
"title": "Falha ao carregar os metadados da API"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "Removido",
|
||||
"text": "Esta mídia não está mais disponível devido a um aviso de remoção ou reivindicação de direitos autorais.",
|
||||
"title": "A mídia foi removida"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "Permissão Pendente",
|
||||
"button": "Usar extensão",
|
||||
"text": "Você possui a extensão de navegador, mas nós precisamos de sua permissão para começar a usá-la.",
|
||||
"title": "Configure a extensão"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "Falhou",
|
||||
"homeButton": "Ir para o início",
|
||||
@ -390,24 +465,49 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "Se você deseja se conectar a um backend personalizado para armazenar seus dados, ative isso e forneça a URL.",
|
||||
"description": "Se você deseja se conectar a um backend personalizado para armazenar seus dados, ative isso e forneça a URL. <0>Instruções.</0>",
|
||||
"label": "Servidor personalizado",
|
||||
"urlLabel": "URL do servidor personalizado"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "Configurar",
|
||||
"errorStatus": {
|
||||
"description": "Parece que um ou mais itens nesta configuração necessitam sua atenção.",
|
||||
"title": "Algo necessita de sua atenção"
|
||||
},
|
||||
"itemError": "Há algo errado com esta configuração. Realize uma nova configuração para corrigir.",
|
||||
"items": {
|
||||
"default": "Configuração padrão",
|
||||
"extension": "Extensão",
|
||||
"proxy": "Proxy personalizado"
|
||||
},
|
||||
"redoSetup": "Refazer configuração",
|
||||
"successStatus": {
|
||||
"description": "Tudo está pronto para você começar a assistir sua mídia favorita.",
|
||||
"title": "Está tudo pronto!"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "Por favor, clique no botão à direita para iniciar a configuração.",
|
||||
"title": "Você não realizou a configuração"
|
||||
}
|
||||
},
|
||||
"title": "Conexões",
|
||||
"workers": {
|
||||
"addButton": "Adicionar novo worker",
|
||||
"description": "Para fazer o aplicativo funcionar, todo o tráfego é roteado através de proxies. Ative isso se você quiser trazer seus próprios workers.",
|
||||
"description": "Para fazer o aplicativo funcionar, todo o tráfego é roteado através de proxies. Ative isso se você quiser trazer seus próprios workers. <0>Instruções.</0>",
|
||||
"emptyState": "Ainda não há workers, adicione um abaixo",
|
||||
"label": "Usar proxy workers personalizados",
|
||||
"urlLabel": "URLs dos workers",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"preferences": {
|
||||
"language": "Idioma do aplicativo",
|
||||
"languageDescription": "Idioma aplicado a todo o aplicativo.",
|
||||
"title": "Região"
|
||||
"languageDescription": "Idioma aplicado para todo o aplicativo.",
|
||||
"thumbnail": "Gerar miniaturas",
|
||||
"thumbnailDescription": "Na maior parte do tempo, os vídeos não possuem miniaturas. Você pode ativar esta configuração para gerá-las dinamicamente, mas elas podem tornar seu vídeo mais lento.",
|
||||
"thumbnailLabel": "Gerar miniaturas",
|
||||
"title": "Preferências"
|
||||
},
|
||||
"reset": "Redefinir",
|
||||
"save": "Salvar",
|
||||
|
432
src/assets/locales/pt-PT.json
Normal file
432
src/assets/locales/pt-PT.json
Normal file
@ -0,0 +1,432 @@
|
||||
{
|
||||
"about": {
|
||||
"description": "movie-web é uma aplicação web que pesquisa a internet por streams. A equipa visa uma abordagem maioritariamente minimalista na consumação de conteúdos.",
|
||||
"faqTitle": "Perguntas frequentes",
|
||||
"q1": {
|
||||
"body": "movie-web não hospeda nenhum conteúdo. Quando clica para assistir a algo, a internet é pesquisada para o media selecionado (Na tela de carregamento e na aba 'fontes de vídeo', pode ver qual a fonte que está a ser utilizada). O media nunca é carregado pelo movie-web, tudo é feito através deste mecanismo de pesquisa.",
|
||||
"title": "De onde vem o conteúdo?"
|
||||
},
|
||||
"q2": {
|
||||
"body": "Não é possível solicitar um programa ou filme, o movie-web não gere nenhum conteúdo. Todo o conteúdo é visualizado através de fontes na internet.",
|
||||
"title": "Onde posso solicitar um programa ou filme?"
|
||||
},
|
||||
"q3": {
|
||||
"body": "Os nossos resultados de pesquisa são alimentados pela The Movie Database (TMDB) e são exibidos independentemente de as nossas fontes realmente terem o conteúdo.",
|
||||
"title": "Os resultados da pesquisa mostram o programa ou filme, por que não consigo reproduzi-lo?"
|
||||
},
|
||||
"title": "Sobre o movie-web"
|
||||
},
|
||||
"actions": {
|
||||
"copied": "Copiado",
|
||||
"copy": "Copiar"
|
||||
},
|
||||
"auth": {
|
||||
"createAccount": "Ainda não tem uma conta? <0>Crie uma conta.</0>",
|
||||
"deviceNameLabel": "Nome do dispositivo",
|
||||
"deviceNamePlaceholder": "Telemóvel pessoal",
|
||||
"generate": {
|
||||
"description": "A sua frase-passe age como o seu nome de utilizador e senha. Certifique-se de a manter segura, pois precisará dela para entrar na sua conta",
|
||||
"next": "Guardei a minha frase-passe",
|
||||
"passphraseFrameLabel": "Frase-passe",
|
||||
"title": "A sua frase-passe"
|
||||
},
|
||||
"hasAccount": "Já tem uma conta? <0>Entre aqui.</0>",
|
||||
"login": {
|
||||
"description": "Por favor, introduza a sua frase-passe para entrar na sua conta",
|
||||
"deviceLengthError": "Por favor, introduza um nome de dispositivo",
|
||||
"passphraseLabel": "Frase-passe de 12 palavras",
|
||||
"passphrasePlaceholder": "Frase-passe",
|
||||
"submit": "Entrar",
|
||||
"title": "Entrar na sua conta",
|
||||
"validationError": "Frase-passe incorreta ou incompleta"
|
||||
},
|
||||
"register": {
|
||||
"information": {
|
||||
"color1": "Cor de perfil um",
|
||||
"color2": "Cor de perfil dois",
|
||||
"header": "Introduza um nome para o seu dispositivo e escolha cores e um ícone de utilizador da sua escolha",
|
||||
"icon": "Ícone de utilizador",
|
||||
"next": "Próximo",
|
||||
"title": "Informações da conta"
|
||||
}
|
||||
},
|
||||
"trust": {
|
||||
"failed": {
|
||||
"text": "Configurou corretamente?",
|
||||
"title": "Falha ao conectar-se ao servidor"
|
||||
},
|
||||
"host": "Está a conectar-se a <0>{{hostname}}</0> - confirme se confia antes de criar uma conta",
|
||||
"no": "Voltar",
|
||||
"title": "Confia neste servidor?",
|
||||
"yes": "Confio neste servidor"
|
||||
},
|
||||
"verify": {
|
||||
"description": "Por favor, introduza a sua frase-passe anterior para confirmar que a guardou e para criar a sua conta",
|
||||
"invalidData": "Dados inválidos",
|
||||
"noMatch": "A frase-passe não coincide",
|
||||
"passphraseLabel": "A sua frase-passe de 12 palavras",
|
||||
"recaptchaFailed": "Falha na validação do ReCaptcha",
|
||||
"register": "Criar conta",
|
||||
"title": "Confirmar a sua frase-passe"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"badge": "Houve um erro",
|
||||
"details": "Detalhes do erro",
|
||||
"reloadPage": "Recarregar a página",
|
||||
"showError": "Mostrar detalhes do erro",
|
||||
"title": "Encontrámos um erro!"
|
||||
},
|
||||
"footer": {
|
||||
"legal": {
|
||||
"disclaimer": "Aviso legal",
|
||||
"disclaimerText": "movie-web não hospeda quaisquer ficheiros, apenas faz ligações para serviços de terceiros. Problemas legais devem ser tratados com os anfitriões e fornecedores de ficheiros. O movie-web não é responsável por quaisquer ficheiros multimédia mostrados pelos fornecedores de vídeo."
|
||||
},
|
||||
"links": {
|
||||
"discord": "Discord",
|
||||
"dmca": "DMCA",
|
||||
"github": "GitHub"
|
||||
},
|
||||
"tagline": "Assista aos seus programas e filmes favoritos com esta aplicação de streaming de código aberto."
|
||||
},
|
||||
"global": {
|
||||
"name": "movie-web",
|
||||
"pages": {
|
||||
"about": "Sobre",
|
||||
"dmca": "DMCA",
|
||||
"login": "Entrar",
|
||||
"pagetitle": "{{title}} - movie-web",
|
||||
"register": "Registrar",
|
||||
"settings": "Configurações"
|
||||
}
|
||||
},
|
||||
"home": {
|
||||
"bookmarks": {
|
||||
"sectionTitle": "Marcadores"
|
||||
},
|
||||
"continueWatching": {
|
||||
"sectionTitle": "Continuar a assistir"
|
||||
},
|
||||
"mediaList": {
|
||||
"stopEditing": "Parar de editar"
|
||||
},
|
||||
"search": {
|
||||
"allResults": "É tudo o que temos!",
|
||||
"failed": "Falha ao encontrar mídia, tente novamente!",
|
||||
"loading": "A carregar...",
|
||||
"noResults": "Não conseguimos encontrar nada!",
|
||||
"placeholder": "O que deseja assistir?",
|
||||
"sectionTitle": "Resultados da pesquisa"
|
||||
},
|
||||
"titles": {
|
||||
"day": {
|
||||
"default": "O que gostaria de assistir esta tarde?",
|
||||
"extra": [
|
||||
"Sentindo-se aventureiro? Jurassic Park pode ser a escolha perfeita."
|
||||
]
|
||||
},
|
||||
"morning": {
|
||||
"default": "O que gostaria de assistir esta manhã?",
|
||||
"extra": [
|
||||
"Dizem que Antes do Amanhecer é bom"
|
||||
]
|
||||
},
|
||||
"night": {
|
||||
"default": "O que gostaria de assistir esta noite?",
|
||||
"extra": [
|
||||
"Cansado? Dizem que O Exorcista é bom."
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"media": {
|
||||
"episodeDisplay": "T{{season}} E{{episode}}",
|
||||
"types": {
|
||||
"movie": "Filme",
|
||||
"show": "Série"
|
||||
}
|
||||
},
|
||||
"navigation": {
|
||||
"banner": {
|
||||
"offline": "Verifique a sua conexão à internet"
|
||||
},
|
||||
"menu": {
|
||||
"about": "Sobre nós",
|
||||
"donation": "Doar",
|
||||
"logout": "Sair",
|
||||
"register": "Sincronizar com a nuvem",
|
||||
"settings": "Configurações",
|
||||
"support": "Suporte"
|
||||
}
|
||||
},
|
||||
"notFound": {
|
||||
"badge": "Não encontrado",
|
||||
"goHome": "Voltar para casa",
|
||||
"message": "Procurámos em todo lugar: embaixo dos caixotes, no armário, atrás do proxy, mas, no final, não conseguimos encontrar a página que procura.",
|
||||
"title": "Não foi possível encontrar essa página"
|
||||
},
|
||||
"overlays": {
|
||||
"close": "Fechar"
|
||||
},
|
||||
"player": {
|
||||
"back": {
|
||||
"default": "Voltar para casa",
|
||||
"short": "Voltar"
|
||||
},
|
||||
"casting": {
|
||||
"enabled": "Transmitindo para o dispositivo..."
|
||||
},
|
||||
"menus": {
|
||||
"downloads": {
|
||||
"disclaimer": "Os downloads são feitos diretamente pelo fornecedor. O movie-web não tem controle sobre como os downloads são fornecidos.",
|
||||
"downloadPlaylist": "Baixar lista de reprodução",
|
||||
"downloadSubtitle": "Baixar legenda atual",
|
||||
"downloadVideo": "Baixar vídeo",
|
||||
"hlsDisclaimer": "Os downloads são feitos diretamente pelo fornecedor. O movie-web não tem controle sobre como os downloads são fornecidos. Por favor, note que está a baixar uma lista de reprodução HLS, isso é destinado a utilizadores familiarizados com streaming multimídia avançado.",
|
||||
"onAndroid": {
|
||||
"1": "Para baixar no Android, clique no botão de download e, na nova página, <bold>toque e segure</bold> no vídeo, depois selecione <bold>guardar</bold>.",
|
||||
"shortTitle": "Baixar / Android",
|
||||
"title": "Baixando no Android"
|
||||
},
|
||||
"onIos": {
|
||||
"1": "Para baixar no iOS, clique no botão de download e, na nova página, clique em <bold><ios_share /></bold>, depois em <bold>Guardar no Ficheiro <ios_files /></bold>.",
|
||||
"shortTitle": "Baixar / iOS",
|
||||
"title": "Baixando no iOS"
|
||||
},
|
||||
"onPc": {
|
||||
"1": "No PC, clique no botão de download e, na nova página, clique com o botão direito no vídeo e selecione <bold>Guardar vídeo como</bold>",
|
||||
"shortTitle": "Baixar / PC",
|
||||
"title": "Baixando no PC"
|
||||
},
|
||||
"title": "Baixar"
|
||||
},
|
||||
"episodes": {
|
||||
"button": "Episódios",
|
||||
"emptyState": "Não há episódios nesta temporada, volte mais tarde!",
|
||||
"episodeBadge": "E{{episode}}",
|
||||
"loadingError": "Erro ao carregar a temporada",
|
||||
"loadingList": "A carregar...",
|
||||
"loadingTitle": "A carregar...",
|
||||
"unairedEpisodes": "Um ou mais episódios nesta temporada foram desativados porque ainda não foram transmitidos."
|
||||
},
|
||||
"playback": {
|
||||
"speedLabel": "Velocidade de reprodução",
|
||||
"title": "Configurações de reprodução"
|
||||
},
|
||||
"quality": {
|
||||
"automaticLabel": "Qualidade automática",
|
||||
"hint": "Pode tentar <0>mudar de fonte</0> para obter opções de qualidade diferentes.",
|
||||
"iosNoQuality": "Devido a limitações definidas pela Apple, a seleção de qualidade não está disponível no iOS para esta fonte. Pode tentar <0>mudar para outra fonte</0> para obter opções de qualidade diferentes.",
|
||||
"title": "Qualidade"
|
||||
},
|
||||
"settings": {
|
||||
"downloadItem": "Download",
|
||||
"enableSubtitles": "Ativar legendas",
|
||||
"experienceSection": "Experiência de visualização",
|
||||
"playbackItem": "Configurações de reprodução",
|
||||
"qualityItem": "Qualidade",
|
||||
"sourceItem": "Fontes de vídeo",
|
||||
"subtitleItem": "Configurações de legendas",
|
||||
"videoSection": "Configurações de vídeo"
|
||||
},
|
||||
"sources": {
|
||||
"failed": {
|
||||
"text": "Houve um erro ao tentar encontrar vídeos, por favor, tente uma fonte diferente.",
|
||||
"title": "Falha ao obter"
|
||||
},
|
||||
"noEmbeds": {
|
||||
"text": "Não conseguimos encontrar nenhum embed, por favor, tente uma fonte diferente.",
|
||||
"title": "Nenhum embed encontrado"
|
||||
},
|
||||
"noStream": {
|
||||
"text": "Esta fonte não tem transmissões para este filme ou série.",
|
||||
"title": "Sem transmissão"
|
||||
},
|
||||
"title": "Fontes",
|
||||
"unknownOption": "Desconhecido"
|
||||
},
|
||||
"subtitles": {
|
||||
"customChoice": "Selecionar legenda do arquivo",
|
||||
"customizeLabel": "Personalizar",
|
||||
"offChoice": "Desativar",
|
||||
"settings": {
|
||||
"backlink": "Legendas personalizadas",
|
||||
"delay": "Atraso das legendas",
|
||||
"fixCapitals": "Corrigir maiúsculas"
|
||||
},
|
||||
"title": "Legendas",
|
||||
"unknownLanguage": "Desconhecido"
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"api": {
|
||||
"text": "Não foi possível carregar os metadados da API, por favor verifique a sua conexão à internet.",
|
||||
"title": "Falha ao carregar os metadados da API"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "Falhou",
|
||||
"homeButton": "Ir para casa",
|
||||
"text": "Não foi possível carregar os metadados do media da TMDB. Por favor, verifique se a TMDB está indisponível ou bloqueada na sua conexão à internet.",
|
||||
"title": "Falha ao carregar os metadados"
|
||||
},
|
||||
"notFound": {
|
||||
"badge": "Não encontrado",
|
||||
"homeButton": "Voltar para casa",
|
||||
"text": "Não conseguimos encontrar o conteúdo que solicitou. Ou foi removido ou houve manipulação na URL.",
|
||||
"title": "Não foi possível encontrar esse conteúdo."
|
||||
}
|
||||
},
|
||||
"nextEpisode": {
|
||||
"cancel": "Cancelar",
|
||||
"next": "Próximo episódio"
|
||||
},
|
||||
"playbackError": {
|
||||
"badge": "Erro de reprodução",
|
||||
"errors": {
|
||||
"errorAborted": "A recuperação do conteúdo foi cancelada a pedido do utilizador.",
|
||||
"errorDecode": "Apesar de ter sido anteriormente considerado utilizável, ocorreu um erro ao tentar decodificar o recurso multimédia, resultando em um erro.",
|
||||
"errorGenericMedia": "Ocorreu um erro desconhecido no multimédia.",
|
||||
"errorNetwork": "Ocorreu algum tipo de erro de rede que impediu a recuperação bem-sucedida do multimédia, apesar de estar disponível anteriormente.",
|
||||
"errorNotSupported": "O objeto multimédia ou do fornecedor de multimédia não é suportado."
|
||||
},
|
||||
"homeButton": "Ir para casa",
|
||||
"text": "Ocorreu um erro ao tentar reproduzir o conteúdo multimédia. Por favor, tente novamente.",
|
||||
"title": "Falha ao reproduzir o vídeo!"
|
||||
},
|
||||
"scraping": {
|
||||
"items": {
|
||||
"failure": "Ocorreu um erro",
|
||||
"notFound": "Não possui o vídeo",
|
||||
"pending": "A verificar vídeos..."
|
||||
},
|
||||
"notFound": {
|
||||
"badge": "Não encontrado",
|
||||
"detailsButton": "Mostrar detalhes",
|
||||
"homeButton": "Ir para casa",
|
||||
"text": "Pesquisámos pelos nossos fornecedores e não conseguimos encontrar o conteúdo que procura! Não alojamos o conteúdo multimédia e não temos controlo sobre o que está disponível. Por favor, clique em 'Mostrar detalhes' abaixo para mais informações.",
|
||||
"title": "Não conseguimos encontrar isso"
|
||||
}
|
||||
},
|
||||
"time": {
|
||||
"regular": "{{timeWatched}} / {{duration}}",
|
||||
"remaining": "{{timeLeft}} restantes • Termina às {{timeFinished, datetime}}",
|
||||
"shortRegular": "{{timeWatched}}",
|
||||
"shortRemaining": "-{{timeLeft}}"
|
||||
},
|
||||
"turnstile": {
|
||||
"description": "Por favor, verifique que é humano completando o Captcha à direita. Isso é para manter o movie-web seguro!",
|
||||
"error": "Falha ao verificar a sua humanidade. Por favor, tente novamente.",
|
||||
"title": "Precisamos verificar que você é humano.",
|
||||
"verifyingHumanity": "Verificando a sua humanidade..."
|
||||
}
|
||||
},
|
||||
"screens": {
|
||||
"dmca": {
|
||||
"text": "Bem-vindo à página de contacto DMCA da movie-web! Respeitamos os direitos de propriedade intelectual e queremos resolver rapidamente quaisquer preocupações de direitos autorais. Se acredita que a sua obra protegida por direitos autorais foi usada indevidamente na nossa plataforma, envie um aviso DMCA detalhado para o email abaixo. Inclua uma descrição do material protegido por direitos autorais, os seus detalhes de contacto e uma declaração de boa fé. Comprometemo-nos a resolver essas questões prontamente e agradecemos a sua cooperação para manter a movie-web como um lugar que respeita a criatividade e os direitos autorais.",
|
||||
"title": "DMCA"
|
||||
},
|
||||
"loadingApp": "A carregar a aplicação",
|
||||
"loadingUser": "A carregar o seu perfil",
|
||||
"loadingUserError": {
|
||||
"logout": "Terminar sessão",
|
||||
"reset": "Repor servidor personalizado",
|
||||
"text": "Falha ao carregar o seu perfil",
|
||||
"textWithReset": "Falha ao carregar o seu perfil do servidor personalizado. Deseja repor para o servidor padrão?"
|
||||
},
|
||||
"migration": {
|
||||
"failed": "Falha ao migrar os seus dados.",
|
||||
"inProgress": "Por favor aguarde, estamos a migrar os seus dados. Isto não deverá demorar muito."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"account": {
|
||||
"accountDetails": {
|
||||
"deviceNameLabel": "Nome do dispositivo",
|
||||
"deviceNamePlaceholder": "Telemóvel pessoal",
|
||||
"editProfile": "Editar",
|
||||
"logoutButton": "Terminar sessão"
|
||||
},
|
||||
"actions": {
|
||||
"delete": {
|
||||
"button": "Eliminar conta",
|
||||
"confirmButton": "Eliminar conta",
|
||||
"confirmDescription": "Tem a certeza de que deseja eliminar a sua conta? Todos os seus dados serão perdidos!",
|
||||
"confirmTitle": "Tem a certeza?",
|
||||
"text": "Esta ação é irreversível. Todos os dados serão eliminados e nada poderá ser recuperado.",
|
||||
"title": "Eliminar conta"
|
||||
},
|
||||
"title": "Ações"
|
||||
},
|
||||
"devices": {
|
||||
"deviceNameLabel": "Nome do dispositivo",
|
||||
"failed": "Falha ao carregar as sessões",
|
||||
"removeDevice": "Remover",
|
||||
"title": "Dispositivos"
|
||||
},
|
||||
"profile": {
|
||||
"finish": "Terminar edição",
|
||||
"firstColor": "Cor do perfil um",
|
||||
"secondColor": "Cor do perfil dois",
|
||||
"title": "Editar imagem de perfil",
|
||||
"userIcon": "Ícone de utilizador"
|
||||
},
|
||||
"register": {
|
||||
"cta": "Começar",
|
||||
"text": "Partilhe o seu progresso de visualização entre dispositivos e mantenha-os sincronizados.",
|
||||
"title": "Sincronizar com a nuvem"
|
||||
},
|
||||
"title": "Conta"
|
||||
},
|
||||
"appearance": {
|
||||
"activeTheme": "Ativo",
|
||||
"themes": {
|
||||
"blue": "Azul",
|
||||
"default": "Padrão",
|
||||
"gray": "Cinzento",
|
||||
"red": "Vermelho",
|
||||
"teal": "Verde-azulado"
|
||||
},
|
||||
"title": "Aparência"
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "Se desejar ligar a um servidor personalizado para armazenar os seus dados, ative isto e forneça o URL.",
|
||||
"label": "Servidor personalizado",
|
||||
"urlLabel": "URL do servidor personalizado"
|
||||
},
|
||||
"title": "Conexões",
|
||||
"workers": {
|
||||
"addButton": "Adicionar novo trabalhador",
|
||||
"description": "Para que a aplicação funcione, todo o tráfego é encaminhado através de proxies. Ative isto se quiser utilizar os seus próprios trabalhadores.",
|
||||
"emptyState": "Ainda não há trabalhadores, adicione um abaixo",
|
||||
"label": "Utilizar trabalhadores de proxy personalizados",
|
||||
"urlLabel": "URLs do trabalhador",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"reset": "Repor",
|
||||
"save": "Guardar",
|
||||
"sidebar": {
|
||||
"info": {
|
||||
"appVersion": "Versão da aplicação",
|
||||
"backendUrl": "URL do backend",
|
||||
"backendVersion": "Versão do backend",
|
||||
"hostname": "Hostname",
|
||||
"insecure": "Inseguro",
|
||||
"notLoggedIn": "Não está autenticado",
|
||||
"secure": "Seguro",
|
||||
"title": "Informações da aplicação",
|
||||
"unknownVersion": "Desconhecida",
|
||||
"userId": "ID de utilizador"
|
||||
}
|
||||
},
|
||||
"subtitles": {
|
||||
"backgroundLabel": "Opacidade do fundo",
|
||||
"colorLabel": "Cor",
|
||||
"previewQuote": "Não devo temer. O medo é o assassino da mente.",
|
||||
"textSizeLabel": "Tamanho do texto",
|
||||
"title": "Legendas"
|
||||
},
|
||||
"unsaved": "Tem alterações não guardadas"
|
||||
}
|
||||
}
|
@ -263,6 +263,17 @@
|
||||
"text": "Metadatele API nu au putut fi încărcate, vă rugăm să vă verificați conexiunea la internet.",
|
||||
"title": "Nu s-a putut incărca API metadata"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "Șters",
|
||||
"text": "Această medie nu mai este valabilă din vina copyright-ului.",
|
||||
"title": "Media a fost ștearsă"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "Permisune pierdută",
|
||||
"button": "Folosește extensia",
|
||||
"text": "Tu ai extensia, dar noi avem nevoie de permisiune ca să începem să folosim extensia.",
|
||||
"title": "Configurează extensia"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "Eșuat",
|
||||
"homeButton": "Du-te acasă :)",
|
||||
@ -394,6 +405,11 @@
|
||||
"label": "Server personalizat",
|
||||
"urlLabel": "Adresa URL personalizată a serverului"
|
||||
},
|
||||
"setup": {
|
||||
"errorStatus": {
|
||||
"title": "Ceva are nevoie de atenția ta"
|
||||
}
|
||||
},
|
||||
"title": "Conexiuni",
|
||||
"workers": {
|
||||
"addButton": "Adaugă un nou muncitor",
|
||||
@ -404,11 +420,6 @@
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"language": "Limba aplicației",
|
||||
"languageDescription": "Limbajul aplicat întregii aplicații.",
|
||||
"title": "Local"
|
||||
},
|
||||
"reset": "Resetare",
|
||||
"save": "Salvează",
|
||||
"sidebar": {
|
||||
|
@ -64,13 +64,18 @@
|
||||
"description": "Пожалуйста, введите фразу, полученную ранее, чтобы подтвердить, что вы ее сохранили, и создать свой аккаунт",
|
||||
"invalidData": "Дата инвалидная",
|
||||
"noMatch": "Парольная фраза не совпадает",
|
||||
"register": "Создать учётную запись"
|
||||
"passphraseLabel": "Ваша 12-словная парольная фраза",
|
||||
"recaptchaFailed": "Проверка ReCaptcha не удалась",
|
||||
"register": "Создать учётную запись",
|
||||
"title": "Подтвердите парольную фразу"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"badge": "Оно сломалось",
|
||||
"details": "Подробности ошибки",
|
||||
"reloadPage": "Перезагрузить страницу",
|
||||
"showError": "Показать сведения об ошибке"
|
||||
"showError": "Показать сведения об ошибке",
|
||||
"title": "Мы столкнулись с ошибкой!"
|
||||
},
|
||||
"footer": {
|
||||
"legal": {
|
||||
@ -106,6 +111,8 @@
|
||||
"search": {
|
||||
"allResults": "Это все, что у нас есть!",
|
||||
"loading": "Загрузка...",
|
||||
"noResults": "Мы не смогли ничего найти!",
|
||||
"placeholder": "Что вы хотите посмотреть?",
|
||||
"sectionTitle": "Результаты поиска"
|
||||
}
|
||||
},
|
||||
@ -128,6 +135,9 @@
|
||||
"support": "Поддержка"
|
||||
}
|
||||
},
|
||||
"notFound": {
|
||||
"title": "Не удалось найти эту страницу"
|
||||
},
|
||||
"overlays": {
|
||||
"close": "Закрыть"
|
||||
},
|
||||
@ -164,7 +174,24 @@
|
||||
"subtitleItem": "Настройки субтитров",
|
||||
"videoSection": "Настройки видео"
|
||||
},
|
||||
"sources": {
|
||||
"failed": {
|
||||
"text": "При попытке найти видео произошла ошибка, пожалуйста, попробуйте использовать другой источник."
|
||||
},
|
||||
"noEmbeds": {
|
||||
"text": "Мы не смогли найти ни одной вставки, пожалуйста, попробуйте использовать другой источник.",
|
||||
"title": "Не найдено ни одной вставки"
|
||||
},
|
||||
"noStream": {
|
||||
"text": "В этом источнике нет потоков для этого фильма или сериала.",
|
||||
"title": "Нет потока"
|
||||
},
|
||||
"title": "Источники",
|
||||
"unknownOption": "Неизвестный"
|
||||
},
|
||||
"subtitles": {
|
||||
"customChoice": "Выбрать субтитры из файла",
|
||||
"offChoice": "Выключить",
|
||||
"settings": {
|
||||
"backlink": "Пользовательские субтитры"
|
||||
},
|
||||
@ -182,6 +209,20 @@
|
||||
},
|
||||
"text": "При попытке воспроизвести медиа файл произошла ошибка. Пожалуйста, попробуйте ещё раз.",
|
||||
"title": "Не удалось воспроизвести видео!"
|
||||
},
|
||||
"scraping": {
|
||||
"notFound": {
|
||||
"detailsButton": "Показать детали",
|
||||
"title": "Мы не смогли найти"
|
||||
}
|
||||
},
|
||||
"time": {
|
||||
"regular": "{{timeWatched}} / {{duration}}"
|
||||
}
|
||||
},
|
||||
"screens": {
|
||||
"dmca": {
|
||||
"title": "DMCA"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
@ -216,6 +257,8 @@
|
||||
"userIcon": "Значок пользователя"
|
||||
},
|
||||
"register": {
|
||||
"cta": "Начать",
|
||||
"text": "Обменивайтесь информацией о прогрессе часов между устройствами и синхронизируйте их.",
|
||||
"title": "Синхронизировать с облаком"
|
||||
},
|
||||
"title": "Аккаунт"
|
||||
@ -233,7 +276,7 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "Если вы хотите подключиться к пользовательскому серверу для хранения ваших данных, включите эту опцию и укажите URL.",
|
||||
"description": "Если вы хотите подключиться к пользовательскому серверу для хранения ваших данных, включите эту опцию и укажите URL. <0>Инструкции.</0>",
|
||||
"label": "Пользовательский сервер",
|
||||
"urlLabel": "URL-адрес пользовательского сервера"
|
||||
},
|
||||
@ -241,26 +284,25 @@
|
||||
"workers": {
|
||||
"addButton": "Добавить новый прокси-сервер",
|
||||
"description": "Для работы приложения весь трафик маршрутизируется через прокси. Включите это, если вы хотите использовать свои собственных прокси-серверы.",
|
||||
"emptyState": "Прокси ещё нет, добавьте их ниже",
|
||||
"emptyState": "Прокси отсутствуют, добавьте их ниже",
|
||||
"label": "Использовать прокси-сервера",
|
||||
"urlLabel": "URL-адреса",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"language": "Язык приложения",
|
||||
"languageDescription": "Язык применяется ко всему приложению.",
|
||||
"title": "Локализация"
|
||||
},
|
||||
"reset": "Сброс",
|
||||
"save": "Сохранить",
|
||||
"sidebar": {
|
||||
"info": {
|
||||
"appVersion": "Версия приложения",
|
||||
"backendUrl": "Внутренний URL-адрес",
|
||||
"backendVersion": "Серверная версия",
|
||||
"hostname": "Имя хоста",
|
||||
"insecure": "Небезопасно",
|
||||
"notLoggedIn": "Вы не авторизованы",
|
||||
"secure": "Безопасный",
|
||||
"title": "Информация о приложении",
|
||||
"unknownVersion": "Неизвестный",
|
||||
"userId": "ID пользователя"
|
||||
}
|
||||
},
|
||||
|
@ -393,11 +393,6 @@
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"language": "Jezik aplikacije",
|
||||
"languageDescription": "Jezik, ki se uporablja za celotno aplikacijo.",
|
||||
"title": "Jezik"
|
||||
},
|
||||
"reset": "Ponastavi",
|
||||
"save": "Shrani",
|
||||
"sidebar": {
|
||||
|
@ -372,11 +372,6 @@
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"language": "Språk för applikationen",
|
||||
"languageDescription": "Språket som används i hela applikationen.",
|
||||
"title": "Plats"
|
||||
},
|
||||
"reset": "Återställ",
|
||||
"save": "Spara",
|
||||
"sidebar": {
|
||||
|
@ -389,11 +389,6 @@
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"language": "ภาษา",
|
||||
"languageDescription": "ภาษาที่ใช้กับแอปพลิเคชันทั้งหมด",
|
||||
"title": "ตำแหน่งที่ตั้ง"
|
||||
},
|
||||
"reset": "เริ่มใหม่",
|
||||
"save": "บันทึก",
|
||||
"sidebar": {
|
||||
|
@ -309,6 +309,9 @@
|
||||
}
|
||||
},
|
||||
"screens": {
|
||||
"dmca": {
|
||||
"title": "DMCA"
|
||||
},
|
||||
"loadingApp": "mi alasa e ilo",
|
||||
"loadingUser": "mi alasa e lipu sina",
|
||||
"loadingUserError": {
|
||||
@ -316,6 +319,9 @@
|
||||
"reset": "o sin e lawa ilo sina",
|
||||
"text": "alasa li pakala",
|
||||
"textWithReset": "alasa tan lawa ilo sina li pakala. sina wile e lawa ilo mi anu seme?"
|
||||
},
|
||||
"migration": {
|
||||
"inProgress": "o awen lili. mi alasa tawa e sona sina"
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
@ -369,13 +375,13 @@
|
||||
"title": "kule"
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "sina wile e poki sona ante la o pana e nimi ona lon ni",
|
||||
"label": "lawa ante",
|
||||
"urlLabel": "nimi pi lawa ante"
|
||||
},
|
||||
"title": "kulupu"
|
||||
},
|
||||
"locale": {
|
||||
"language": "toki ilo",
|
||||
"languageDescription": "ilo li toki kepeken toki ni:",
|
||||
"title": "toki"
|
||||
},
|
||||
"reset": "o weka e ante",
|
||||
"save": "o ante",
|
||||
"subtitles": {
|
||||
|
@ -74,7 +74,7 @@
|
||||
"badge": "Bir şeyler ters gitti",
|
||||
"details": "Hata detayları",
|
||||
"reloadPage": "Sayfayı yenile",
|
||||
"showError": "Hata detaylarını göster",
|
||||
"showError": "Hata ayrıntılarını göster",
|
||||
"title": "Bir hatayla karşılaştık!"
|
||||
},
|
||||
"footer": {
|
||||
@ -206,7 +206,8 @@
|
||||
"episodeBadge": "B{{episode}}",
|
||||
"loadingError": "Sezon yüklenirken hata oluştu",
|
||||
"loadingList": "Yükleniyor...",
|
||||
"loadingTitle": "Yükleniyor..."
|
||||
"loadingTitle": "Yükleniyor...",
|
||||
"unairedEpisodes": "Bu sezondaki bir veya daha fazla bölüm henüz yayınlanmadığı için devre dışı bırakılmıştır."
|
||||
},
|
||||
"playback": {
|
||||
"speedLabel": "Oynatma hızı",
|
||||
@ -246,7 +247,7 @@
|
||||
},
|
||||
"subtitles": {
|
||||
"customChoice": "Altyazı dosyası yükle",
|
||||
"customizeLabel": "Kişiselleştir",
|
||||
"customizeLabel": "Seçenekler",
|
||||
"offChoice": "Kapat",
|
||||
"settings": {
|
||||
"backlink": "Kişisel altyazılar",
|
||||
@ -258,6 +259,10 @@
|
||||
}
|
||||
},
|
||||
"metadata": {
|
||||
"api": {
|
||||
"text": "API üstverisi yüklenemedi, lütfen internet bağlantınızı kontrol edin.",
|
||||
"title": "API üstverisi yüklenemedi"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "Başarısız oldu",
|
||||
"homeButton": "Ana sayfaya dön",
|
||||
@ -296,7 +301,7 @@
|
||||
},
|
||||
"notFound": {
|
||||
"badge": "Bulunamadı",
|
||||
"detailsButton": "Detayları göster",
|
||||
"detailsButton": "Ayrıntıları göster",
|
||||
"homeButton": "Ana sayfaya git",
|
||||
"text": "Sağlayıcılarımız arasında arama yaptık ve aradığınız medyayı bulamadık! Medyaları barındırmıyoruz ve mevcut olanlar üzerinde hiçbir kontrolümüz yok. Daha fazla ayrıntı için lütfen aşağıdaki 'Ayrıntıları göster' seçeneğine tıklayın.",
|
||||
"title": "Bunu bulamadık"
|
||||
@ -307,6 +312,12 @@
|
||||
"remaining": "{{timeLeft}} kaldı • {{timeFinished, datetime}}'de bitiyor",
|
||||
"shortRegular": "{{timeWatched}}",
|
||||
"shortRemaining": "-{{timeLeft}}"
|
||||
},
|
||||
"turnstile": {
|
||||
"description": "Lütfen sağ taraftaki Captcha'yı çözerek insan olduğunuzu doğrulayın. Bu, movie-web'i güvende tutmak içindir!",
|
||||
"error": "İnsan olduğunuz doğrulanamadı. Lütfen tekrar deneyin.",
|
||||
"title": "İnsan olduğunuzu doğrulamamız gerekiyor.",
|
||||
"verifyingHumanity": "İnsan olduğunuz doğrulanıyor..."
|
||||
}
|
||||
},
|
||||
"screens": {
|
||||
@ -379,25 +390,20 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "Verilerinizi depolamak için özel bir arkayüze bağlanmak istiyorsanız, bunu etkinleştirin ve URL'yi sağlayın.",
|
||||
"description": "Verilerinizi depolamak için özel bir arkayüze bağlanmak istiyorsanız, bunu etkinleştirin ve URL'yi sağlayın. <0>Yönergeler.</0>",
|
||||
"label": "Özel sunucu",
|
||||
"urlLabel": "Özel sunucu URL'si"
|
||||
},
|
||||
"title": "Bağlantılar",
|
||||
"workers": {
|
||||
"addButton": "Yeni işleyici ekle",
|
||||
"description": "Uygulamanın çalışması için tüm trafik vekil sunucular üzerinden yönlendirilir. Kendi işleyicilerinizi getirmek istiyorsanız bunu etkinleştirin.",
|
||||
"description": "Uygulamanın çalışması için tüm trafik vekil sunucular üzerinden yönlendirilir. Kendi işleyicilerinizi getirmek istiyorsanız bunu etkinleştirin.<0>Yönergeler.</0>",
|
||||
"emptyState": "Henüz işleyici yok, aşağıya bir tane ekleyin",
|
||||
"label": "Özel vekil sunucu işleyici kullan",
|
||||
"urlLabel": "İşleyici URL'leri",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"language": "Uygulama dili",
|
||||
"languageDescription": "Uygulamanın tamamına uygulanan dil.",
|
||||
"title": "Yerelleştirme"
|
||||
},
|
||||
"reset": "Sıfırla",
|
||||
"save": "Kaydet",
|
||||
"sidebar": {
|
||||
@ -417,7 +423,7 @@
|
||||
"subtitles": {
|
||||
"backgroundLabel": "Arka plan opaklığı",
|
||||
"colorLabel": "Renk",
|
||||
"previewQuote": "Korkmamalıyım. Korku akıl katilidir.",
|
||||
"previewQuote": "Korkmamalıyım. Korku aklın katilidir.",
|
||||
"textSizeLabel": "Yazı boyutu",
|
||||
"title": "Altyazılar"
|
||||
},
|
||||
|
@ -95,6 +95,7 @@
|
||||
"about": "Про",
|
||||
"dmca": "DMCA",
|
||||
"login": "Логін",
|
||||
"onboarding": "Встановлення",
|
||||
"pagetitle": "{{title}} - movie-web",
|
||||
"register": "Зареєструватися",
|
||||
"settings": "Налаштування"
|
||||
@ -165,6 +166,69 @@
|
||||
"message": "Ми шукали всюди: під смітниками, у шафі, за проксі-сервером, але зрештою не змогли знайти сторінку, яку ви шукали.",
|
||||
"title": "Не вдалося знайти цю сторінку"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "Скасувати",
|
||||
"confirm": "Використовувати налаштування за умовчанням",
|
||||
"description": "Налаштування за замовчуванням не мають найкращих потоків і можуть бути нестерпно повільними.",
|
||||
"title": "Ви впевнені?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "Повернутись назад",
|
||||
"explainer": "Використовуючи розширення для браузера, ви можете отримати найякісніші трансляції, які ми можемо запропонувати. Просто встановивши його.",
|
||||
"explainerIos": "На жаль, розширення браузера не підтримується на iOS, натисніть <bold>Повернутися</bold>, щоб вибрати інший варіант.",
|
||||
"extensionHelp": "Якщо ви встановили розширення, але воно не виявлено. <bold>Відкрийте розширення в меню розширень вашого браузеру</bold> і дотримуйтеся вказівок на екрані.",
|
||||
"linkChrome": "Встанови Chrome розширення",
|
||||
"linkFirefox": "Встанови Firefox розширення",
|
||||
"notDetecting": "Встановили в Chrome, але сайт його не виявляє? Спробуйте перезавантажити сторінку!",
|
||||
"notDetectingAction": "Оновити сторінку",
|
||||
"status": {
|
||||
"disallowed": "Розширення не ввімкнено для цієї сторінки",
|
||||
"disallowedAction": "Активувати розширення",
|
||||
"failed": "Не вдалося отримати статус",
|
||||
"loading": "Очікуємо, поки ви встановите розширення",
|
||||
"outdated": "Версія розширення застаріла",
|
||||
"success": "Розширення працює як очікувалося!"
|
||||
},
|
||||
"submit": "Продовжити",
|
||||
"title": "Почати використовувати розширення"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "Повернутись назад",
|
||||
"explainer": "З використанням проксі ви можете отримати високоякісні потоки, створивши самостійний проксі-сервіс.",
|
||||
"input": {
|
||||
"errorConnection": "Не вдалося підключитися до проксі",
|
||||
"errorInvalidUrl": "Не валідний URL",
|
||||
"errorNotProxy": "Очікувався проксі, але отримано вебсайт",
|
||||
"label": "URL проксі",
|
||||
"placeholder": "https://"
|
||||
},
|
||||
"link": "Дізнайтесь як створити проксі",
|
||||
"submit": "Надати проксі",
|
||||
"title": "Давайте створимо новий проксі"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "Щоб отримати найкращу трансляцію, вам потрібно буде вибрати, який метод стрімінгу ви хочете використовувати.",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "Мені не потрібна хороша якість потоків,<0 /> <1>використовувати налаштування за замовчуванням</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "Встановити розширення",
|
||||
"description": "Встановіть розширення для браузера та отримайте доступ до найкращих джерел.",
|
||||
"quality": "Найкраща якість",
|
||||
"title": "Розширення браузера"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "Налаштування проксі",
|
||||
"description": "Налаштуйте проксі всього за 5 хвилин і отримайте доступ до чудових джерел.",
|
||||
"quality": "Гарна якість",
|
||||
"title": "Користувацький проксі"
|
||||
}
|
||||
},
|
||||
"title": "Давайте налаштуємо вам movie-web"
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "Закрити"
|
||||
},
|
||||
@ -182,7 +246,7 @@
|
||||
"downloadPlaylist": "Завантажити плейлист",
|
||||
"downloadSubtitle": "Завантажити поточні субтитри",
|
||||
"downloadVideo": "Завантажити відео",
|
||||
"hlsDisclaimer": "Завантаження виконуються безпосередньо від постачальника. У movie-web немає контролю над тим, як надаються завантаження. Будь ласка, зверніть увагу, що ви завантажуєте список відтворення HLS, він призначений для користувачів, знайомих із розширеним потоковим мультимедійним вмістом.",
|
||||
"hlsDisclaimer": "Завантаження виконуються безпосередньо від постачальника. У movie-web немає контролю над тим, як надаються завантаження.<br /><br />Зверніть увагу, що ви завантажуєте список відтворення HLS, <bold>його не рекомендується завантажувати, якщо ви не знайомі з розширеними форматами потокового передавання</bold>. Спробуйте різні джерела для інших форматів.",
|
||||
"onAndroid": {
|
||||
"1": "Щоб завантажити на Android, натисніть кнопку завантаження, потім на новій сторінці <bold>торкніться й утримуйте</bold> відео, а потім виберіть <bold>зберегти</bold>.",
|
||||
"shortTitle": "Завантажити / Android",
|
||||
@ -263,6 +327,17 @@
|
||||
"text": "Не вдалося завантажити метадані API, перевірте підключення до Інтернету.",
|
||||
"title": "Не вдалося завантажити метадані API"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "Видалено",
|
||||
"text": "Це медіа більше не доступне через повідомлення про видалення або позов про порушення авторських прав.",
|
||||
"title": "Медіа було видалено"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "Дозвіл Відсутній",
|
||||
"button": "Використовувати розширення",
|
||||
"text": "У вас вже є розширення для браузера, але нам потрібен ваш дозвіл, щоб почати використовувати його.",
|
||||
"title": "Налаштуйте продовження"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "Не вдалося",
|
||||
"homeButton": "Повернутися на головну",
|
||||
@ -322,7 +397,7 @@
|
||||
},
|
||||
"screens": {
|
||||
"dmca": {
|
||||
"text": "Ласкаво просимо на контактну сторінку DMCA від movie-web! Ми поважаємо права інтелектуальної власності і прагнемо швидко вирішувати будь-які проблеми, пов'язані з авторськими правами. Якщо ви вважаєте, що ваша робота, захищена авторським правом, була неналежним чином використана на нашій платформі, будь ласка, надішліть детальне повідомлення DMCA на електронну адресу нижче. Будь ласка, додайте опис матеріалу, захищеного авторським правом, ваші контактні дані та заяву з обґрунтуванням ваших сумлінних переконань. Ми прагнемо оперативно вирішити ці питання і будемо вдячні за вашу співпрацю у збереженні movie-web місцем, де поважають творчість і авторські права.",
|
||||
"text": "Вітаємо на нашій сторінці зв'язку DMCA! Ми поважаємо права інтелектуальної власності і хочемо вирішити будь-які проблеми з авторськими правами швидко. Якщо ви вважаєте, що ваші авторські права були неправильно використані на нашій платформі, будь ласка, надішліть детальне повідомлення DMCA на електронну адресу нижче. Будь ласка, вкажіть опис авторського матеріалу, ваші контактні дані та заяву про добросовісну віру. Ми зобов'язані вирішити ці питання оперативно і вдячні за вашу співпрацю в збереженні movie-web місцем, яке поважає творчість та авторські права.",
|
||||
"title": "DMCA"
|
||||
},
|
||||
"loadingApp": "Завантаження застосунку",
|
||||
@ -381,7 +456,7 @@
|
||||
"activeTheme": "Активна тема",
|
||||
"themes": {
|
||||
"blue": "Блакитний",
|
||||
"default": "Основний",
|
||||
"default": "За замовчуванням",
|
||||
"gray": "Сірий",
|
||||
"red": "Червоний",
|
||||
"teal": "Бірюзовий"
|
||||
@ -390,24 +465,49 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "Якщо ви хочете підключитися до кастомного серверу для зберігання ваших даних, увімкніть це та надайте URL.",
|
||||
"description": "Якщо ви бажаєте підключитися до користувацького сервера для зберігання даних, увімкніть це та вкажіть URL-адресу. <0>Інструкції.</0>",
|
||||
"label": "Власний сервер",
|
||||
"urlLabel": "URL сервера"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "Виконайте налаштування",
|
||||
"errorStatus": {
|
||||
"description": "Здається, що один або декілька пунктів у цьому налаштуванні потребують вашої уваги.",
|
||||
"title": "Дещо потребує вашої уваги"
|
||||
},
|
||||
"itemError": "Щось не так із цією настройкою. Пройдіть налаштування ще раз, щоб виправити це.",
|
||||
"items": {
|
||||
"default": "Налаштування за замовчанням",
|
||||
"extension": "Розширення",
|
||||
"proxy": "Користувацький проксі"
|
||||
},
|
||||
"redoSetup": "Повторити налаштування",
|
||||
"successStatus": {
|
||||
"description": "Усе готово для того, щоб ви могли почати дивитися улюблені медіа.",
|
||||
"title": "Все готово!"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "Будь ласка, натисніть кнопку праворуч, щоб розпочати процес налаштування.",
|
||||
"title": "Ви не завершили налаштування"
|
||||
}
|
||||
},
|
||||
"title": "З'єднання",
|
||||
"workers": {
|
||||
"addButton": "Додати нового працівника",
|
||||
"description": "Щоб додаток працював, весь трафік маршрутизується через проксі-сервери. Увімкніть це, якщо ви хочете використовувати власні проксі воркери.",
|
||||
"description": "Щоб додаток працював, весь трафік маршрутизується через проксі-сервери. Увімкніть це, якщо ви хочете використовувати власні проксі воркери. <0>Інструкція.</0>",
|
||||
"emptyState": "Немає працівників",
|
||||
"label": "Використовувати власних проксі-працівників",
|
||||
"urlLabel": "URL-у працівника",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"language": "Мова застосунку",
|
||||
"languageDescription": "Виберіть мову, яку ви хочете використовувати.",
|
||||
"title": "Налаштування локації"
|
||||
"preferences": {
|
||||
"language": "Мова додатку",
|
||||
"languageDescription": "Мова застосована до всього додатку.",
|
||||
"thumbnail": "Створити мініатюри",
|
||||
"thumbnailDescription": "Часто відео не мають мініатюр. Ви можете активувати цей параметр для їх генерації під час відтворення, але це може уповільнити відтворення відео.",
|
||||
"thumbnailLabel": "Сгенерувати мініатюри",
|
||||
"title": "Параметри"
|
||||
},
|
||||
"reset": "Скинути налаштування",
|
||||
"save": "Зберегти",
|
||||
|
@ -1,18 +1,18 @@
|
||||
{
|
||||
"about": {
|
||||
"description": "movie-web là một ứng dụng web tìm kiếm các truyền pháp trực tuyến trên internet. Nhóm phát triển ứng dụng này nhắm đến một cách tiêu thụ nội dung chủ yếu là đơn giản hơn.",
|
||||
"description": "movie-web là một ứng dụng web tìm kiếm các nguồn truyền phát trực tuyến trên Internet. Nhóm phát triển ứng dụng này nhắm đến một cách dễ dàng hơn trong việc tiêu thụ nội dung.",
|
||||
"faqTitle": "Các câu hỏi thường gặp",
|
||||
"q1": {
|
||||
"body": "movie-web không lưu trữ bất kì nội dung nào. Khi bạn bấm vào một cái gì đó để xem, ứng dụng sẽ tìm kiếm nội dung đó trên internet (Trên màn hình tải và trong tab 'nguồn video' bạn sẽ tìm thấy nguồn đang được dùng). Nội dung không bao giờ được tải lên trên movie-web, mọi thứ đều thông qua cơ chế tìm kiếm này.",
|
||||
"body": "movie-web không lưu trữ bất kì nội dung nào. Khi bạn chọn xem một nội dung nào đó, ứng dụng sẽ tìm kiếm nội dung đó trên Internet (Khi nội dung tải và trong tab 'nguồn video' bạn sẽ tìm thấy nguồn đang được dùng). Nội dung không bao giờ được tải lên trên movie-web, mọi thứ đều được tìm kiếm thông qua phương thức này.",
|
||||
"title": "Nội dung đến từ đâu?"
|
||||
},
|
||||
"q2": {
|
||||
"body": "Việc yêu cầu một chương trình truyền hình hoặc phim là bất khả thi bởi vì movie-web không quản lý nội dung nào. Tất cả nội dung được truyền thông qua các nguồn trên internet.",
|
||||
"title": "Tôi có thể yêu cầu một chương trình truyền hình hoặc phim ở đâu?"
|
||||
"body": "Việc yêu cầu thêm một chương trình truyền hình hoặc phim là điều bất khả thi bởi vì movie-web không quản lý bất kỳ nội dung nào. Tất cả nội dung được truyền thông qua những nguồn trên internet.",
|
||||
"title": "Tôi có thể yêu cầu thêm một chương trình truyền hình hoặc phim ở đâu?"
|
||||
},
|
||||
"q3": {
|
||||
"body": "Các kết quả tìm kiếm được cung cấp bởi The Movie Database (TMDB) và hiện lên bất kể các nguồn của trang thực sự có lưu trữ nội dung hay không.",
|
||||
"title": "Tại sao kết quả tìm kiếm hiển thị chương trình truyền hình hoặc phim nhưng tôi không thể chơi nó?"
|
||||
"body": "Các kết quả tìm kiếm được cung cấp bởi The Movie Database (TMDB) và hiện lên bất kể các nguồn của trang thực sự có lưu trữ nội dung đó hay không.",
|
||||
"title": "Tại sao kết quả tìm kiếm hiển thị chương trình truyền hình hoặc phim nhưng tôi không thể xem nó?"
|
||||
},
|
||||
"title": "Về movie-web"
|
||||
},
|
||||
@ -52,12 +52,49 @@
|
||||
},
|
||||
"trust": {
|
||||
"failed": {
|
||||
"text": "Bạn đã lắp đặt nó một cách chính xác chưa?"
|
||||
}
|
||||
"text": "Bạn đã cài đặt nó một cách chính xác chưa?",
|
||||
"title": "Không thể truy vấn máy chủ"
|
||||
},
|
||||
"host": "Bạn đang kết nối đến máy chủ <0>{{hostname}}</0> - vui lòng chắc chắn rằng bạn tin tưởng máy chủ này trước khi tạo tài khoản",
|
||||
"no": "Quay lại",
|
||||
"title": "Bạn có tin tưởng máy chủ này không?",
|
||||
"yes": "Tôi tin tưởng máy chủ này"
|
||||
},
|
||||
"verify": {
|
||||
"description": "Vui lòng nhập mật ngữ của bạn lúc nãy đễ chắc chắn rằng bạn đã lưu nó và để tạo tài khoản",
|
||||
"invalidData": "Dữ liệu không hợp lệ",
|
||||
"noMatch": "Mật ngữ không khớp",
|
||||
"passphraseLabel": "Mật ngữ 12 ký tự của bạn",
|
||||
"recaptchaFailed": "Xác minh bằng ReCaptcha không hợp lệ",
|
||||
"register": "Tạo tài khoản",
|
||||
"title": "Nhập lại mật ngữ của bạn"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"badge": "Lỗi",
|
||||
"details": "Thông tin về lỗi",
|
||||
"reloadPage": "Tải lại trang",
|
||||
"showError": "Hiển thị thông tin về lỗi",
|
||||
"title": "Đã xảy ra lỗi!"
|
||||
},
|
||||
"footer": {
|
||||
"legal": {
|
||||
"disclaimer": "Tuyên bố miễn trừ trách nhiệm",
|
||||
"disclaimerText": "movie-web không lưu trữ bất kì file nào, nó chỉ đến những đường dẫn của các dịch vụ bên thứ ba. Bất kỳ vấn đề nào về pháp lý nên được đưa đến chủ sỡ hữu của file hoặc những nhà cung cấp đó. movie-web hoàn toàn không chịu trách nhiệm cho bất kỳ nội dung nào được chiếu từ các nhà cung cấp."
|
||||
},
|
||||
"links": {
|
||||
"discord": "Discord",
|
||||
"dmca": "DMCA",
|
||||
"github": "GitHub"
|
||||
},
|
||||
"tagline": "Xem các chương trình và phim yêu thích của bạn với ứng dụng phát trực tuyến nguồn mở này."
|
||||
},
|
||||
"global": {
|
||||
"name": "movie-web"
|
||||
"name": "movie-web",
|
||||
"pages": {
|
||||
"pagetitle": "{{title}} - movie-web",
|
||||
"register": "Đăng ký"
|
||||
}
|
||||
},
|
||||
"home": {
|
||||
"bookmarks": {
|
||||
|
@ -21,9 +21,9 @@
|
||||
"copy": "复制"
|
||||
},
|
||||
"auth": {
|
||||
"createAccount": "还没有账户? <0>创建一个。</0>",
|
||||
"createAccount": "还没有账户? <0>创建一个</0>",
|
||||
"deviceNameLabel": "设备名称",
|
||||
"deviceNamePlaceholder": "如:个人电话",
|
||||
"deviceNamePlaceholder": "如:我的手机",
|
||||
"generate": {
|
||||
"description": "您的密码短语相当于用户名与密码。由于您需要输入它来登录账户,请确保将其存放到安全位置",
|
||||
"next": "我已保存密码短语",
|
||||
@ -37,13 +37,13 @@
|
||||
"passphraseLabel": "12 词密码短语",
|
||||
"passphrasePlaceholder": "密码短语",
|
||||
"submit": "登录",
|
||||
"title": "登录到您的账户",
|
||||
"title": "登录您的账户",
|
||||
"validationError": "密码短语不正确或不完整"
|
||||
},
|
||||
"register": {
|
||||
"information": {
|
||||
"color1": "个人资料颜色 1",
|
||||
"color2": "个人资料颜色 2",
|
||||
"color1": "头像配色 1",
|
||||
"color2": "头像配色 2",
|
||||
"header": "为您的设备输入名称,并选取一组代表色和一个用户图标",
|
||||
"icon": "用户图标",
|
||||
"next": "下一步",
|
||||
@ -52,8 +52,8 @@
|
||||
},
|
||||
"trust": {
|
||||
"failed": {
|
||||
"text": "您是否正确配置了它?",
|
||||
"title": "服务器连通失败"
|
||||
"text": "您的配置是否正确?",
|
||||
"title": "服务器无法接通"
|
||||
},
|
||||
"host": "您正在连接到 <0>{{hostname}}</0> - 在创建账户前,确保您信任它",
|
||||
"no": "返回",
|
||||
@ -71,11 +71,11 @@
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"badge": "它损坏了",
|
||||
"badge": "它已损坏",
|
||||
"details": "错误细节",
|
||||
"reloadPage": "刷新页面",
|
||||
"showError": "显示错误细节",
|
||||
"title": "我们遇到了错误!"
|
||||
"title": "我们遭遇到错误!"
|
||||
},
|
||||
"footer": {
|
||||
"legal": {
|
||||
@ -95,6 +95,7 @@
|
||||
"about": "关于",
|
||||
"dmca": "DMCA",
|
||||
"login": "登录",
|
||||
"onboarding": "设定",
|
||||
"pagetitle": "{{title}} - movie-web",
|
||||
"register": "注册",
|
||||
"settings": "设置"
|
||||
@ -148,7 +149,7 @@
|
||||
},
|
||||
"navigation": {
|
||||
"banner": {
|
||||
"offline": "检查您的互联网连接"
|
||||
"offline": "请检查您的互联网连接"
|
||||
},
|
||||
"menu": {
|
||||
"about": "关于我们",
|
||||
@ -162,9 +163,72 @@
|
||||
"notFound": {
|
||||
"badge": "未找到",
|
||||
"goHome": "返回首页",
|
||||
"message": "我们已经到处找过了:不管是垃圾桶下、橱柜里或是代理之后。但最终并没有发现您查找的页面。",
|
||||
"message": "我们已经到处找过了:不管是废纸篓下、橱柜中还是代理服务之外,但最终并没有发现您查找的页面。",
|
||||
"title": "无法找到页面"
|
||||
},
|
||||
"onboarding": {
|
||||
"defaultConfirm": {
|
||||
"cancel": "取消",
|
||||
"confirm": "使用默认设定",
|
||||
"description": "默认设定不具备最好的视频流,并且播放速度可能慢得难以忍受。",
|
||||
"title": "您确定吗?"
|
||||
},
|
||||
"extension": {
|
||||
"back": "返回",
|
||||
"explainer": "使用浏览器扩展,您可以获得我们提供的最佳串流。只需简单的安装即可。",
|
||||
"explainerIos": "很遗憾,浏览器扩展不被 iOS 支持,单击<bold>返回</bold>以选择其他选项。",
|
||||
"extensionHelp": "如您已安装扩展程序但未被检测到,<bold>请从浏览器的扩展菜单打开扩展</bold> 并按屏幕上的指示操作。",
|
||||
"linkChrome": "安装 Chrome 扩展程序",
|
||||
"linkFirefox": "安装 Firefox 扩展程序",
|
||||
"notDetecting": "已在 Chrome 上安装,但网站未能检测到?尝试刷新页面!",
|
||||
"notDetectingAction": "刷新页面",
|
||||
"status": {
|
||||
"disallowed": "扩展程序未对本页面启用",
|
||||
"disallowedAction": "启用扩展程序",
|
||||
"failed": "请求状态失败",
|
||||
"loading": "正等待您安装扩展程序",
|
||||
"outdated": "扩展版本过旧",
|
||||
"success": "扩展程序工作正常!"
|
||||
},
|
||||
"submit": "继续",
|
||||
"title": "让我们从扩展程序开始"
|
||||
},
|
||||
"proxy": {
|
||||
"back": "返回",
|
||||
"explainer": "使用代理方式,您可以通过自助代理服务获得高质量的串流。",
|
||||
"input": {
|
||||
"errorConnection": "无法连接到代理",
|
||||
"errorInvalidUrl": "URL 无效",
|
||||
"errorNotProxy": "检测到常规网站,链接应指向代理",
|
||||
"label": "代理 URL",
|
||||
"placeholder": "https://"
|
||||
},
|
||||
"link": "了解如何设置代理",
|
||||
"submit": "提交代理",
|
||||
"title": "让我们设置新的代理"
|
||||
},
|
||||
"start": {
|
||||
"explainer": "为了尽可能获得最佳串流,您将要选择使用何种串流方法。",
|
||||
"options": {
|
||||
"default": {
|
||||
"text": "我不想使用高质量串流,<0 /> <1>使用默认设定</1>"
|
||||
},
|
||||
"extension": {
|
||||
"action": "安装扩展程序",
|
||||
"description": "安装浏览器扩展并获取最佳视频源。",
|
||||
"quality": "最佳质量",
|
||||
"title": "浏览器扩展"
|
||||
},
|
||||
"proxy": {
|
||||
"action": "设定代理",
|
||||
"description": "在 5 分钟内设定好代理并获取优质资源。",
|
||||
"quality": "高质量",
|
||||
"title": "自定义代理"
|
||||
}
|
||||
},
|
||||
"title": "让我们为您设定 movie-web"
|
||||
}
|
||||
},
|
||||
"overlays": {
|
||||
"close": "关闭"
|
||||
},
|
||||
@ -182,7 +246,7 @@
|
||||
"downloadPlaylist": "下载播放列表",
|
||||
"downloadSubtitle": "下载当前字幕",
|
||||
"downloadVideo": "下载视频",
|
||||
"hlsDisclaimer": "下载内容是直接从内容提供者获取的。movie-web 无法控制下载内容如何被提供。请注意,您正在下载 HLS 播放列表,这适用于熟悉高级多媒体串流技术的用户。",
|
||||
"hlsDisclaimer": "下载内容是直接从内容提供者获取的。movie-web 无法控制下载内容如何被提供。<br /><br />请注意,您正在下载 HLS 播放列表,<bold>如您不熟悉高级流媒体格式,我们不推荐此操作</bold>。如需下载其他格式,请尝试切换视频源。",
|
||||
"onAndroid": {
|
||||
"1": "要从 Android 下载,先点击下载按钮,之后在新的页面上, <bold>点击并按住</bold>视频,然后选择 <bold>保存</bold>。",
|
||||
"shortTitle": "下载 / Android",
|
||||
@ -263,6 +327,17 @@
|
||||
"text": "无法载入 API 元数据,请检查您的互联网连接。",
|
||||
"title": "载入 API 元数据失败"
|
||||
},
|
||||
"dmca": {
|
||||
"badge": "已移除",
|
||||
"text": "由于收到删除通知或版权声索,此媒体不再可用。",
|
||||
"title": "媒体已被移除"
|
||||
},
|
||||
"extensionPermission": {
|
||||
"badge": "缺失权限",
|
||||
"button": "使用扩展程序",
|
||||
"text": "您已安装浏览器扩展,但我们需要您的许可才能启用它。",
|
||||
"title": "配置扩展程序"
|
||||
},
|
||||
"failed": {
|
||||
"badge": "失败",
|
||||
"homeButton": "返回首页",
|
||||
@ -316,7 +391,7 @@
|
||||
"turnstile": {
|
||||
"description": "请完成右侧的验证码以验证您是人类。这是为了确保 movie-web 的安全!",
|
||||
"error": "验证失败。请重试。",
|
||||
"title": "我们需要验证您是人类。",
|
||||
"title": "我们需要验证您是不是人类。",
|
||||
"verifyingHumanity": "正在验证您是否为人类…"
|
||||
}
|
||||
},
|
||||
@ -390,24 +465,49 @@
|
||||
},
|
||||
"connections": {
|
||||
"server": {
|
||||
"description": "若您想连接到自定义后端保存数据,请启用此选项并提供 URL。",
|
||||
"description": "若您想连接到自定义后端保存数据,请启用此选项并提供 URL。 <0>查看指引</0>",
|
||||
"label": "自定义服务器",
|
||||
"urlLabel": "自定义服务器 URL"
|
||||
},
|
||||
"setup": {
|
||||
"doSetup": "进行设定",
|
||||
"errorStatus": {
|
||||
"description": "看起来此配置中的一项或多项需要您的注意。",
|
||||
"title": "有件事需要您的注意"
|
||||
},
|
||||
"itemError": "此设置存在错误。再次进行设定过程以修复它。",
|
||||
"items": {
|
||||
"default": "默认设定",
|
||||
"extension": "扩展程序",
|
||||
"proxy": "自定义代理"
|
||||
},
|
||||
"redoSetup": "重新进行设定",
|
||||
"successStatus": {
|
||||
"description": "一切已经就绪,您可以开始观赏喜爱的媒体了。",
|
||||
"title": "一切就绪!"
|
||||
},
|
||||
"unsetStatus": {
|
||||
"description": "请单击右侧的按钮开始进行设定。",
|
||||
"title": "您尚未完成设定"
|
||||
}
|
||||
},
|
||||
"title": "连接",
|
||||
"workers": {
|
||||
"addButton": "添加新的 Worker",
|
||||
"description": "要让应用程序正常运作,所有流量会通过代理路由。若您想使用自己的 Worker,请启用该选项。",
|
||||
"description": "要让应用程序正常运作,所有流量会通过代理路由。若您想使用自己的 Worker,请启用该选项。 <0>查看指引</0>",
|
||||
"emptyState": "还没有 Worker,在下方添加一个",
|
||||
"label": "使用自定义代理 Worker",
|
||||
"urlLabel": "Worker URL",
|
||||
"urlPlaceholder": "https://"
|
||||
}
|
||||
},
|
||||
"locale": {
|
||||
"preferences": {
|
||||
"language": "应用程序语言",
|
||||
"languageDescription": "当前已应用到整个应用程序的语言。",
|
||||
"title": "本地化"
|
||||
"languageDescription": "作用于整个应用程序的语言。",
|
||||
"thumbnail": "生成缩略图",
|
||||
"thumbnailDescription": "大多数时候,视频没有缩略图。您可以启用此设置以在视频播放时动态生成它们,但此选项可能会拖慢视频速度。",
|
||||
"thumbnailLabel": "生成缩略图",
|
||||
"title": "偏好设置"
|
||||
},
|
||||
"reset": "重设",
|
||||
"save": "保存",
|
||||
|
@ -87,6 +87,13 @@ export function progressResponsesToEntries(responses: ProgressResponse[]) {
|
||||
}
|
||||
|
||||
const item = items[v.tmdbId];
|
||||
|
||||
// Since each watched episode is a single array entry but with the same tmdbId, the root item updatedAt will only have the first episode's timestamp (which is not the newest).
|
||||
// Here, we are setting it explicitly so the updatedAt always has the highest updatedAt from the episodes.
|
||||
if (new Date(v.updatedAt).getTime() > item.updatedAt) {
|
||||
item.updatedAt = new Date(v.updatedAt).getTime();
|
||||
}
|
||||
|
||||
if (item.type === "movie") {
|
||||
item.progress = {
|
||||
duration: Number(v.duration),
|
||||
|
7
src/backend/extension/compatibility.ts
Normal file
7
src/backend/extension/compatibility.ts
Normal file
@ -0,0 +1,7 @@
|
||||
import { satisfies } from "semver";
|
||||
|
||||
const allowedExtensionRange = "~1.0.2";
|
||||
|
||||
export function isAllowedExtensionVersion(version: string): boolean {
|
||||
return satisfies(version, allowedExtensionRange);
|
||||
}
|
80
src/backend/extension/messaging.ts
Normal file
80
src/backend/extension/messaging.ts
Normal file
@ -0,0 +1,80 @@
|
||||
import {
|
||||
MessagesMetadata,
|
||||
sendToBackgroundViaRelay,
|
||||
} from "@plasmohq/messaging";
|
||||
|
||||
import { isAllowedExtensionVersion } from "@/backend/extension/compatibility";
|
||||
import { ExtensionMakeRequestResponse } from "@/backend/extension/plasmo";
|
||||
|
||||
// for some reason, about 500 ms is needed after
|
||||
// page load before the extension starts responding properly
|
||||
const isExtensionReady = new Promise<void>((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve();
|
||||
}, 500);
|
||||
});
|
||||
|
||||
let activeExtension = false;
|
||||
|
||||
async function sendMessage<MessageKey extends keyof MessagesMetadata>(
|
||||
message: MessageKey,
|
||||
payload: MessagesMetadata[MessageKey]["req"] | undefined = undefined,
|
||||
timeout: number = -1,
|
||||
) {
|
||||
await isExtensionReady;
|
||||
return new Promise<MessagesMetadata[MessageKey]["res"] | null>((resolve) => {
|
||||
if (timeout >= 0) setTimeout(() => resolve(null), timeout);
|
||||
sendToBackgroundViaRelay<
|
||||
MessagesMetadata[MessageKey]["req"],
|
||||
MessagesMetadata[MessageKey]["res"]
|
||||
>({
|
||||
name: message,
|
||||
body: payload,
|
||||
})
|
||||
.then((res) => {
|
||||
activeExtension = true;
|
||||
resolve(res);
|
||||
})
|
||||
.catch(() => {
|
||||
activeExtension = false;
|
||||
resolve(null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export async function sendExtensionRequest<T>(
|
||||
ops: MessagesMetadata["makeRequest"]["req"],
|
||||
): Promise<ExtensionMakeRequestResponse<T> | null> {
|
||||
return sendMessage("makeRequest", ops);
|
||||
}
|
||||
|
||||
export async function setDomainRule(
|
||||
ops: MessagesMetadata["prepareStream"]["req"],
|
||||
): Promise<MessagesMetadata["prepareStream"]["res"] | null> {
|
||||
return sendMessage("prepareStream", ops);
|
||||
}
|
||||
|
||||
export async function sendPage(
|
||||
ops: MessagesMetadata["openPage"]["req"],
|
||||
): Promise<MessagesMetadata["openPage"]["res"] | null> {
|
||||
return sendMessage("openPage", ops);
|
||||
}
|
||||
|
||||
export async function extensionInfo(): Promise<
|
||||
MessagesMetadata["hello"]["res"] | null
|
||||
> {
|
||||
const message = await sendMessage("hello", undefined, 500);
|
||||
return message;
|
||||
}
|
||||
|
||||
export function isExtensionActiveCached(): boolean {
|
||||
return activeExtension;
|
||||
}
|
||||
|
||||
export async function isExtensionActive(): Promise<boolean> {
|
||||
const info = await extensionInfo();
|
||||
if (!info?.success) return false;
|
||||
const allowedVersion = isAllowedExtensionVersion(info.version);
|
||||
if (!allowedVersion) return false;
|
||||
return info.allowed && info.hasPermission;
|
||||
}
|
71
src/backend/extension/plasmo.ts
Normal file
71
src/backend/extension/plasmo.ts
Normal file
@ -0,0 +1,71 @@
|
||||
export interface ExtensionBaseRequest {}
|
||||
|
||||
export type ExtensionBaseResponse<T = object> =
|
||||
| ({
|
||||
success: true;
|
||||
} & T)
|
||||
| {
|
||||
success: false;
|
||||
error: string;
|
||||
};
|
||||
|
||||
export type ExtensionHelloResponse = ExtensionBaseResponse<{
|
||||
version: string;
|
||||
allowed: boolean;
|
||||
hasPermission: boolean;
|
||||
}>;
|
||||
|
||||
export interface ExtensionMakeRequest extends ExtensionBaseRequest {
|
||||
url: string;
|
||||
method: string;
|
||||
headers?: Record<string, string>;
|
||||
body?: string | Record<string, any>;
|
||||
bodyType?: "string" | "FormData" | "URLSearchParams" | "object";
|
||||
}
|
||||
|
||||
export type ExtensionMakeRequestBodyType = ExtensionMakeRequest["bodyType"];
|
||||
|
||||
export type ExtensionMakeRequestResponse<T> = ExtensionBaseResponse<{
|
||||
response: {
|
||||
statusCode: number;
|
||||
headers: Record<string, string>;
|
||||
finalUrl: string;
|
||||
body: T;
|
||||
};
|
||||
}>;
|
||||
|
||||
export interface ExtensionPrepareStreamRequest extends ExtensionBaseRequest {
|
||||
ruleId: number;
|
||||
targetDomains: string[];
|
||||
requestHeaders?: Record<string, string>;
|
||||
responseHeaders?: Record<string, string>;
|
||||
}
|
||||
|
||||
export interface MmMetadata {
|
||||
hello: {
|
||||
req: ExtensionBaseRequest;
|
||||
res: ExtensionHelloResponse;
|
||||
};
|
||||
makeRequest: {
|
||||
req: ExtensionMakeRequest;
|
||||
res: ExtensionMakeRequestResponse<any>;
|
||||
};
|
||||
prepareStream: {
|
||||
req: ExtensionPrepareStreamRequest;
|
||||
res: ExtensionBaseResponse;
|
||||
};
|
||||
openPage: {
|
||||
req: ExtensionBaseRequest & {
|
||||
page: string;
|
||||
redirectUrl: string;
|
||||
};
|
||||
res: ExtensionBaseResponse;
|
||||
};
|
||||
}
|
||||
|
||||
interface MpMetadata {}
|
||||
|
||||
declare module "@plasmohq/messaging" {
|
||||
interface MessagesMetadata extends MmMetadata {}
|
||||
interface PortsMetadata extends MpMetadata {}
|
||||
}
|
17
src/backend/extension/request.ts
Normal file
17
src/backend/extension/request.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { ExtensionMakeRequestBodyType } from "./plasmo";
|
||||
|
||||
export function getBodyTypeFromBody(
|
||||
body: unknown,
|
||||
): ExtensionMakeRequestBodyType {
|
||||
if (typeof body === "string") return "string";
|
||||
if (body instanceof FormData) return "FormData";
|
||||
if (body instanceof URLSearchParams) return "URLSearchParams";
|
||||
return "object";
|
||||
}
|
||||
|
||||
export function convertBodyToObject(body: unknown): any {
|
||||
if (body instanceof FormData || body instanceof URLSearchParams) {
|
||||
return [...body];
|
||||
}
|
||||
return body;
|
||||
}
|
43
src/backend/extension/streams.ts
Normal file
43
src/backend/extension/streams.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { Stream } from "@movie-web/providers";
|
||||
|
||||
import { setDomainRule } from "@/backend/extension/messaging";
|
||||
|
||||
function extractDomain(url: string): string | null {
|
||||
try {
|
||||
const u = new URL(url);
|
||||
return u.hostname;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function extractDomainsFromStream(stream: Stream): string[] {
|
||||
if (stream.type === "hls") {
|
||||
return [extractDomain(stream.playlist)].filter((v): v is string => !!v);
|
||||
}
|
||||
if (stream.type === "file") {
|
||||
return Object.values(stream.qualities)
|
||||
.map((v) => extractDomain(v.url))
|
||||
.filter((v): v is string => !!v);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
function buildHeadersFromStream(stream: Stream): Record<string, string> {
|
||||
const headers: Record<string, string> = {};
|
||||
Object.entries(stream.headers ?? {}).forEach((entry) => {
|
||||
headers[entry[0]] = entry[1];
|
||||
});
|
||||
Object.entries(stream.preferredHeaders ?? {}).forEach((entry) => {
|
||||
headers[entry[0]] = entry[1];
|
||||
});
|
||||
return headers;
|
||||
}
|
||||
|
||||
export async function prepareStream(stream: Stream) {
|
||||
await setDomainRule({
|
||||
ruleId: 1,
|
||||
targetDomains: extractDomainsFromStream(stream),
|
||||
requestHeaders: buildHeadersFromStream(stream),
|
||||
});
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { ofetch } from "ofetch";
|
||||
|
||||
import { getApiToken, setApiToken } from "@/backend/helpers/providerApi";
|
||||
import { getLoadbalancedProxyUrl } from "@/utils/providers";
|
||||
import { getLoadbalancedProxyUrl } from "@/backend/providers/fetchers";
|
||||
|
||||
type P<T> = Parameters<typeof ofetch<T, any>>;
|
||||
type R<T> = ReturnType<typeof ofetch<T, any>>;
|
||||
|
@ -3,7 +3,9 @@ import { nanoid } from "nanoid";
|
||||
import { ofetch } from "ofetch";
|
||||
import { useCallback } from "react";
|
||||
|
||||
import { isExtensionActiveCached } from "@/backend/extension/messaging";
|
||||
import { ScrapingItems, ScrapingSegment } from "@/hooks/useProviderScrape";
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
import { PlayerMeta } from "@/stores/player/slices/source";
|
||||
|
||||
// for anybody who cares - these are anonymous metrics.
|
||||
@ -25,6 +27,15 @@ export type ProviderMetric = {
|
||||
fullError?: string;
|
||||
};
|
||||
|
||||
export type ScrapeTool = "default" | "custom-proxy" | "extension";
|
||||
|
||||
export function getScrapeTool(): ScrapeTool {
|
||||
if (isExtensionActiveCached()) return "extension";
|
||||
const hasProxySet = !!useAuthStore.getState().proxySet;
|
||||
if (hasProxySet) return "custom-proxy";
|
||||
return "default";
|
||||
}
|
||||
|
||||
function getStackTrace(error: Error, lines: number) {
|
||||
const topMessage = error.toString();
|
||||
const stackTraceLines = (error.stack ?? "").split("\n", lines + 1);
|
||||
@ -37,6 +48,7 @@ export async function reportProviders(items: ProviderMetric[]): Promise<void> {
|
||||
method: "POST",
|
||||
body: {
|
||||
items,
|
||||
tool: getScrapeTool(),
|
||||
batchId: batchId(),
|
||||
},
|
||||
});
|
||||
|
@ -1,15 +1,11 @@
|
||||
import {
|
||||
Fetcher,
|
||||
ProviderControls,
|
||||
makeProviders,
|
||||
makeSimpleProxyFetcher,
|
||||
makeStandardFetcher,
|
||||
targets,
|
||||
} from "@movie-web/providers";
|
||||
import { Fetcher, makeSimpleProxyFetcher } from "@movie-web/providers";
|
||||
|
||||
import { sendExtensionRequest } from "@/backend/extension/messaging";
|
||||
import { getApiToken, setApiToken } from "@/backend/helpers/providerApi";
|
||||
import { getProviderApiUrls, getProxyUrls } from "@/utils/proxyUrls";
|
||||
|
||||
import { convertBodyToObject, getBodyTypeFromBody } from "../extension/request";
|
||||
|
||||
function makeLoadbalancedList(getter: () => string[]) {
|
||||
let listIndex = -1;
|
||||
return () => {
|
||||
@ -48,7 +44,7 @@ async function fetchButWithApiTokens(
|
||||
return response;
|
||||
}
|
||||
|
||||
function makeLoadBalancedSimpleProxyFetcher() {
|
||||
export function makeLoadBalancedSimpleProxyFetcher() {
|
||||
const fetcher: Fetcher = async (a, b) => {
|
||||
const currentFetcher = makeSimpleProxyFetcher(
|
||||
getLoadbalancedProxyUrl(),
|
||||
@ -59,8 +55,34 @@ function makeLoadBalancedSimpleProxyFetcher() {
|
||||
return fetcher;
|
||||
}
|
||||
|
||||
export const providers = makeProviders({
|
||||
fetcher: makeStandardFetcher(fetch),
|
||||
proxiedFetcher: makeLoadBalancedSimpleProxyFetcher(),
|
||||
target: targets.BROWSER,
|
||||
}) as any as ProviderControls;
|
||||
function makeFinalHeaders(
|
||||
readHeaders: string[],
|
||||
headers: Record<string, string>,
|
||||
): Headers {
|
||||
const lowercasedHeaders = readHeaders.map((v) => v.toLowerCase());
|
||||
return new Headers(
|
||||
Object.entries(headers).filter((entry) =>
|
||||
lowercasedHeaders.includes(entry[0].toLowerCase()),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
export function makeExtensionFetcher() {
|
||||
const fetcher: Fetcher = async (url, ops) => {
|
||||
const result = await sendExtensionRequest<any>({
|
||||
url,
|
||||
...ops,
|
||||
body: convertBodyToObject(ops.body),
|
||||
bodyType: getBodyTypeFromBody(ops.body),
|
||||
});
|
||||
if (!result?.success) throw new Error(`extension error: ${result?.error}`);
|
||||
const res = result.response;
|
||||
return {
|
||||
body: res.body,
|
||||
finalUrl: res.finalUrl,
|
||||
statusCode: res.statusCode,
|
||||
headers: makeFinalHeaders(ops.readHeaders, res.headers),
|
||||
};
|
||||
};
|
||||
return fetcher;
|
||||
}
|
27
src/backend/providers/providers.ts
Normal file
27
src/backend/providers/providers.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import {
|
||||
makeProviders,
|
||||
makeStandardFetcher,
|
||||
targets,
|
||||
} from "@movie-web/providers";
|
||||
|
||||
import { isExtensionActiveCached } from "@/backend/extension/messaging";
|
||||
import {
|
||||
makeExtensionFetcher,
|
||||
makeLoadBalancedSimpleProxyFetcher,
|
||||
} from "@/backend/providers/fetchers";
|
||||
|
||||
export function getProviders() {
|
||||
if (isExtensionActiveCached()) {
|
||||
return makeProviders({
|
||||
fetcher: makeExtensionFetcher(),
|
||||
target: targets.BROWSER_EXTENSION,
|
||||
consistentIpForRequests: true,
|
||||
});
|
||||
}
|
||||
|
||||
return makeProviders({
|
||||
fetcher: makeStandardFetcher(fetch),
|
||||
proxiedFetcher: makeLoadBalancedSimpleProxyFetcher(),
|
||||
target: targets.BROWSER,
|
||||
});
|
||||
}
|
@ -109,7 +109,7 @@ export function LinksDropdown(props: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="relative is-dropdown">
|
||||
<div
|
||||
className="cursor-pointer tabbable rounded-full flex gap-2 text-white items-center py-2 px-3 bg-pill-background bg-opacity-50 hover:bg-pill-backgroundHover transition-[background,transform] duration-100 hover:scale-105"
|
||||
className="cursor-pointer tabbable rounded-full flex gap-2 text-white items-center py-2 px-3 bg-pill-background bg-opacity-50 hover:bg-pill-backgroundHover backdrop-blur-lg transition-[background,transform] duration-100 hover:scale-105"
|
||||
tabIndex={0}
|
||||
onClick={toggleOpen}
|
||||
onKeyUp={(evt) => evt.key === "Enter" && toggleOpen()}
|
||||
|
@ -25,7 +25,7 @@ export function IconPatch(props: IconPatchProps) {
|
||||
return (
|
||||
<div className={props.className || undefined} onClick={props.onClick}>
|
||||
<div
|
||||
className={`flex items-center justify-center rounded-full border-2 border-transparent bg-pill-background bg-opacity-50 transition-[background-color,color,transform,border-color] duration-75 ${transparentClasses} ${clickableClasses} ${activeClasses} ${sizeClasses}`}
|
||||
className={`flex items-center justify-center rounded-full border-2 border-transparent backdrop-blur-lg bg-pill-background bg-opacity-50 transition-[background-color,color,transform,border-color] duration-75 ${transparentClasses} ${clickableClasses} ${activeClasses} ${sizeClasses}`}
|
||||
>
|
||||
<Icon icon={props.icon} />
|
||||
</div>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import classNames from "classnames";
|
||||
|
||||
export function Toggle(props: { onClick: () => void; enabled?: boolean }) {
|
||||
export function Toggle(props: { onClick?: () => void; enabled?: boolean }) {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
|
@ -9,7 +9,7 @@ import { TextInputControl } from "../text-inputs/TextInputControl";
|
||||
export interface SearchBarProps {
|
||||
placeholder?: string;
|
||||
onChange: (value: string, force: boolean) => void;
|
||||
onUnFocus: () => void;
|
||||
onUnFocus: (newSearch?: string) => void;
|
||||
value: string;
|
||||
}
|
||||
|
||||
@ -57,6 +57,20 @@ export const SearchBarInput = forwardRef<HTMLInputElement, SearchBarProps>(
|
||||
className="w-full flex-1 bg-transparent px-4 py-4 pl-12 text-search-text placeholder-search-placeholder focus:outline-none sm:py-4 sm:pr-2"
|
||||
placeholder={props.placeholder}
|
||||
/>
|
||||
|
||||
{props.value.length > 0 && (
|
||||
<div
|
||||
onClick={() => {
|
||||
props.onUnFocus("");
|
||||
if (ref && typeof ref !== "function") {
|
||||
ref.current?.focus();
|
||||
}
|
||||
}}
|
||||
className="cursor-pointer hover:text-white absolute bottom-0 right-2 top-0 flex justify-center my-auto h-10 w-10 items-center hover:bg-search-hoverBackground active:scale-110 text-search-icon rounded-full transition-[transform,background-color] duration-200"
|
||||
>
|
||||
<Icon icon={Icons.X} className="transition-colors duration-200" />
|
||||
</div>
|
||||
)}
|
||||
</Flare.Child>
|
||||
</Flare.Base>
|
||||
);
|
||||
|
@ -16,7 +16,7 @@ export function BrandPill(props: {
|
||||
"flex items-center space-x-2 rounded-full px-4 py-2 text-type-logo",
|
||||
props.backgroundClass ?? "bg-pill-background bg-opacity-50",
|
||||
props.clickable
|
||||
? "transition-[transform,background-color] hover:scale-105 hover:bg-pill-backgroundHover hover:text-type-logo active:scale-95"
|
||||
? "transition-[transform,background-color] hover:scale-105 hover:bg-pill-backgroundHover backdrop-blur-lg hover:text-type-logo active:scale-95"
|
||||
: "",
|
||||
)}
|
||||
>
|
||||
|
25
src/components/layout/Stepper.tsx
Normal file
25
src/components/layout/Stepper.tsx
Normal file
@ -0,0 +1,25 @@
|
||||
export interface StepperProps {
|
||||
current: number;
|
||||
steps: number;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function Stepper(props: StepperProps) {
|
||||
const percentage = (props.current / props.steps) * 100;
|
||||
|
||||
return (
|
||||
<div className={props.className}>
|
||||
<p className="mb-2">
|
||||
{props.current}/{props.steps}
|
||||
</p>
|
||||
<div className="max-w-full h-1 w-32 bg-onboarding-bar rounded-full overflow-hidden">
|
||||
<div
|
||||
className="h-full bg-onboarding-barFilled transition-[width] rounded-full"
|
||||
style={{
|
||||
width: `${percentage.toFixed(0)}%`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
import classNames from "classnames";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
interface ThinContainerProps {
|
||||
@ -16,3 +17,16 @@ export function ThinContainer(props: ThinContainerProps) {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function CenterContainer(props: ThinContainerProps) {
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
"min-h-screen w-full flex justify-center p-8 py-24 items-center",
|
||||
props.classNames,
|
||||
)}
|
||||
>
|
||||
<div className="w-[700px] max-w-full">{props.children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ export function useModal(id: string) {
|
||||
export function ModalCard(props: { children?: ReactNode }) {
|
||||
return (
|
||||
<div className="w-full max-w-[30rem] m-4">
|
||||
<div className="w-full bg-dropdown-background rounded-xl p-8 pointer-events-auto">
|
||||
<div className="w-full bg-modal-background rounded-xl p-8 pointer-events-auto">
|
||||
{props.children}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -134,7 +134,7 @@ export function CaptionsView({ id }: { id: string }) {
|
||||
[selectCaptionById, setCurrentlyDownloading],
|
||||
);
|
||||
|
||||
const content = subtitleList.map((v, i) => {
|
||||
const content = subtitleList.map((v) => {
|
||||
return (
|
||||
<CaptionOption
|
||||
// key must use index to prevent url collisions
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useMemo } from "react";
|
||||
import { useCallback, useMemo } from "react";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
|
||||
import { Button } from "@/components/buttons/Button";
|
||||
@ -27,6 +27,7 @@ function StyleTrans(props: { k: string }) {
|
||||
i18nKey={props.k}
|
||||
components={{
|
||||
bold: <Menu.Highlight />,
|
||||
br: <br />,
|
||||
ios_share: (
|
||||
<Icon icon={Icons.IOS_SHARE} className="inline-block text-xl -mb-1" />
|
||||
),
|
||||
@ -45,13 +46,13 @@ export function DownloadView({ id }: { id: string }) {
|
||||
|
||||
const sourceType = usePlayerStore((s) => s.source?.type);
|
||||
const selectedCaption = usePlayerStore((s) => s.caption?.selected);
|
||||
const subtitleUrl = useMemo(
|
||||
() =>
|
||||
selectedCaption
|
||||
? convertSubtitlesToSrtDataurl(selectedCaption?.srtData)
|
||||
: null,
|
||||
[selectedCaption],
|
||||
);
|
||||
const openSubtitleDownload = useCallback(() => {
|
||||
const dataUrl = selectedCaption
|
||||
? convertSubtitlesToSrtDataurl(selectedCaption?.srtData)
|
||||
: null;
|
||||
if (!dataUrl) return;
|
||||
window.open(dataUrl);
|
||||
}, [selectedCaption]);
|
||||
|
||||
if (!downloadUrl) return null;
|
||||
|
||||
@ -73,10 +74,9 @@ export function DownloadView({ id }: { id: string }) {
|
||||
</Button>
|
||||
<Button
|
||||
className="w-full mt-2"
|
||||
href={subtitleUrl ?? undefined}
|
||||
disabled={!subtitleUrl}
|
||||
onClick={openSubtitleDownload}
|
||||
disabled={!selectedCaption}
|
||||
theme="secondary"
|
||||
download="subtitles.srt"
|
||||
>
|
||||
{t("player.menus.downloads.downloadSubtitle")}
|
||||
</Button>
|
||||
@ -108,8 +108,8 @@ export function DownloadView({ id }: { id: string }) {
|
||||
</Button>
|
||||
<Button
|
||||
className="w-full mt-2"
|
||||
href={subtitleUrl ?? undefined}
|
||||
disabled={!subtitleUrl}
|
||||
onClick={openSubtitleDownload}
|
||||
disabled={!selectedCaption}
|
||||
theme="secondary"
|
||||
download="subtitles.srt"
|
||||
>
|
||||
@ -123,24 +123,6 @@ export function DownloadView({ id }: { id: string }) {
|
||||
);
|
||||
}
|
||||
|
||||
export function CantDownloadView({ id }: { id: string }) {
|
||||
const router = useOverlayRouter(id);
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Menu.BackLink onClick={() => router.navigate("/")}>
|
||||
{t("player.menus.downloads.title")}
|
||||
</Menu.BackLink>
|
||||
<Menu.Section>
|
||||
<Menu.Paragraph>
|
||||
<StyleTrans k="player.menus.downloads.hlsExplanation" />
|
||||
</Menu.Paragraph>
|
||||
</Menu.Section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function AndroidExplanationView({ id }: { id: string }) {
|
||||
const router = useOverlayRouter(id);
|
||||
const { t } = useTranslation();
|
||||
@ -202,11 +184,6 @@ export function DownloadRoutes({ id }: { id: string }) {
|
||||
<DownloadView id={id} />
|
||||
</Menu.CardWithScrollable>
|
||||
</OverlayPage>
|
||||
<OverlayPage id={id} path="/download/unable" width={343} height={440}>
|
||||
<Menu.CardWithScrollable>
|
||||
<CantDownloadView id={id} />
|
||||
</Menu.CardWithScrollable>
|
||||
</OverlayPage>
|
||||
<OverlayPage id={id} path="/download/ios" width={343} height={440}>
|
||||
<Menu.CardWithScrollable>
|
||||
<IOSExplanationView id={id} />
|
||||
|
@ -147,7 +147,7 @@ export function SourceSelectionView({
|
||||
<Menu.BackLink onClick={() => router.navigate("/")}>
|
||||
{t("player.menus.sources.title")}
|
||||
</Menu.BackLink>
|
||||
<Menu.Section>
|
||||
<Menu.Section className="pb-4">
|
||||
{sources.map((v) => (
|
||||
<SelectableLink
|
||||
key={v.id}
|
||||
|
@ -41,6 +41,7 @@ function qualityToHlsLevel(quality: SourceQuality): number | null {
|
||||
);
|
||||
return found ? +found[0] : null;
|
||||
}
|
||||
|
||||
function hlsLevelsToQualities(levels: Level[]): SourceQuality[] {
|
||||
return levels
|
||||
.map((v) => hlsLevelToQuality(v))
|
||||
|
@ -5,6 +5,8 @@ import {
|
||||
} from "@movie-web/providers";
|
||||
import { useAsyncFn } from "react-use";
|
||||
|
||||
import { isExtensionActiveCached } from "@/backend/extension/messaging";
|
||||
import { prepareStream } from "@/backend/extension/streams";
|
||||
import {
|
||||
connectServerSideEvents,
|
||||
makeProviderUrl,
|
||||
@ -13,12 +15,13 @@ import {
|
||||
scrapeSourceOutputToProviderMetric,
|
||||
useReportProviders,
|
||||
} from "@/backend/helpers/report";
|
||||
import { getLoadbalancedProviderApiUrl } from "@/backend/providers/fetchers";
|
||||
import { getProviders } from "@/backend/providers/providers";
|
||||
import { convertProviderCaption } from "@/components/player/utils/captions";
|
||||
import { convertRunoutputToSource } from "@/components/player/utils/convertRunoutputToSource";
|
||||
import { useOverlayRouter } from "@/hooks/useOverlayRouter";
|
||||
import { metaToScrapeMedia } from "@/stores/player/slices/source";
|
||||
import { usePlayerStore } from "@/stores/player/store";
|
||||
import { getLoadbalancedProviderApiUrl, providers } from "@/utils/providers";
|
||||
|
||||
export function useEmbedScraping(
|
||||
routerId: string,
|
||||
@ -39,7 +42,7 @@ export function useEmbedScraping(
|
||||
let result: EmbedOutput | undefined;
|
||||
if (!meta) return;
|
||||
try {
|
||||
if (providerApiUrl) {
|
||||
if (providerApiUrl && !isExtensionActiveCached()) {
|
||||
const baseUrlMaker = makeProviderUrl(providerApiUrl);
|
||||
const conn = await connectServerSideEvents<EmbedOutput>(
|
||||
baseUrlMaker.scrapeEmbed(embedId, url),
|
||||
@ -47,7 +50,7 @@ export function useEmbedScraping(
|
||||
);
|
||||
result = await conn.promise();
|
||||
} else {
|
||||
result = await providers.runEmbedScraper({
|
||||
result = await getProviders().runEmbedScraper({
|
||||
id: embedId,
|
||||
url,
|
||||
});
|
||||
@ -70,6 +73,7 @@ export function useEmbedScraping(
|
||||
report([
|
||||
scrapeSourceOutputToProviderMetric(meta, sourceId, null, "success", null),
|
||||
]);
|
||||
if (isExtensionActiveCached()) await prepareStream(result.stream[0]);
|
||||
setSourceId(sourceId);
|
||||
setCaption(null);
|
||||
setSource(
|
||||
@ -103,7 +107,7 @@ export function useSourceScraping(sourceId: string | null, routerId: string) {
|
||||
|
||||
let result: SourcererOutput | undefined;
|
||||
try {
|
||||
if (providerApiUrl) {
|
||||
if (providerApiUrl && !isExtensionActiveCached()) {
|
||||
const baseUrlMaker = makeProviderUrl(providerApiUrl);
|
||||
const conn = await connectServerSideEvents<SourcererOutput>(
|
||||
baseUrlMaker.scrapeSource(sourceId, scrapeMedia),
|
||||
@ -111,7 +115,7 @@ export function useSourceScraping(sourceId: string | null, routerId: string) {
|
||||
);
|
||||
result = await conn.promise();
|
||||
} else {
|
||||
result = await providers.runSourceScraper({
|
||||
result = await getProviders().runSourceScraper({
|
||||
id: sourceId,
|
||||
media: scrapeMedia,
|
||||
});
|
||||
@ -130,6 +134,7 @@ export function useSourceScraping(sourceId: string | null, routerId: string) {
|
||||
]);
|
||||
|
||||
if (result.stream) {
|
||||
if (isExtensionActiveCached()) await prepareStream(result.stream[0]);
|
||||
setCaption(null);
|
||||
setSource(
|
||||
convertRunoutputToSource({ stream: result.stream[0] }),
|
||||
@ -144,7 +149,7 @@ export function useSourceScraping(sourceId: string | null, routerId: string) {
|
||||
let embedResult: EmbedOutput | undefined;
|
||||
if (!meta) return;
|
||||
try {
|
||||
if (providerApiUrl) {
|
||||
if (providerApiUrl && !isExtensionActiveCached()) {
|
||||
const baseUrlMaker = makeProviderUrl(providerApiUrl);
|
||||
const conn = await connectServerSideEvents<EmbedOutput>(
|
||||
baseUrlMaker.scrapeEmbed(
|
||||
@ -155,7 +160,7 @@ export function useSourceScraping(sourceId: string | null, routerId: string) {
|
||||
);
|
||||
embedResult = await conn.promise();
|
||||
} else {
|
||||
embedResult = await providers.runEmbedScraper({
|
||||
embedResult = await getProviders().runEmbedScraper({
|
||||
id: result.embeds[0].embedId,
|
||||
url: result.embeds[0].url,
|
||||
});
|
||||
@ -186,6 +191,7 @@ export function useSourceScraping(sourceId: string | null, routerId: string) {
|
||||
]);
|
||||
setSourceId(sourceId);
|
||||
setCaption(null);
|
||||
if (isExtensionActiveCached()) await prepareStream(embedResult.stream[0]);
|
||||
setSource(
|
||||
convertRunoutputToSource({ stream: embedResult.stream[0] }),
|
||||
convertProviderCaption(embedResult.stream[0].captions),
|
||||
|
@ -2,7 +2,10 @@ import classNames from "classnames";
|
||||
import { ReactNode } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { StatusCircle } from "@/components/player/internals/StatusCircle";
|
||||
import {
|
||||
StatusCircle,
|
||||
StatusCircleProps,
|
||||
} from "@/components/player/internals/StatusCircle";
|
||||
import { Transition } from "@/components/utils/Transition";
|
||||
|
||||
export interface ScrapeItemProps {
|
||||
@ -23,13 +26,14 @@ const statusTextMap: Partial<Record<ScrapeCardProps["status"], string>> = {
|
||||
pending: "player.scraping.items.pending",
|
||||
};
|
||||
|
||||
const statusMap: Record<ScrapeCardProps["status"], StatusCircle["type"]> = {
|
||||
failure: "error",
|
||||
notfound: "noresult",
|
||||
pending: "loading",
|
||||
success: "success",
|
||||
waiting: "waiting",
|
||||
};
|
||||
const statusMap: Record<ScrapeCardProps["status"], StatusCircleProps["type"]> =
|
||||
{
|
||||
failure: "error",
|
||||
notfound: "noresult",
|
||||
pending: "loading",
|
||||
success: "success",
|
||||
waiting: "waiting",
|
||||
};
|
||||
|
||||
export function ScrapeItem(props: ScrapeItemProps) {
|
||||
const { t } = useTranslation();
|
||||
|
@ -4,23 +4,24 @@ import classNames from "classnames";
|
||||
import { Icon, Icons } from "@/components/Icon";
|
||||
import { Transition } from "@/components/utils/Transition";
|
||||
|
||||
export interface StatusCircle {
|
||||
export interface StatusCircleProps {
|
||||
type: "loading" | "success" | "error" | "noresult" | "waiting";
|
||||
percentage?: number;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export interface StatusCircleLoading extends StatusCircle {
|
||||
export interface StatusCircleLoading extends StatusCircleProps {
|
||||
type: "loading";
|
||||
percentage: number;
|
||||
}
|
||||
|
||||
function statusIsLoading(
|
||||
props: StatusCircle | StatusCircleLoading,
|
||||
props: StatusCircleProps | StatusCircleLoading,
|
||||
): props is StatusCircleLoading {
|
||||
return props.type === "loading";
|
||||
}
|
||||
|
||||
export function StatusCircle(props: StatusCircle | StatusCircleLoading) {
|
||||
export function StatusCircle(props: StatusCircleProps | StatusCircleLoading) {
|
||||
const [spring] = useSpring(
|
||||
() => ({
|
||||
percentage: statusIsLoading(props) ? props.percentage : 0,
|
||||
@ -30,18 +31,21 @@ export function StatusCircle(props: StatusCircle | StatusCircleLoading) {
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames({
|
||||
"p-0.5 border-current border-[3px] rounded-full h-6 w-6 relative transition-colors":
|
||||
true,
|
||||
"text-video-scraping-loading": props.type === "loading",
|
||||
"text-video-scraping-noresult text-opacity-50":
|
||||
props.type === "waiting",
|
||||
"text-video-scraping-error bg-video-scraping-error":
|
||||
props.type === "error",
|
||||
"text-green-500 bg-green-500": props.type === "success",
|
||||
"text-video-scraping-noresult bg-video-scraping-noresult":
|
||||
props.type === "noresult",
|
||||
})}
|
||||
className={classNames(
|
||||
{
|
||||
"p-0.5 border-current border-[3px] rounded-full h-6 w-6 relative transition-colors":
|
||||
true,
|
||||
"text-video-scraping-loading": props.type === "loading",
|
||||
"text-video-scraping-noresult text-opacity-50":
|
||||
props.type === "waiting",
|
||||
"text-video-scraping-error bg-video-scraping-error":
|
||||
props.type === "error",
|
||||
"text-green-500 bg-green-500": props.type === "success",
|
||||
"text-video-scraping-noresult bg-video-scraping-noresult":
|
||||
props.type === "noresult",
|
||||
},
|
||||
props.className,
|
||||
)}
|
||||
>
|
||||
<Transition animation="fade" show={statusIsLoading(props)}>
|
||||
<svg
|
||||
@ -65,13 +69,13 @@ export function StatusCircle(props: StatusCircle | StatusCircleLoading) {
|
||||
</Transition>
|
||||
<Transition animation="fade" show={props.type === "error"}>
|
||||
<Icon
|
||||
className="absolute inset-0 flex items-center justify-center text-white"
|
||||
className="absolute inset-0 flex items-center justify-center text-background-main"
|
||||
icon={Icons.X}
|
||||
/>
|
||||
</Transition>
|
||||
<Transition animation="fade" show={props.type === "success"}>
|
||||
<Icon
|
||||
className="absolute inset-0 flex items-center text-xs justify-center text-white"
|
||||
className="absolute inset-0 flex items-center text-sm justify-center text-background-main"
|
||||
icon={Icons.CHECKMARK}
|
||||
/>
|
||||
</Transition>
|
||||
|
@ -5,6 +5,7 @@ import { playerStatus } from "@/stores/player/slices/source";
|
||||
import { ThumbnailImage } from "@/stores/player/slices/thumbnails";
|
||||
import { usePlayerStore } from "@/stores/player/store";
|
||||
import { LoadableSource, selectQuality } from "@/stores/player/utils/qualities";
|
||||
import { usePreferencesStore } from "@/stores/preferences";
|
||||
import { processCdnLink } from "@/utils/cdn";
|
||||
import { isSafari } from "@/utils/detectFeatures";
|
||||
|
||||
@ -128,6 +129,7 @@ export function ThumbnailScraper() {
|
||||
const resetImages = usePlayerStore((s) => s.thumbnails.resetImages);
|
||||
const meta = usePlayerStore((s) => s.meta);
|
||||
const source = usePlayerStore((s) => s.source);
|
||||
const enableThumbnails = usePreferencesStore((s) => s.enableThumbnails);
|
||||
const workerRef = useRef<ThumnbnailWorker | null>(null);
|
||||
|
||||
// object references dont always trigger changes, so we serialize it to detect *any* change
|
||||
@ -159,8 +161,8 @@ export function ThumbnailScraper() {
|
||||
|
||||
// start worker with the stream
|
||||
useEffect(() => {
|
||||
startRef.current();
|
||||
}, [sourceSeralized]);
|
||||
if (enableThumbnails) startRef.current();
|
||||
}, [sourceSeralized, enableThumbnails]);
|
||||
|
||||
// destroy worker on unmount
|
||||
useEffect(() => {
|
||||
@ -183,8 +185,8 @@ export function ThumbnailScraper() {
|
||||
workerRef.current.destroy();
|
||||
workerRef.current = null;
|
||||
}
|
||||
startRef.current();
|
||||
}, [serializedMeta, sourceSeralized, status]);
|
||||
if (enableThumbnails) startRef.current();
|
||||
}, [serializedMeta, sourceSeralized, status, enableThumbnails]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ export function convertRunoutputToSource(out: {
|
||||
return {
|
||||
type: "hls",
|
||||
url: out.stream.playlist,
|
||||
preferredHeaders: out.stream.preferredHeaders,
|
||||
};
|
||||
}
|
||||
if (out.stream.type === "file") {
|
||||
@ -49,6 +50,7 @@ export function convertRunoutputToSource(out: {
|
||||
return {
|
||||
type: "file",
|
||||
qualities,
|
||||
preferredHeaders: out.stream.preferredHeaders,
|
||||
};
|
||||
}
|
||||
throw new Error("unrecognized type");
|
||||
|
@ -1,3 +1,5 @@
|
||||
import classNames from "classnames";
|
||||
|
||||
import { TextInputControl } from "./TextInputControl";
|
||||
|
||||
export function AuthInputBox(props: {
|
||||
@ -8,9 +10,10 @@ export function AuthInputBox(props: {
|
||||
placeholder?: string;
|
||||
onChange?: (data: string) => void;
|
||||
passwordToggleable?: boolean;
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<div className={classNames("space-y-3", props.className)}>
|
||||
{props.label ? (
|
||||
<p className="font-bold text-white">{props.label}</p>
|
||||
) : null}
|
||||
|
18
src/components/utils/ErrorLine.tsx
Normal file
18
src/components/utils/ErrorLine.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import classNames from "classnames";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
import { Icon, Icons } from "@/components/Icon";
|
||||
|
||||
export function ErrorLine(props: { children?: ReactNode; className?: string }) {
|
||||
return (
|
||||
<p
|
||||
className={classNames(
|
||||
"inline-flex items-center text-type-danger",
|
||||
props.className,
|
||||
)}
|
||||
>
|
||||
<Icon icon={Icons.WARNING} className="text-xl mr-4" />
|
||||
{props.children}
|
||||
</p>
|
||||
);
|
||||
}
|
@ -69,7 +69,7 @@ function Light(props: FlareProps) {
|
||||
},
|
||||
)}
|
||||
style={{
|
||||
backgroundImage: `radial-gradient(circle at center, rgba(var(${cssVar}), 1), rgba(var(${cssVar}), 0) 70%)`,
|
||||
backgroundImage: `radial-gradient(circle at center, rgba(var(${cssVar}) / 1), rgba(var(${cssVar}) / 0) 70%)`,
|
||||
backgroundPosition: `var(--bg-x) var(--bg-y)`,
|
||||
backgroundRepeat: "no-repeat",
|
||||
backgroundSize: `${size.toFixed(0)}px ${size.toFixed(0)}px`,
|
||||
@ -85,7 +85,7 @@ function Light(props: FlareProps) {
|
||||
<div
|
||||
className="absolute inset-0 opacity-10"
|
||||
style={{
|
||||
background: `radial-gradient(circle at center, rgba(var(${cssVar}), 1), rgba(var(${cssVar}), 0) 70%)`,
|
||||
background: `radial-gradient(circle at center, rgba(var(${cssVar}) / 1), rgba(var(${cssVar}) / 0) 70%)`,
|
||||
backgroundPosition: `var(--bg-x) var(--bg-y)`,
|
||||
backgroundRepeat: "no-repeat",
|
||||
backgroundSize: `${size.toFixed(0)}px ${size.toFixed(0)}px`,
|
||||
|
@ -149,8 +149,10 @@ export function useAuth() {
|
||||
bookmarkMediaToInput(tmdbId, item),
|
||||
);
|
||||
|
||||
await importProgress(backendUrl, account, progressInputs);
|
||||
await importBookmarks(backendUrl, account, bookmarkInputs);
|
||||
await Promise.all([
|
||||
importProgress(backendUrl, account, progressInputs),
|
||||
importBookmarks(backendUrl, account, bookmarkInputs),
|
||||
]);
|
||||
},
|
||||
[backendUrl],
|
||||
);
|
||||
@ -174,9 +176,11 @@ export function useAuth() {
|
||||
throw err;
|
||||
}
|
||||
|
||||
const bookmarks = await getBookmarks(backendUrl, account);
|
||||
const progress = await getProgress(backendUrl, account);
|
||||
const settings = await getSettings(backendUrl, account);
|
||||
const [bookmarks, progress, settings] = await Promise.all([
|
||||
getBookmarks(backendUrl, account),
|
||||
getProgress(backendUrl, account),
|
||||
getSettings(backendUrl, account),
|
||||
]);
|
||||
|
||||
syncData(user.user, user.session, progress, bookmarks, settings);
|
||||
},
|
||||
|
@ -5,12 +5,15 @@ import {
|
||||
} from "@movie-web/providers";
|
||||
import { RefObject, useCallback, useEffect, useRef, useState } from "react";
|
||||
|
||||
import { isExtensionActiveCached } from "@/backend/extension/messaging";
|
||||
import { prepareStream } from "@/backend/extension/streams";
|
||||
import {
|
||||
connectServerSideEvents,
|
||||
getCachedMetadata,
|
||||
makeProviderUrl,
|
||||
} from "@/backend/helpers/providerApi";
|
||||
import { getLoadbalancedProviderApiUrl, providers } from "@/utils/providers";
|
||||
import { getLoadbalancedProviderApiUrl } from "@/backend/providers/fetchers";
|
||||
import { getProviders } from "@/backend/providers/providers";
|
||||
|
||||
export interface ScrapingItems {
|
||||
id: string;
|
||||
@ -156,7 +159,7 @@ export function useScrape() {
|
||||
const startScraping = useCallback(
|
||||
async (media: ScrapeMedia) => {
|
||||
const providerApiUrl = getLoadbalancedProviderApiUrl();
|
||||
if (providerApiUrl) {
|
||||
if (providerApiUrl && !isExtensionActiveCached()) {
|
||||
startScrape();
|
||||
const baseUrlMaker = makeProviderUrl(providerApiUrl);
|
||||
const conn = await connectServerSideEvents<RunOutput | "">(
|
||||
@ -168,12 +171,14 @@ export function useScrape() {
|
||||
conn.on("update", updateEvent);
|
||||
conn.on("discoverEmbeds", discoverEmbedsEvent);
|
||||
const sseOutput = await conn.promise();
|
||||
if (sseOutput && isExtensionActiveCached())
|
||||
await prepareStream(sseOutput.stream);
|
||||
|
||||
return getResult(sseOutput === "" ? null : sseOutput);
|
||||
}
|
||||
|
||||
if (!providers) return null;
|
||||
startScrape();
|
||||
const providers = getProviders();
|
||||
const output = await providers.runAll({
|
||||
media,
|
||||
events: {
|
||||
@ -183,6 +188,8 @@ export function useScrape() {
|
||||
discoverEmbeds: discoverEmbedsEvent,
|
||||
},
|
||||
});
|
||||
if (output && isExtensionActiveCached())
|
||||
await prepareStream(output.stream);
|
||||
return getResult(output);
|
||||
},
|
||||
[
|
||||
|
@ -33,8 +33,8 @@ export function useSearchQuery(): [
|
||||
);
|
||||
};
|
||||
|
||||
const onUnFocus = () => {
|
||||
updateParams(search, true);
|
||||
const onUnFocus = (newSearch?: string) => {
|
||||
updateParams(newSearch ?? search, true);
|
||||
};
|
||||
|
||||
return [search, updateParams, onUnFocus];
|
||||
|
@ -49,6 +49,7 @@ export function useSettingsState(
|
||||
icon: string;
|
||||
}
|
||||
| undefined,
|
||||
enableThumbnails: boolean,
|
||||
) {
|
||||
const [proxyUrlsState, setProxyUrls, resetProxyUrls, proxyUrlsChanged] =
|
||||
useDerived(proxyUrls);
|
||||
@ -71,6 +72,12 @@ export function useSettingsState(
|
||||
] = useDerived(deviceName);
|
||||
const [profileState, setProfileState, resetProfile, profileChanged] =
|
||||
useDerived(profile);
|
||||
const [
|
||||
enableThumbnailsState,
|
||||
setEnableThumbnailsState,
|
||||
resetEnableThumbnails,
|
||||
enableThumbnailsChanged,
|
||||
] = useDerived(enableThumbnails);
|
||||
|
||||
function reset() {
|
||||
resetTheme();
|
||||
@ -80,6 +87,7 @@ export function useSettingsState(
|
||||
resetBackendUrl();
|
||||
resetDeviceName();
|
||||
resetProfile();
|
||||
resetEnableThumbnails();
|
||||
}
|
||||
|
||||
const changed =
|
||||
@ -89,7 +97,8 @@ export function useSettingsState(
|
||||
deviceNameChanged ||
|
||||
backendUrlChanged ||
|
||||
proxyUrlsChanged ||
|
||||
profileChanged;
|
||||
profileChanged ||
|
||||
enableThumbnailsChanged;
|
||||
|
||||
return {
|
||||
reset,
|
||||
@ -129,5 +138,10 @@ export function useSettingsState(
|
||||
set: setProfileState,
|
||||
changed: profileChanged,
|
||||
},
|
||||
enableThumbnails: {
|
||||
state: enableThumbnailsState,
|
||||
set: setEnableThumbnailsState,
|
||||
changed: enableThumbnailsChanged,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,6 +1,12 @@
|
||||
import { RunOutput } from "@movie-web/providers";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import { useNavigate, useParams } from "react-router-dom";
|
||||
import {
|
||||
Navigate,
|
||||
useLocation,
|
||||
useNavigate,
|
||||
useParams,
|
||||
} from "react-router-dom";
|
||||
import { useAsync } from "react-use";
|
||||
|
||||
import { usePlayer } from "@/components/player/hooks/usePlayer";
|
||||
import { usePlayerMeta } from "@/components/player/hooks/usePlayerMeta";
|
||||
@ -15,9 +21,10 @@ import { ScrapeErrorPart } from "@/pages/parts/player/ScrapeErrorPart";
|
||||
import { ScrapingPart } from "@/pages/parts/player/ScrapingPart";
|
||||
import { useLastNonPlayerLink } from "@/stores/history";
|
||||
import { PlayerMeta, playerStatus } from "@/stores/player/slices/source";
|
||||
import { needsOnboarding } from "@/utils/onboarding";
|
||||
import { parseTimestamp } from "@/utils/timestamp";
|
||||
|
||||
export function PlayerView() {
|
||||
export function RealPlayerView() {
|
||||
const navigate = useNavigate();
|
||||
const params = useParams<{
|
||||
media: string;
|
||||
@ -109,4 +116,25 @@ export function PlayerView() {
|
||||
);
|
||||
}
|
||||
|
||||
export function PlayerView() {
|
||||
const loc = useLocation();
|
||||
const { loading, error, value } = useAsync(() => {
|
||||
return needsOnboarding();
|
||||
});
|
||||
|
||||
if (error) throw new Error("Failed to detect onboarding");
|
||||
if (loading) return null;
|
||||
if (value)
|
||||
return (
|
||||
<Navigate
|
||||
replace
|
||||
to={{
|
||||
pathname: "/onboarding",
|
||||
search: `redirect=${encodeURIComponent(loc.pathname)}`,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
return <RealPlayerView />;
|
||||
}
|
||||
|
||||
export default PlayerView;
|
||||
|
@ -31,11 +31,12 @@ import { ThemePart } from "@/pages/parts/settings/ThemePart";
|
||||
import { PageTitle } from "@/pages/parts/util/PageTitle";
|
||||
import { AccountWithToken, useAuthStore } from "@/stores/auth";
|
||||
import { useLanguageStore } from "@/stores/language";
|
||||
import { usePreferencesStore } from "@/stores/preferences";
|
||||
import { useSubtitleStore } from "@/stores/subtitles";
|
||||
import { useThemeStore } from "@/stores/theme";
|
||||
|
||||
import { SubPageLayout } from "./layouts/SubPageLayout";
|
||||
import { LocalePart } from "./parts/settings/LocalePart";
|
||||
import { PreferencesPart } from "./parts/settings/PreferencesPart";
|
||||
|
||||
function SettingsLayout(props: { children: React.ReactNode }) {
|
||||
const { isMobile } = useIsMobile();
|
||||
@ -115,6 +116,9 @@ export function SettingsPage() {
|
||||
const backendUrlSetting = useAuthStore((s) => s.backendUrl);
|
||||
const setBackendUrl = useAuthStore((s) => s.setBackendUrl);
|
||||
|
||||
const enableThumbnails = usePreferencesStore((s) => s.enableThumbnails);
|
||||
const setEnableThumbnails = usePreferencesStore((s) => s.setEnableThumbnails);
|
||||
|
||||
const account = useAuthStore((s) => s.account);
|
||||
const updateProfile = useAuthStore((s) => s.setAccountProfile);
|
||||
const updateDeviceName = useAuthStore((s) => s.updateDeviceName);
|
||||
@ -136,6 +140,7 @@ export function SettingsPage() {
|
||||
proxySet,
|
||||
backendUrlSetting,
|
||||
account?.profile,
|
||||
enableThumbnails,
|
||||
);
|
||||
|
||||
const saveChanges = useCallback(async () => {
|
||||
@ -168,6 +173,7 @@ export function SettingsPage() {
|
||||
}
|
||||
}
|
||||
|
||||
setEnableThumbnails(state.enableThumbnails.state);
|
||||
setAppLanguage(state.appLanguage.state);
|
||||
setTheme(state.theme.state);
|
||||
setSubStyling(state.subtitleStyling.state);
|
||||
@ -186,6 +192,7 @@ export function SettingsPage() {
|
||||
state,
|
||||
account,
|
||||
backendUrl,
|
||||
setEnableThumbnails,
|
||||
setAppLanguage,
|
||||
setTheme,
|
||||
setSubStyling,
|
||||
@ -225,10 +232,12 @@ export function SettingsPage() {
|
||||
<RegisterCalloutPart />
|
||||
)}
|
||||
</div>
|
||||
<div id="settings-locale" className="mt-48">
|
||||
<LocalePart
|
||||
<div id="settings-preferences" className="mt-48">
|
||||
<PreferencesPart
|
||||
language={state.appLanguage.state}
|
||||
setLanguage={state.appLanguage.set}
|
||||
enableThumbnails={state.enableThumbnails.state}
|
||||
setEnableThumbnails={state.enableThumbnails.set}
|
||||
/>
|
||||
</div>
|
||||
<div id="settings-appearance" className="mt-48">
|
||||
|
28
src/pages/layouts/MinimalPageLayout.tsx
Normal file
28
src/pages/layouts/MinimalPageLayout.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
import { BrandPill } from "@/components/layout/BrandPill";
|
||||
import { BlurEllipsis } from "@/pages/layouts/SubPageLayout";
|
||||
|
||||
export function MinimalPageLayout(props: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div
|
||||
className="bg-background-main min-h-screen"
|
||||
style={{
|
||||
backgroundImage:
|
||||
"linear-gradient(to bottom, var(--tw-gradient-from), var(--tw-gradient-to) 800px)",
|
||||
}}
|
||||
>
|
||||
<BlurEllipsis />
|
||||
{/* Main page */}
|
||||
<div className="fixed px-7 py-5 left-0 top-0">
|
||||
<Link
|
||||
className="block tabbable rounded-full text-xs ssm:text-base"
|
||||
to="/"
|
||||
>
|
||||
<BrandPill clickable />
|
||||
</Link>
|
||||
</div>
|
||||
<div className="min-h-screen">{props.children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
117
src/pages/onboarding/Onboarding.tsx
Normal file
117
src/pages/onboarding/Onboarding.tsx
Normal file
@ -0,0 +1,117 @@
|
||||
import classNames from "classnames";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
|
||||
import { Button } from "@/components/buttons/Button";
|
||||
import { Stepper } from "@/components/layout/Stepper";
|
||||
import { CenterContainer } from "@/components/layout/ThinContainer";
|
||||
import { Modal, ModalCard, useModal } from "@/components/overlays/Modal";
|
||||
import { Heading1, Heading2, Paragraph } from "@/components/utils/Text";
|
||||
import { MinimalPageLayout } from "@/pages/layouts/MinimalPageLayout";
|
||||
import {
|
||||
useNavigateOnboarding,
|
||||
useRedirectBack,
|
||||
} from "@/pages/onboarding/onboardingHooks";
|
||||
import { Card, CardContent, Link } from "@/pages/onboarding/utils";
|
||||
import { PageTitle } from "@/pages/parts/util/PageTitle";
|
||||
|
||||
function VerticalLine(props: { className?: string }) {
|
||||
return (
|
||||
<div className={classNames("w-full grid justify-center", props.className)}>
|
||||
<div className="w-px h-10 bg-onboarding-divider" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function OnboardingPage() {
|
||||
const navigate = useNavigateOnboarding();
|
||||
const skipModal = useModal("skip");
|
||||
const { completeAndRedirect } = useRedirectBack();
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<MinimalPageLayout>
|
||||
<PageTitle subpage k="global.pages.onboarding" />
|
||||
<Modal id={skipModal.id}>
|
||||
<ModalCard>
|
||||
<Heading1 className="!mt-0 !mb-4 !text-2xl">
|
||||
{t("onboarding.defaultConfirm.title")}
|
||||
</Heading1>
|
||||
<Paragraph className="!mt-1 !mb-12">
|
||||
{t("onboarding.defaultConfirm.description")}
|
||||
</Paragraph>
|
||||
<div className="flex flex-col-reverse gap-3 md:flex-row md:justify-between">
|
||||
<Button theme="secondary" onClick={skipModal.hide}>
|
||||
{t("onboarding.defaultConfirm.cancel")}
|
||||
</Button>
|
||||
<Button theme="purple" onClick={() => completeAndRedirect()}>
|
||||
{t("onboarding.defaultConfirm.confirm")}
|
||||
</Button>
|
||||
</div>
|
||||
</ModalCard>
|
||||
</Modal>
|
||||
<CenterContainer>
|
||||
<Stepper steps={2} current={1} className="mb-12" />
|
||||
<Heading2 className="!mt-0 !text-3xl max-w-[435px]">
|
||||
{t("onboarding.start.title")}
|
||||
</Heading2>
|
||||
<Paragraph className="max-w-[320px]">
|
||||
{t("onboarding.start.explainer")}
|
||||
</Paragraph>
|
||||
|
||||
<div className="w-full flex flex-col md:flex-row gap-3">
|
||||
<Card onClick={() => navigate("/onboarding/extension")}>
|
||||
<CardContent
|
||||
colorClass="!text-onboarding-best"
|
||||
title={t("onboarding.start.options.extension.title")}
|
||||
subtitle={t("onboarding.start.options.extension.quality")}
|
||||
description={t("onboarding.start.options.extension.description")}
|
||||
>
|
||||
<Link>{t("onboarding.start.options.extension.action")}</Link>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<div className="hidden md:grid grid-rows-[1fr,auto,1fr] justify-center gap-4">
|
||||
<VerticalLine className="items-end" />
|
||||
<span className="text-xs uppercase font-bold">or</span>
|
||||
<VerticalLine />
|
||||
</div>
|
||||
<Card onClick={() => navigate("/onboarding/proxy")}>
|
||||
<CardContent
|
||||
colorClass="!text-onboarding-good"
|
||||
title={t("onboarding.start.options.proxy.title")}
|
||||
subtitle={t("onboarding.start.options.proxy.quality")}
|
||||
description={t("onboarding.start.options.proxy.description")}
|
||||
>
|
||||
<Link>{t("onboarding.start.options.proxy.action")}</Link>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<p className="text-center hidden md:block mt-12">
|
||||
<Trans i18nKey="onboarding.start.options.default.text">
|
||||
<br />
|
||||
<a
|
||||
onClick={skipModal.show}
|
||||
type="button"
|
||||
className="text-onboarding-link hover:opacity-75 cursor-pointer"
|
||||
/>
|
||||
</Trans>
|
||||
</p>
|
||||
|
||||
<div className=" max-w-[300px] mx-auto md:hidden mt-12 ">
|
||||
<Button
|
||||
className="!text-type-text !bg-opacity-50"
|
||||
theme="secondary"
|
||||
onClick={skipModal.show}
|
||||
>
|
||||
<span>
|
||||
<Trans i18nKey="onboarding.start.options.default.text">
|
||||
<span />
|
||||
<span />
|
||||
</Trans>
|
||||
</span>
|
||||
</Button>
|
||||
</div>
|
||||
</CenterContainer>
|
||||
</MinimalPageLayout>
|
||||
);
|
||||
}
|
281
src/pages/onboarding/OnboardingExtension.tsx
Normal file
281
src/pages/onboarding/OnboardingExtension.tsx
Normal file
@ -0,0 +1,281 @@
|
||||
import { ReactNode, useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import { useAsyncFn, useInterval } from "react-use";
|
||||
|
||||
import { isAllowedExtensionVersion } from "@/backend/extension/compatibility";
|
||||
import { extensionInfo, sendPage } from "@/backend/extension/messaging";
|
||||
import { Button } from "@/components/buttons/Button";
|
||||
import { Icon, Icons } from "@/components/Icon";
|
||||
import { Loading } from "@/components/layout/Loading";
|
||||
import { Stepper } from "@/components/layout/Stepper";
|
||||
import { CenterContainer } from "@/components/layout/ThinContainer";
|
||||
import { Heading2, Paragraph } from "@/components/utils/Text";
|
||||
import { MinimalPageLayout } from "@/pages/layouts/MinimalPageLayout";
|
||||
import {
|
||||
useNavigateOnboarding,
|
||||
useRedirectBack,
|
||||
} from "@/pages/onboarding/onboardingHooks";
|
||||
import { Card, Link } from "@/pages/onboarding/utils";
|
||||
import { PageTitle } from "@/pages/parts/util/PageTitle";
|
||||
import { conf } from "@/setup/config";
|
||||
import {
|
||||
ExtensionDetectionResult,
|
||||
detectExtensionInstall,
|
||||
} from "@/utils/detectFeatures";
|
||||
|
||||
type ExtensionStatus =
|
||||
| "unknown"
|
||||
| "failed"
|
||||
| "disallowed"
|
||||
| "noperms"
|
||||
| "outdated"
|
||||
| "success";
|
||||
|
||||
async function getExtensionState(): Promise<ExtensionStatus> {
|
||||
const info = await extensionInfo();
|
||||
if (!info) return "unknown"; // cant talk to extension
|
||||
if (!info.success) return "failed"; // extension failed to respond
|
||||
if (!info.allowed) return "disallowed"; // extension is not enabled on this page
|
||||
if (!info.hasPermission) return "noperms"; // extension has no perms to do it's tasks
|
||||
if (!isAllowedExtensionVersion(info.version)) return "outdated"; // extension is too old
|
||||
return "success"; // no problems
|
||||
}
|
||||
|
||||
function RefreshBar() {
|
||||
const { t } = useTranslation();
|
||||
const reload = useCallback(() => {
|
||||
window.location.reload();
|
||||
}, []);
|
||||
return (
|
||||
<Card className="mt-4">
|
||||
<div className="flex items-center space-x-7">
|
||||
<p className="flex-1">{t("onboarding.extension.notDetecting")}</p>
|
||||
<Button theme="secondary" onClick={reload}>
|
||||
{t("onboarding.extension.notDetectingAction")}
|
||||
</Button>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
export function ExtensionStatus(props: {
|
||||
status: ExtensionStatus;
|
||||
loading: boolean;
|
||||
showHelp?: boolean;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [lastKnownStatus, setLastKnownStatus] = useState(props.status);
|
||||
useEffect(() => {
|
||||
if (!props.loading) setLastKnownStatus(props.status);
|
||||
}, [props.status, props.loading]);
|
||||
|
||||
let content: ReactNode = null;
|
||||
if (props.loading || props.status === "unknown")
|
||||
content = (
|
||||
<>
|
||||
<Loading />
|
||||
<p>{t("onboarding.extension.status.loading")}</p>
|
||||
</>
|
||||
);
|
||||
if (props.status === "disallowed" || props.status === "noperms")
|
||||
content = (
|
||||
<>
|
||||
<p>{t("onboarding.extension.status.disallowed")}</p>
|
||||
<Button
|
||||
onClick={() => {
|
||||
sendPage({
|
||||
page: "PermissionGrant",
|
||||
redirectUrl: window.location.href,
|
||||
});
|
||||
}}
|
||||
theme="purple"
|
||||
padding="md:px-12 p-2.5"
|
||||
className="mt-6"
|
||||
>
|
||||
{t("onboarding.extension.status.disallowedAction")}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
else if (props.status === "failed")
|
||||
content = <p>{t("onboarding.extension.status.failed")}</p>;
|
||||
else if (props.status === "outdated")
|
||||
content = <p>{t("onboarding.extension.status.outdated")}</p>;
|
||||
else if (props.status === "success")
|
||||
content = (
|
||||
<p className="flex items-center">
|
||||
<Icon icon={Icons.CHECKMARK} className="text-type-success mr-4" />
|
||||
{t("onboarding.extension.status.success")}
|
||||
</p>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<Card>
|
||||
<div className="flex py-6 flex-col space-y-2 items-center justify-center">
|
||||
{content}
|
||||
</div>
|
||||
</Card>
|
||||
{lastKnownStatus === "unknown" ? <RefreshBar /> : null}
|
||||
{props.showHelp ? (
|
||||
<Card className="mt-4">
|
||||
<div className="flex items-center space-x-7">
|
||||
<Icon icon={Icons.WARNING} className="text-type-danger text-2xl" />
|
||||
<p className="flex-1">
|
||||
<Trans
|
||||
i18nKey="onboarding.extension.extensionHelp"
|
||||
components={{
|
||||
bold: <span className="text-white" />,
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</Card>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
interface ExtensionPageProps {
|
||||
status: ExtensionStatus;
|
||||
loading: boolean;
|
||||
}
|
||||
|
||||
function ChromeExtensionPage(props: ExtensionPageProps) {
|
||||
const { t } = useTranslation();
|
||||
const installLink = conf().ONBOARDING_CHROME_EXTENSION_INSTALL_LINK;
|
||||
return (
|
||||
<>
|
||||
<Heading2 className="!mt-0 !text-3xl max-w-[435px]">
|
||||
{t("onboarding.extension.title")}
|
||||
</Heading2>
|
||||
<Paragraph className="max-w-[320px] mb-4">
|
||||
{t("onboarding.extension.explainer")}
|
||||
</Paragraph>
|
||||
{installLink ? (
|
||||
<Link href={installLink} target="_blank" className="mb-12">
|
||||
{t("onboarding.extension.linkChrome")}
|
||||
</Link>
|
||||
) : null}
|
||||
|
||||
<ExtensionStatus status={props.status} loading={props.loading} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function FirefoxExtensionPage(props: ExtensionPageProps) {
|
||||
const { t } = useTranslation();
|
||||
const installLink = conf().ONBOARDING_FIREFOX_EXTENSION_INSTALL_LINK;
|
||||
return (
|
||||
<>
|
||||
<Heading2 className="!mt-0 !text-3xl max-w-[435px]">
|
||||
{t("onboarding.extension.title")}
|
||||
</Heading2>
|
||||
<Paragraph className="max-w-[320px] mb-4">
|
||||
{t("onboarding.extension.explainer")}
|
||||
</Paragraph>
|
||||
{installLink ? (
|
||||
<Link href={installLink} target="_blank" className="mb-12">
|
||||
{t("onboarding.extension.linkFirefox")}
|
||||
</Link>
|
||||
) : null}
|
||||
|
||||
<ExtensionStatus status={props.status} loading={props.loading} showHelp />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function IosExtensionPage(_props: ExtensionPageProps) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<>
|
||||
<Heading2 className="!mt-0 !text-3xl max-w-[435px]">
|
||||
{t("onboarding.extension.title")}
|
||||
</Heading2>
|
||||
<Paragraph className="max-w-[320px] mb-4">
|
||||
<Trans
|
||||
i18nKey="onboarding.extension.explainerIos"
|
||||
components={{ bold: <span className="text-white font-bold" /> }}
|
||||
/>
|
||||
</Paragraph>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function UnknownExtensionPage(props: ExtensionPageProps) {
|
||||
const { t } = useTranslation();
|
||||
const installChromeLink = conf().ONBOARDING_CHROME_EXTENSION_INSTALL_LINK;
|
||||
const installFirefoxLink = conf().ONBOARDING_FIREFOX_EXTENSION_INSTALL_LINK;
|
||||
return (
|
||||
<>
|
||||
<Heading2 className="!mt-0 !text-3xl max-w-[435px]">
|
||||
{t("onboarding.extension.title")}
|
||||
</Heading2>
|
||||
<Paragraph className="max-w-[320px] mb-4">
|
||||
{t("onboarding.extension.explainer")}
|
||||
</Paragraph>
|
||||
<div className="mb-4">
|
||||
{installChromeLink ? (
|
||||
<Link href={installChromeLink} target="_blank">
|
||||
{t("onboarding.extension.linkChrome")}
|
||||
</Link>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="mb-12">
|
||||
{installFirefoxLink ? (
|
||||
<Link href={installFirefoxLink} target="_blank">
|
||||
{t("onboarding.extension.linkFirefox")}
|
||||
</Link>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<ExtensionStatus status={props.status} loading={props.loading} showHelp />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function OnboardingExtensionPage() {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigateOnboarding();
|
||||
const { completeAndRedirect } = useRedirectBack();
|
||||
const extensionSupport = useMemo(() => detectExtensionInstall(), []);
|
||||
|
||||
const [{ loading, value }, exec] = useAsyncFn(
|
||||
async (triggeredManually: boolean = false) => {
|
||||
const status = await getExtensionState();
|
||||
if (status === "success" && triggeredManually) completeAndRedirect();
|
||||
return status;
|
||||
},
|
||||
[completeAndRedirect],
|
||||
);
|
||||
useInterval(exec, 1000);
|
||||
|
||||
const componentMap: Record<
|
||||
ExtensionDetectionResult,
|
||||
typeof UnknownExtensionPage
|
||||
> = {
|
||||
chrome: ChromeExtensionPage,
|
||||
firefox: FirefoxExtensionPage,
|
||||
ios: IosExtensionPage,
|
||||
unknown: UnknownExtensionPage,
|
||||
};
|
||||
const PageContent = componentMap[extensionSupport];
|
||||
|
||||
return (
|
||||
<MinimalPageLayout>
|
||||
<PageTitle subpage k="global.pages.onboarding" />
|
||||
<CenterContainer>
|
||||
<Stepper steps={2} current={2} className="mb-12" />
|
||||
<PageContent loading={loading} status={value ?? "unknown"} />
|
||||
<div className="flex justify-between items-center mt-8">
|
||||
<Button onClick={() => navigate("/onboarding")} theme="secondary">
|
||||
{t("onboarding.extension.back")}
|
||||
</Button>
|
||||
{value === "success" ? (
|
||||
<Button onClick={() => exec(true)} theme="purple">
|
||||
{t("onboarding.extension.submit")}
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
</CenterContainer>
|
||||
</MinimalPageLayout>
|
||||
);
|
||||
}
|
96
src/pages/onboarding/OnboardingProxy.tsx
Normal file
96
src/pages/onboarding/OnboardingProxy.tsx
Normal file
@ -0,0 +1,96 @@
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useAsyncFn } from "react-use";
|
||||
|
||||
import { updateSettings } from "@/backend/accounts/settings";
|
||||
import { singularProxiedFetch } from "@/backend/helpers/fetch";
|
||||
import { Button } from "@/components/buttons/Button";
|
||||
import { Stepper } from "@/components/layout/Stepper";
|
||||
import { CenterContainer } from "@/components/layout/ThinContainer";
|
||||
import { AuthInputBox } from "@/components/text-inputs/AuthInputBox";
|
||||
import { Divider } from "@/components/utils/Divider";
|
||||
import { ErrorLine } from "@/components/utils/ErrorLine";
|
||||
import { Heading2, Paragraph } from "@/components/utils/Text";
|
||||
import { useBackendUrl } from "@/hooks/auth/useBackendUrl";
|
||||
import { MinimalPageLayout } from "@/pages/layouts/MinimalPageLayout";
|
||||
import {
|
||||
useNavigateOnboarding,
|
||||
useRedirectBack,
|
||||
} from "@/pages/onboarding/onboardingHooks";
|
||||
import { Link } from "@/pages/onboarding/utils";
|
||||
import { PageTitle } from "@/pages/parts/util/PageTitle";
|
||||
import { conf } from "@/setup/config";
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
|
||||
const testUrl = "https://postman-echo.com/get";
|
||||
|
||||
export function OnboardingProxyPage() {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigateOnboarding();
|
||||
const { completeAndRedirect } = useRedirectBack();
|
||||
const [url, setUrl] = useState("");
|
||||
const setProxySet = useAuthStore((s) => s.setProxySet);
|
||||
const installLink = conf().ONBOARDING_PROXY_INSTALL_LINK;
|
||||
const backendUrl = useBackendUrl();
|
||||
const account = useAuthStore((s) => s.account);
|
||||
|
||||
const [{ loading, error }, test] = useAsyncFn(async () => {
|
||||
if (!url.startsWith("http"))
|
||||
throw new Error("onboarding.proxy.input.errorInvalidUrl");
|
||||
try {
|
||||
const res = await singularProxiedFetch(url, testUrl, {});
|
||||
if (res.url !== testUrl)
|
||||
throw new Error("onboarding.proxy.input.errorNotProxy");
|
||||
setProxySet([url]);
|
||||
|
||||
if (account) {
|
||||
await updateSettings(backendUrl, account, {
|
||||
proxyUrls: [url],
|
||||
});
|
||||
}
|
||||
|
||||
completeAndRedirect();
|
||||
} catch (e) {
|
||||
throw new Error("onboarding.proxy.input.errorConnection");
|
||||
}
|
||||
}, [url, completeAndRedirect, setProxySet]);
|
||||
|
||||
return (
|
||||
<MinimalPageLayout>
|
||||
<PageTitle subpage k="global.pages.onboarding" />
|
||||
<CenterContainer>
|
||||
<Stepper steps={2} current={2} className="mb-12" />
|
||||
<Heading2 className="!mt-0 !text-3xl max-w-[435px]">
|
||||
{t("onboarding.proxy.title")}
|
||||
</Heading2>
|
||||
<Paragraph className="max-w-[320px] !mb-5">
|
||||
{t("onboarding.proxy.explainer")}
|
||||
</Paragraph>
|
||||
{installLink ? (
|
||||
<Link href={installLink} target="_blank" className="mb-12">
|
||||
{t("onboarding.proxy.link")}
|
||||
</Link>
|
||||
) : null}
|
||||
<div className="w-[400px] max-w-full mt-14 mb-28">
|
||||
<AuthInputBox
|
||||
label={t("onboarding.proxy.input.label")}
|
||||
value={url}
|
||||
onChange={setUrl}
|
||||
placeholder={t("onboarding.proxy.input.placeholder")}
|
||||
className="mb-4"
|
||||
/>
|
||||
{error ? <ErrorLine>{t(error.message)}</ErrorLine> : null}
|
||||
</div>
|
||||
<Divider />
|
||||
<div className="flex justify-between">
|
||||
<Button theme="secondary" onClick={() => navigate("/onboarding")}>
|
||||
{t("onboarding.proxy.back")}
|
||||
</Button>
|
||||
<Button theme="purple" loading={loading} onClick={test}>
|
||||
{t("onboarding.proxy.submit")}
|
||||
</Button>
|
||||
</div>
|
||||
</CenterContainer>
|
||||
</MinimalPageLayout>
|
||||
);
|
||||
}
|
37
src/pages/onboarding/onboardingHooks.ts
Normal file
37
src/pages/onboarding/onboardingHooks.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { useCallback } from "react";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
|
||||
import { useQueryParam } from "@/hooks/useQueryParams";
|
||||
import { useOnboardingStore } from "@/stores/onboarding";
|
||||
|
||||
export function useRedirectBack() {
|
||||
const [url] = useQueryParam("redirect");
|
||||
const navigate = useNavigate();
|
||||
const setCompleted = useOnboardingStore((s) => s.setCompleted);
|
||||
|
||||
const redirectBack = useCallback(() => {
|
||||
navigate(url ?? "/");
|
||||
}, [navigate, url]);
|
||||
|
||||
const completeAndRedirect = useCallback(() => {
|
||||
setCompleted(true);
|
||||
redirectBack();
|
||||
}, [redirectBack, setCompleted]);
|
||||
|
||||
return { completeAndRedirect };
|
||||
}
|
||||
|
||||
export function useNavigateOnboarding() {
|
||||
const navigate = useNavigate();
|
||||
const loc = useLocation();
|
||||
const nav = useCallback(
|
||||
(path: string) => {
|
||||
navigate({
|
||||
pathname: path,
|
||||
search: loc.search,
|
||||
});
|
||||
},
|
||||
[navigate, loc],
|
||||
);
|
||||
return nav;
|
||||
}
|
91
src/pages/onboarding/utils.tsx
Normal file
91
src/pages/onboarding/utils.tsx
Normal file
@ -0,0 +1,91 @@
|
||||
import classNames from "classnames";
|
||||
import { ReactNode } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import { Icon, Icons } from "@/components/Icon";
|
||||
import { Heading2, Heading3, Paragraph } from "@/components/utils/Text";
|
||||
|
||||
export function Card(props: {
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
onClick?: () => void;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
{
|
||||
"bg-onboarding-card duration-300 border border-onboarding-border rounded-lg p-7":
|
||||
true,
|
||||
"hover:bg-onboarding-cardHover transition-colors cursor-pointer":
|
||||
!!props.onClick,
|
||||
},
|
||||
props.className,
|
||||
)}
|
||||
onClick={props.onClick}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function CardContent(props: {
|
||||
title: ReactNode;
|
||||
description: ReactNode;
|
||||
subtitle: ReactNode;
|
||||
colorClass: string;
|
||||
children?: React.ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<div className="grid grid-rows-[1fr,auto] h-full">
|
||||
<div>
|
||||
<Icon
|
||||
icon={Icons.RISING_STAR}
|
||||
className={classNames("text-4xl mb-8 block", props.colorClass)}
|
||||
/>
|
||||
<Heading3
|
||||
className={classNames(
|
||||
"!mt-0 !mb-0 !text-xs uppercase",
|
||||
props.colorClass,
|
||||
)}
|
||||
>
|
||||
{props.subtitle}
|
||||
</Heading3>
|
||||
<Heading2 className="!mb-0 !mt-1 !text-base">{props.title}</Heading2>
|
||||
<Paragraph className="max-w-[320px] !my-4">
|
||||
{props.description}
|
||||
</Paragraph>
|
||||
</div>
|
||||
<div>{props.children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function Link(props: {
|
||||
children?: React.ReactNode;
|
||||
to?: string;
|
||||
href?: string;
|
||||
className?: string;
|
||||
target?: "_blank";
|
||||
}) {
|
||||
const navigate = useNavigate();
|
||||
return (
|
||||
<a
|
||||
onClick={() => {
|
||||
if (props.to) navigate(props.to);
|
||||
}}
|
||||
href={props.href}
|
||||
target={props.target}
|
||||
className={classNames(
|
||||
"text-onboarding-link cursor-pointer inline-flex gap-2 items-center group hover:opacity-75 transition-opacity",
|
||||
props.className,
|
||||
)}
|
||||
rel="noreferrer"
|
||||
>
|
||||
{props.children}
|
||||
<Icon
|
||||
icon={Icons.ARROW_RIGHT}
|
||||
className="group-hover:translate-x-0.5 transition-transform text-xl group-active:translate-x-0"
|
||||
/>
|
||||
</a>
|
||||
);
|
||||
}
|
@ -3,6 +3,8 @@ import { useNavigate, useParams } from "react-router-dom";
|
||||
import { useAsync } from "react-use";
|
||||
import type { AsyncReturnType } from "type-fest";
|
||||
|
||||
import { isAllowedExtensionVersion } from "@/backend/extension/compatibility";
|
||||
import { extensionInfo, sendPage } from "@/backend/extension/messaging";
|
||||
import {
|
||||
fetchMetadata,
|
||||
setCachedMetadata,
|
||||
@ -10,6 +12,8 @@ import {
|
||||
import { DetailedMeta, getMetaFromId } from "@/backend/metadata/getmeta";
|
||||
import { decodeTMDBId } from "@/backend/metadata/tmdb";
|
||||
import { MWMediaType } from "@/backend/metadata/types/mw";
|
||||
import { getLoadbalancedProviderApiUrl } from "@/backend/providers/fetchers";
|
||||
import { getProviders } from "@/backend/providers/providers";
|
||||
import { Button } from "@/components/buttons/Button";
|
||||
import { Icons } from "@/components/Icon";
|
||||
import { IconPill } from "@/components/layout/IconPill";
|
||||
@ -18,7 +22,6 @@ import { Paragraph } from "@/components/text/Paragraph";
|
||||
import { Title } from "@/components/text/Title";
|
||||
import { ErrorContainer, ErrorLayout } from "@/pages/layouts/ErrorLayout";
|
||||
import { conf } from "@/setup/config";
|
||||
import { getLoadbalancedProviderApiUrl, providers } from "@/utils/providers";
|
||||
|
||||
export interface MetaPartProps {
|
||||
onGetMeta?: (meta: DetailedMeta, episodeId?: string) => void;
|
||||
@ -41,8 +44,17 @@ export function MetaPart(props: MetaPartProps) {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { error, value, loading } = useAsync(async () => {
|
||||
const info = await extensionInfo();
|
||||
const isValidExtension =
|
||||
info?.success && isAllowedExtensionVersion(info.version) && info.allowed;
|
||||
|
||||
if (isValidExtension) {
|
||||
if (!info.hasPermission) throw new Error("extension-no-permission");
|
||||
}
|
||||
|
||||
// use api metadata or providers metadata
|
||||
const providerApiUrl = getLoadbalancedProviderApiUrl();
|
||||
if (providerApiUrl) {
|
||||
if (providerApiUrl && !isValidExtension) {
|
||||
try {
|
||||
await fetchMetadata(providerApiUrl);
|
||||
} catch (err) {
|
||||
@ -50,11 +62,12 @@ export function MetaPart(props: MetaPartProps) {
|
||||
}
|
||||
} else {
|
||||
setCachedMetadata([
|
||||
...providers.listSources(),
|
||||
...providers.listEmbeds(),
|
||||
...getProviders().listSources(),
|
||||
...getProviders().listEmbeds(),
|
||||
]);
|
||||
}
|
||||
|
||||
// get media meta data
|
||||
let data: ReturnType<typeof decodeTMDBId> = null;
|
||||
try {
|
||||
if (!params.media) throw new Error("no media params");
|
||||
@ -98,16 +111,42 @@ export function MetaPart(props: MetaPartProps) {
|
||||
props.onGetMeta?.(meta, epId);
|
||||
}, []);
|
||||
|
||||
if (error && error.message === "extension-no-permission") {
|
||||
return (
|
||||
<ErrorLayout>
|
||||
<ErrorContainer>
|
||||
<IconPill icon={Icons.WAND}>
|
||||
{t("player.metadata.extensionPermission.badge")}
|
||||
</IconPill>
|
||||
<Title>{t("player.metadata.extensionPermission.title")}</Title>
|
||||
<Paragraph>{t("player.metadata.extensionPermission.text")}</Paragraph>
|
||||
<Button
|
||||
onClick={() => {
|
||||
sendPage({
|
||||
page: "PermissionGrant",
|
||||
redirectUrl: window.location.href,
|
||||
});
|
||||
}}
|
||||
theme="purple"
|
||||
padding="md:px-12 p-2.5"
|
||||
className="mt-6"
|
||||
>
|
||||
{t("player.metadata.extensionPermission.button")}
|
||||
</Button>
|
||||
</ErrorContainer>
|
||||
</ErrorLayout>
|
||||
);
|
||||
}
|
||||
|
||||
if (error && error.message === "dmca") {
|
||||
return (
|
||||
<ErrorLayout>
|
||||
<ErrorContainer>
|
||||
<IconPill icon={Icons.DRAGON}>Removed</IconPill>
|
||||
<Title>Media has been removed</Title>
|
||||
<Paragraph>
|
||||
This media is no longer available due to a takedown notice or
|
||||
copyright claim.
|
||||
</Paragraph>
|
||||
<IconPill icon={Icons.DRAGON}>
|
||||
{t("player.metadata.dmca.badge")}
|
||||
</IconPill>
|
||||
<Title>{t("player.metadata.dmca.title")}</Title>
|
||||
<Paragraph>{t("player.metadata.dmca.text")}</Paragraph>
|
||||
<Button
|
||||
href="/"
|
||||
theme="purple"
|
||||
|
@ -1,13 +1,15 @@
|
||||
import { Dispatch, SetStateAction, useCallback } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
|
||||
import { Button } from "@/components/buttons/Button";
|
||||
import { Toggle } from "@/components/buttons/Toggle";
|
||||
import { Icon, Icons } from "@/components/Icon";
|
||||
import { SettingsCard } from "@/components/layout/SettingsCard";
|
||||
import { MwLink } from "@/components/text/Link";
|
||||
import { AuthInputBox } from "@/components/text-inputs/AuthInputBox";
|
||||
import { Divider } from "@/components/utils/Divider";
|
||||
import { Heading1 } from "@/components/utils/Text";
|
||||
import { SetupPart } from "@/pages/parts/settings/SetupPart";
|
||||
|
||||
interface ProxyEditProps {
|
||||
proxyUrls: string[] | null;
|
||||
@ -52,7 +54,11 @@ function ProxyEdit({ proxyUrls, setProxyUrls }: ProxyEditProps) {
|
||||
{t("settings.connections.workers.label")}
|
||||
</p>
|
||||
<p className="max-w-[20rem] font-medium">
|
||||
{t("settings.connections.workers.description")}
|
||||
<Trans i18nKey="settings.connections.workers.description">
|
||||
<MwLink to="https://docs.movie-web.app/proxy/deploy">
|
||||
Proxy documentation
|
||||
</MwLink>
|
||||
</Trans>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
@ -118,7 +124,11 @@ function BackendEdit({ backendUrl, setBackendUrl }: BackendEditProps) {
|
||||
{t("settings.connections.server.label")}
|
||||
</p>
|
||||
<p className="max-w-[20rem] font-medium">
|
||||
{t("settings.connections.server.description")}
|
||||
<Trans i18nKey="settings.connections.server.description">
|
||||
<MwLink to="https://docs.movie-web.app/backend/deploy">
|
||||
Backend documentation
|
||||
</MwLink>
|
||||
</Trans>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
@ -147,6 +157,7 @@ export function ConnectionsPart(props: BackendEditProps & ProxyEditProps) {
|
||||
<div>
|
||||
<Heading1 border>{t("settings.connections.title")}</Heading1>
|
||||
<div className="space-y-6">
|
||||
<SetupPart />
|
||||
<ProxyEdit
|
||||
proxyUrls={props.proxyUrls}
|
||||
setProxyUrls={props.setProxyUrls}
|
||||
|
@ -1,44 +0,0 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { FlagIcon } from "@/components/FlagIcon";
|
||||
import { Dropdown } from "@/components/form/Dropdown";
|
||||
import { Heading1 } from "@/components/utils/Text";
|
||||
import { appLanguageOptions } from "@/setup/i18n";
|
||||
import { getLocaleInfo, sortLangCodes } from "@/utils/language";
|
||||
|
||||
export function LocalePart(props: {
|
||||
language: string;
|
||||
setLanguage: (l: string) => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const sorted = sortLangCodes(appLanguageOptions.map((item) => item.code));
|
||||
|
||||
const options = appLanguageOptions
|
||||
.sort((a, b) => sorted.indexOf(a.code) - sorted.indexOf(b.code))
|
||||
.map((opt) => ({
|
||||
id: opt.code,
|
||||
name: `${opt.name}${opt.nativeName ? ` — ${opt.nativeName}` : ""}`,
|
||||
leftIcon: <FlagIcon langCode={opt.code} />,
|
||||
}));
|
||||
|
||||
const selected = options.find(
|
||||
(item) => item.id === getLocaleInfo(props.language)?.code,
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Heading1 border>{t("settings.locale.title")}</Heading1>
|
||||
<p className="text-white font-bold mb-3">
|
||||
{t("settings.locale.language")}
|
||||
</p>
|
||||
<p className="max-w-[20rem] font-medium">
|
||||
{t("settings.locale.languageDescription")}
|
||||
</p>
|
||||
<Dropdown
|
||||
options={options}
|
||||
selectedItem={selected || options[0]}
|
||||
setSelectedItem={(opt) => props.setLanguage(opt.id)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
67
src/pages/parts/settings/PreferencesPart.tsx
Normal file
67
src/pages/parts/settings/PreferencesPart.tsx
Normal file
@ -0,0 +1,67 @@
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { Toggle } from "@/components/buttons/Toggle";
|
||||
import { FlagIcon } from "@/components/FlagIcon";
|
||||
import { Dropdown } from "@/components/form/Dropdown";
|
||||
import { Heading1 } from "@/components/utils/Text";
|
||||
import { appLanguageOptions } from "@/setup/i18n";
|
||||
import { getLocaleInfo, sortLangCodes } from "@/utils/language";
|
||||
|
||||
export function PreferencesPart(props: {
|
||||
language: string;
|
||||
setLanguage: (l: string) => void;
|
||||
enableThumbnails: boolean;
|
||||
setEnableThumbnails: (v: boolean) => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const sorted = sortLangCodes(appLanguageOptions.map((item) => item.code));
|
||||
|
||||
const options = appLanguageOptions
|
||||
.sort((a, b) => sorted.indexOf(a.code) - sorted.indexOf(b.code))
|
||||
.map((opt) => ({
|
||||
id: opt.code,
|
||||
name: `${opt.name}${opt.nativeName ? ` — ${opt.nativeName}` : ""}`,
|
||||
leftIcon: <FlagIcon langCode={opt.code} />,
|
||||
}));
|
||||
|
||||
const selected = options.find(
|
||||
(item) => item.id === getLocaleInfo(props.language)?.code,
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="space-y-12">
|
||||
<Heading1 border>{t("settings.preferences.title")}</Heading1>
|
||||
<div>
|
||||
<p className="text-white font-bold mb-3">
|
||||
{t("settings.preferences.language")}
|
||||
</p>
|
||||
<p className="max-w-[20rem] font-medium">
|
||||
{t("settings.preferences.languageDescription")}
|
||||
</p>
|
||||
<Dropdown
|
||||
options={options}
|
||||
selectedItem={selected || options[0]}
|
||||
setSelectedItem={(opt) => props.setLanguage(opt.id)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="text-white font-bold mb-3">
|
||||
{t("settings.preferences.thumbnail")}
|
||||
</p>
|
||||
<p className="max-w-[25rem] font-medium">
|
||||
{t("settings.preferences.thumbnailDescription")}
|
||||
</p>
|
||||
<div
|
||||
onClick={() => props.setEnableThumbnails(!props.enableThumbnails)}
|
||||
className="bg-dropdown-background hover:bg-dropdown-hoverBackground select-none my-4 cursor-pointer space-x-3 flex items-center max-w-[25rem] py-3 px-4 rounded-lg"
|
||||
>
|
||||
<Toggle enabled={props.enableThumbnails} />
|
||||
<p className="flex-1 text-white font-bold">
|
||||
{t("settings.preferences.thumbnailLabel")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
204
src/pages/parts/settings/SetupPart.tsx
Normal file
204
src/pages/parts/settings/SetupPart.tsx
Normal file
@ -0,0 +1,204 @@
|
||||
import classNames from "classnames";
|
||||
import { ReactNode } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useAsync } from "react-use";
|
||||
|
||||
import { isExtensionActive } from "@/backend/extension/messaging";
|
||||
import { singularProxiedFetch } from "@/backend/helpers/fetch";
|
||||
import { Button } from "@/components/buttons/Button";
|
||||
import { Icon, Icons } from "@/components/Icon";
|
||||
import { Loading } from "@/components/layout/Loading";
|
||||
import { SettingsCard } from "@/components/layout/SettingsCard";
|
||||
import {
|
||||
StatusCircle,
|
||||
StatusCircleProps,
|
||||
} from "@/components/player/internals/StatusCircle";
|
||||
import { Heading3 } from "@/components/utils/Text";
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
|
||||
const testUrl = "https://postman-echo.com/get";
|
||||
|
||||
type Status = "success" | "unset" | "error";
|
||||
|
||||
type SetupData = {
|
||||
extension: Status;
|
||||
proxy: Status;
|
||||
defaultProxy: Status;
|
||||
};
|
||||
|
||||
function testProxy(url: string) {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
setTimeout(() => reject(new Error("Timed out!")), 3000);
|
||||
singularProxiedFetch(url, testUrl, {})
|
||||
.then((res) => {
|
||||
if (res.url !== testUrl) return reject(new Error("Not a proxy"));
|
||||
resolve();
|
||||
})
|
||||
.catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
function useIsSetup() {
|
||||
const proxyUrls = useAuthStore((s) => s.proxySet);
|
||||
const { loading, value } = useAsync(async (): Promise<SetupData> => {
|
||||
const extensionStatus: Status = (await isExtensionActive())
|
||||
? "success"
|
||||
: "unset";
|
||||
let proxyStatus: Status = "unset";
|
||||
if (proxyUrls && proxyUrls.length > 0) {
|
||||
try {
|
||||
await testProxy(proxyUrls[0]);
|
||||
proxyStatus = "success";
|
||||
} catch {
|
||||
proxyStatus = "error";
|
||||
}
|
||||
}
|
||||
return {
|
||||
extension: extensionStatus,
|
||||
proxy: proxyStatus,
|
||||
defaultProxy: "success",
|
||||
};
|
||||
}, [proxyUrls]);
|
||||
|
||||
let globalState: Status = "unset";
|
||||
if (value?.extension === "success" || value?.proxy === "success")
|
||||
globalState = "success";
|
||||
if (value?.proxy === "error" || value?.extension === "error")
|
||||
globalState = "error";
|
||||
|
||||
return {
|
||||
setupStates: value,
|
||||
globalState,
|
||||
loading,
|
||||
};
|
||||
}
|
||||
|
||||
function SetupCheckList(props: {
|
||||
status: Status;
|
||||
grey?: boolean;
|
||||
highlight?: boolean;
|
||||
children?: ReactNode;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const statusMap: Record<Status, StatusCircleProps["type"]> = {
|
||||
error: "error",
|
||||
success: "success",
|
||||
unset: "noresult",
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex items-start text-type-dimmed my-4">
|
||||
<StatusCircle
|
||||
type={statusMap[props.status]}
|
||||
className={classNames({
|
||||
"!text-video-scraping-noresult !bg-video-scraping-noresult opacity-50":
|
||||
props.grey,
|
||||
"scale-90 mr-3": true,
|
||||
})}
|
||||
/>
|
||||
<div>
|
||||
<p
|
||||
className={classNames({
|
||||
"!text-white": props.grey && props.highlight,
|
||||
"!text-type-dimmed opacity-75": props.grey && !props.highlight,
|
||||
"text-type-danger": props.status === "error",
|
||||
"text-white": props.status === "success",
|
||||
})}
|
||||
>
|
||||
{props.children}
|
||||
</p>
|
||||
{props.status === "error" ? (
|
||||
<p className="max-w-96">
|
||||
{t("settings.connections.setup.itemError")}
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function SetupPart() {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const { loading, setupStates, globalState } = useIsSetup();
|
||||
if (loading || !setupStates) {
|
||||
return (
|
||||
<SettingsCard>
|
||||
<div className="flex py-6 items-center justify-center">
|
||||
<Loading />
|
||||
</div>
|
||||
</SettingsCard>
|
||||
);
|
||||
}
|
||||
|
||||
const textLookupMap: Record<
|
||||
Status,
|
||||
{ title: string; desc: string; button: string }
|
||||
> = {
|
||||
error: {
|
||||
title: "settings.connections.setup.errorStatus.title",
|
||||
desc: "settings.connections.setup.errorStatus.description",
|
||||
button: "settings.connections.setup.redoSetup",
|
||||
},
|
||||
success: {
|
||||
title: "settings.connections.setup.successStatus.title",
|
||||
desc: "settings.connections.setup.successStatus.description",
|
||||
button: "settings.connections.setup.redoSetup",
|
||||
},
|
||||
unset: {
|
||||
title: "settings.connections.setup.unsetStatus.title",
|
||||
desc: "settings.connections.setup.unsetStatus.description",
|
||||
button: "settings.connections.setup.doSetup",
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<SettingsCard>
|
||||
<div className="flex flex-col md:flex-row items-start gap-4">
|
||||
<div>
|
||||
<div
|
||||
className={classNames({
|
||||
"rounded-full h-12 w-12 flex bg-opacity-15 justify-center items-center":
|
||||
true,
|
||||
"text-type-success bg-type-success": globalState === "success",
|
||||
"text-type-danger bg-type-danger":
|
||||
globalState === "error" || globalState === "unset",
|
||||
})}
|
||||
>
|
||||
<Icon
|
||||
icon={globalState === "success" ? Icons.CHECKMARK : Icons.X}
|
||||
className="text-xl"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<Heading3 className="!mb-3">
|
||||
{t(textLookupMap[globalState].title)}
|
||||
</Heading3>
|
||||
<p className="max-w-[20rem] font-medium mb-6">
|
||||
{t(textLookupMap[globalState].desc)}
|
||||
</p>
|
||||
<SetupCheckList status={setupStates.extension}>
|
||||
{t("settings.connections.setup.items.extension")}
|
||||
</SetupCheckList>
|
||||
<SetupCheckList status={setupStates.proxy}>
|
||||
{t("settings.connections.setup.items.proxy")}
|
||||
</SetupCheckList>
|
||||
<SetupCheckList
|
||||
grey
|
||||
highlight={globalState === "unset"}
|
||||
status={setupStates.defaultProxy}
|
||||
>
|
||||
{t("settings.connections.setup.items.default")}
|
||||
</SetupCheckList>
|
||||
</div>
|
||||
<div className="md:mt-5">
|
||||
<Button theme="purple" onClick={() => navigate("/onboarding")}>
|
||||
{t(textLookupMap[globalState].button)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</SettingsCard>
|
||||
);
|
||||
}
|
@ -44,9 +44,9 @@ export function SidebarPart() {
|
||||
icon: Icons.USER,
|
||||
},
|
||||
{
|
||||
textKey: "settings.locale.title",
|
||||
id: "settings-locale",
|
||||
icon: Icons.BOOKMARK,
|
||||
textKey: "settings.preferences.title",
|
||||
id: "settings-preferences",
|
||||
icon: Icons.SETTINGS,
|
||||
},
|
||||
{
|
||||
textKey: "settings.appearance.title",
|
||||
|
@ -19,6 +19,9 @@ import { DmcaPage, shouldHaveDmcaPage } from "@/pages/Dmca";
|
||||
import { NotFoundPage } from "@/pages/errors/NotFoundPage";
|
||||
import { HomePage } from "@/pages/HomePage";
|
||||
import { LoginPage } from "@/pages/Login";
|
||||
import { OnboardingPage } from "@/pages/onboarding/Onboarding";
|
||||
import { OnboardingExtensionPage } from "@/pages/onboarding/OnboardingExtension";
|
||||
import { OnboardingProxyPage } from "@/pages/onboarding/OnboardingProxy";
|
||||
import { RegisterPage } from "@/pages/Register";
|
||||
import { Layout } from "@/setup/Layout";
|
||||
import { useHistoryListener } from "@/stores/history";
|
||||
@ -119,6 +122,12 @@ function App() {
|
||||
<Route path="/register" element={<RegisterPage />} />
|
||||
<Route path="/login" element={<LoginPage />} />
|
||||
<Route path="/about" element={<AboutPage />} />
|
||||
<Route path="/onboarding" element={<OnboardingPage />} />
|
||||
<Route
|
||||
path="/onboarding/extension"
|
||||
element={<OnboardingExtensionPage />}
|
||||
/>
|
||||
<Route path="/onboarding/proxy" element={<OnboardingProxyPage />} />
|
||||
|
||||
{shouldHaveDmcaPage() ? (
|
||||
<Route path="/dmca" element={<DmcaPage />} />
|
||||
|
@ -19,6 +19,10 @@ interface Config {
|
||||
DISALLOWED_IDS: string;
|
||||
TURNSTILE_KEY: string;
|
||||
CDN_REPLACEMENTS: string;
|
||||
HAS_ONBOARDING: string;
|
||||
ONBOARDING_CHROME_EXTENSION_INSTALL_LINK: string;
|
||||
ONBOARDING_FIREFOX_EXTENSION_INSTALL_LINK: string;
|
||||
ONBOARDING_PROXY_INSTALL_LINK: string;
|
||||
}
|
||||
|
||||
export interface RuntimeConfig {
|
||||
@ -34,6 +38,10 @@ export interface RuntimeConfig {
|
||||
DISALLOWED_IDS: string[];
|
||||
TURNSTILE_KEY: string | null;
|
||||
CDN_REPLACEMENTS: Array<string[]>;
|
||||
HAS_ONBOARDING: boolean;
|
||||
ONBOARDING_CHROME_EXTENSION_INSTALL_LINK: string | null;
|
||||
ONBOARDING_FIREFOX_EXTENSION_INSTALL_LINK: string | null;
|
||||
ONBOARDING_PROXY_INSTALL_LINK: string | null;
|
||||
}
|
||||
|
||||
const env: Record<keyof Config, undefined | string> = {
|
||||
@ -42,6 +50,12 @@ const env: Record<keyof Config, undefined | string> = {
|
||||
GITHUB_LINK: undefined,
|
||||
DONATION_LINK: undefined,
|
||||
DISCORD_LINK: undefined,
|
||||
ONBOARDING_CHROME_EXTENSION_INSTALL_LINK: import.meta.env
|
||||
.VITE_ONBOARDING_CHROME_EXTENSION_INSTALL_LINK,
|
||||
ONBOARDING_FIREFOX_EXTENSION_INSTALL_LINK: import.meta.env
|
||||
.VITE_ONBOARDING_FIREFOX_EXTENSION_INSTALL_LINK,
|
||||
ONBOARDING_PROXY_INSTALL_LINK: import.meta.env
|
||||
.VITE_ONBOARDING_PROXY_INSTALL_LINK,
|
||||
DMCA_EMAIL: import.meta.env.VITE_DMCA_EMAIL,
|
||||
CORS_PROXY_URL: import.meta.env.VITE_CORS_PROXY_URL,
|
||||
NORMAL_ROUTER: import.meta.env.VITE_NORMAL_ROUTER,
|
||||
@ -49,6 +63,7 @@ const env: Record<keyof Config, undefined | string> = {
|
||||
DISALLOWED_IDS: import.meta.env.VITE_DISALLOWED_IDS,
|
||||
TURNSTILE_KEY: import.meta.env.VITE_TURNSTILE_KEY,
|
||||
CDN_REPLACEMENTS: import.meta.env.VITE_CDN_REPLACEMENTS,
|
||||
HAS_ONBOARDING: import.meta.env.VITE_HAS_ONBOARDING,
|
||||
};
|
||||
|
||||
// loads from different locations, in order: environment (VITE_{KEY}), window (public/config.js)
|
||||
@ -69,6 +84,9 @@ function getKey(key: keyof Config, defaultString?: string): string {
|
||||
|
||||
export function conf(): RuntimeConfig {
|
||||
const dmcaEmail = getKey("DMCA_EMAIL");
|
||||
const chromeExtension = getKey("ONBOARDING_CHROME_EXTENSION_INSTALL_LINK");
|
||||
const firefoxExtension = getKey("ONBOARDING_FIREFOX_EXTENSION_INSTALL_LINK");
|
||||
const proxyInstallLink = getKey("ONBOARDING_PROXY_INSTALL_LINK");
|
||||
const turnstileKey = getKey("TURNSTILE_KEY");
|
||||
return {
|
||||
APP_VERSION,
|
||||
@ -76,12 +94,19 @@ export function conf(): RuntimeConfig {
|
||||
DONATION_LINK,
|
||||
DISCORD_LINK,
|
||||
DMCA_EMAIL: dmcaEmail.length > 0 ? dmcaEmail : null,
|
||||
ONBOARDING_CHROME_EXTENSION_INSTALL_LINK:
|
||||
chromeExtension.length > 0 ? chromeExtension : null,
|
||||
ONBOARDING_FIREFOX_EXTENSION_INSTALL_LINK:
|
||||
firefoxExtension.length > 0 ? firefoxExtension : null,
|
||||
ONBOARDING_PROXY_INSTALL_LINK:
|
||||
proxyInstallLink.length > 0 ? proxyInstallLink : null,
|
||||
BACKEND_URL: getKey("BACKEND_URL", BACKEND_URL),
|
||||
TMDB_READ_API_KEY: getKey("TMDB_READ_API_KEY"),
|
||||
PROXY_URLS: getKey("CORS_PROXY_URL")
|
||||
.split(",")
|
||||
.map((v) => v.trim()),
|
||||
NORMAL_ROUTER: getKey("NORMAL_ROUTER", "false") === "true",
|
||||
HAS_ONBOARDING: getKey("HAS_ONBOARDING", "false") === "true",
|
||||
TURNSTILE_KEY: turnstileKey.length > 0 ? turnstileKey : null,
|
||||
DISALLOWED_IDS: getKey("DISALLOWED_IDS", "")
|
||||
.split(",")
|
||||
|
@ -46,7 +46,8 @@ export function useLastNonPlayerLink() {
|
||||
(v) =>
|
||||
!v.path.startsWith("/media") && // cannot be a player link
|
||||
location.pathname !== v.path && // cannot be current link
|
||||
!v.path.startsWith("/s/"), // cannot be a quick search link
|
||||
!v.path.startsWith("/s/") && // cannot be a quick search link
|
||||
!v.path.startsWith("/onboarding"), // cannot be an onboarding link
|
||||
);
|
||||
return route?.path ?? "/";
|
||||
}, [routes, location]);
|
||||
|
22
src/stores/onboarding/index.tsx
Normal file
22
src/stores/onboarding/index.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
import { immer } from "zustand/middleware/immer";
|
||||
|
||||
export interface OnboardingStore {
|
||||
completed: boolean;
|
||||
setCompleted(v: boolean): void;
|
||||
}
|
||||
|
||||
export const useOnboardingStore = create(
|
||||
persist(
|
||||
immer<OnboardingStore>((set) => ({
|
||||
completed: false,
|
||||
setCompleted(v) {
|
||||
set((s) => {
|
||||
s.completed = v;
|
||||
});
|
||||
},
|
||||
})),
|
||||
{ name: "__MW::onboarding" },
|
||||
),
|
||||
);
|
@ -118,6 +118,7 @@ export const createSourceSlice: MakeSlice<SourceSlice> = (set, get) => ({
|
||||
},
|
||||
setSourceId(id) {
|
||||
set((s) => {
|
||||
s.status = playerStatus.PLAYING;
|
||||
s.sourceId = id;
|
||||
});
|
||||
},
|
||||
@ -155,6 +156,8 @@ export const createSourceSlice: MakeSlice<SourceSlice> = (set, get) => ({
|
||||
s.qualities = qualities as SourceQuality[];
|
||||
s.currentQuality = loadableStream.quality;
|
||||
s.captionList = captions;
|
||||
s.interface.error = undefined;
|
||||
s.status = playerStatus.PLAYING;
|
||||
});
|
||||
const store = get();
|
||||
store.redisplaySource(startAt);
|
||||
@ -168,7 +171,10 @@ export const createSourceSlice: MakeSlice<SourceSlice> = (set, get) => ({
|
||||
automaticQuality: qualityPreferences.quality.automaticQuality,
|
||||
lastChosenQuality: quality,
|
||||
});
|
||||
|
||||
set((s) => {
|
||||
s.interface.error = undefined;
|
||||
s.status = playerStatus.PLAYING;
|
||||
});
|
||||
store.display?.load({
|
||||
source: loadableStream.stream,
|
||||
startAt,
|
||||
@ -184,6 +190,8 @@ export const createSourceSlice: MakeSlice<SourceSlice> = (set, get) => ({
|
||||
if (!selectedQuality) return;
|
||||
set((s) => {
|
||||
s.currentQuality = quality;
|
||||
s.status = playerStatus.PLAYING;
|
||||
s.interface.error = undefined;
|
||||
});
|
||||
store.display?.load({
|
||||
source: selectedQuality,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Qualities } from "@movie-web/providers";
|
||||
import { Qualities, Stream } from "@movie-web/providers";
|
||||
|
||||
import { QualityStore } from "@/stores/quality";
|
||||
|
||||
@ -14,16 +14,19 @@ export type SourceFileStream = {
|
||||
export type LoadableSource = {
|
||||
type: StreamType;
|
||||
url: string;
|
||||
preferredHeaders?: Stream["preferredHeaders"];
|
||||
};
|
||||
|
||||
export type SourceSliceSource =
|
||||
| {
|
||||
type: "file";
|
||||
qualities: Partial<Record<SourceQuality, SourceFileStream>>;
|
||||
preferredHeaders?: Stream["preferredHeaders"];
|
||||
}
|
||||
| {
|
||||
type: "hls";
|
||||
url: string;
|
||||
preferredHeaders?: Stream["preferredHeaders"];
|
||||
};
|
||||
|
||||
const qualitySorting: Record<SourceQuality, number> = {
|
||||
|
24
src/stores/preferences/index.tsx
Normal file
24
src/stores/preferences/index.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
import { immer } from "zustand/middleware/immer";
|
||||
|
||||
export interface PreferencesStore {
|
||||
enableThumbnails: boolean;
|
||||
setEnableThumbnails(v: boolean): void;
|
||||
}
|
||||
|
||||
export const usePreferencesStore = create(
|
||||
persist(
|
||||
immer<PreferencesStore>((set) => ({
|
||||
enableThumbnails: false,
|
||||
setEnableThumbnails(v) {
|
||||
set((s) => {
|
||||
s.enableThumbnails = v;
|
||||
});
|
||||
},
|
||||
})),
|
||||
{
|
||||
name: "__MW::preferences",
|
||||
},
|
||||
),
|
||||
);
|
@ -1,3 +1,4 @@
|
||||
import { detect } from "detect-browser";
|
||||
import fscreen from "fscreen";
|
||||
import Hls from "hls.js";
|
||||
|
||||
@ -52,3 +53,27 @@ export function canPlayHlsNatively(video: HTMLVideoElement): boolean {
|
||||
if (Hls.isSupported()) return false; // no need to play natively
|
||||
return !!video.canPlayType("application/vnd.apple.mpegurl");
|
||||
}
|
||||
|
||||
export type ExtensionDetectionResult =
|
||||
| "unknown" // unknown detection or weird browser
|
||||
| "firefox" // firefox extensions
|
||||
| "chrome" // chrome extension (could be chromium, but still works with chrome extensions)
|
||||
| "ios"; // ios, no extensions
|
||||
|
||||
export function detectExtensionInstall(): ExtensionDetectionResult {
|
||||
const res = detect();
|
||||
|
||||
// not a browser or failed to detect
|
||||
if (res?.type !== "browser") return "unknown";
|
||||
|
||||
if (res.name === "ios" || res.name === "ios-webview") return "ios";
|
||||
if (
|
||||
res.name === "chrome" ||
|
||||
res.name === "chromium-webview" ||
|
||||
res.name === "edge-chromium" ||
|
||||
res.name === "opera"
|
||||
)
|
||||
return "chrome";
|
||||
if (res.name === "firefox") return "firefox";
|
||||
return "unknown";
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ const languageOrder = ["en", "hi", "fr", "de", "nl", "pt"];
|
||||
// iso639_1 -> iso3166 Alpha-2
|
||||
const countryPriority: Record<string, string> = {
|
||||
zh: "cn",
|
||||
nv: "us",
|
||||
};
|
||||
|
||||
// list of iso639_1 Alpha-2 codes used as default languages
|
||||
@ -46,6 +47,7 @@ const defaultLanguageCodes: string[] = [
|
||||
"tr-TR",
|
||||
"vi-VN",
|
||||
"zh-CN",
|
||||
"nv-US",
|
||||
];
|
||||
|
||||
export interface LocaleInfo {
|
||||
@ -86,7 +88,7 @@ function populateLanguageCode(language: string): string {
|
||||
* @returns pretty format for language, null if it no info can be found for language
|
||||
*/
|
||||
export function getPrettyLanguageNameFromLocale(locale: string): string | null {
|
||||
const tag = getTag(populateLanguageCode(locale), true);
|
||||
const tag = getTag(locale, true);
|
||||
const lang = tag?.language?.Description?.[0] ?? null;
|
||||
if (!lang) return null;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user