From cd02f6d7a3be25dc2a3eb6ee7d3898148328e90b Mon Sep 17 00:00:00 2001 From: Ashutosh Shinde Date: Sat, 6 Jan 2024 13:40:04 +0530 Subject: [PATCH 001/151] fixed #614 multiple captions of the same language all appeared as selected when selecting only one --- .../player/atoms/settings/CaptionsView.tsx | 23 ++++++++++--------- .../player/display/displayInterface.ts | 1 + src/components/player/hooks/useCaptions.ts | 19 +++++++++++++++ src/components/player/utils/captions.ts | 1 + src/stores/player/slices/source.ts | 2 ++ 5 files changed, 35 insertions(+), 11 deletions(-) diff --git a/src/components/player/atoms/settings/CaptionsView.tsx b/src/components/player/atoms/settings/CaptionsView.tsx index dc9a112f..3d89655d 100644 --- a/src/components/player/atoms/settings/CaptionsView.tsx +++ b/src/components/player/atoms/settings/CaptionsView.tsx @@ -75,6 +75,7 @@ function CustomCaptionOption() { setCaption({ language: "custom", srtData: converted, + id: "custom-caption", }); setCustomSubs(); }); @@ -115,22 +116,22 @@ function useSubtitleList(subs: CaptionListItem[], searchQuery: string) { export function CaptionsView({ id }: { id: string }) { const { t } = useTranslation(); const router = useOverlayRouter(id); - const lang = usePlayerStore((s) => s.caption.selected?.language); + const selectedCaptionId = usePlayerStore((s) => s.caption.selected?.id); const [currentlyDownloading, setCurrentlyDownloading] = useState< string | null >(null); - const { selectLanguage, disable } = useCaptions(); + const { selectCaptionById, disable } = useCaptions(); const captionList = usePlayerStore((s) => s.captionList); const [searchQuery, setSearchQuery] = useState(""); const subtitleList = useSubtitleList(captionList, searchQuery); const [downloadReq, startDownload] = useAsyncFn( - async (language: string) => { - setCurrentlyDownloading(language); - return selectLanguage(language); + async (captionId: string) => { + setCurrentlyDownloading(captionId); + return selectCaptionById(captionId); }, - [selectLanguage, setCurrentlyDownloading], + [selectCaptionById, setCurrentlyDownloading], ); const content = subtitleList.map((v, i) => { @@ -140,14 +141,14 @@ export function CaptionsView({ id }: { id: string }) { // eslint-disable-next-line react/no-array-index-key key={`${i}-${v.url}`} countryCode={v.language} - selected={lang === v.language} - loading={v.language === currentlyDownloading && downloadReq.loading} + selected={v.id === selectedCaptionId} + loading={v.id === currentlyDownloading && downloadReq.loading} error={ - v.language === currentlyDownloading && downloadReq.error + v.id === currentlyDownloading && downloadReq.error ? downloadReq.error.toString() : undefined } - onClick={() => startDownload(v.language)} + onClick={() => startDownload(v.id)} > {v.languageName} @@ -176,7 +177,7 @@ export function CaptionsView({ id }: { id: string }) { - disable()} selected={!lang}> + disable()} selected={!selectedCaptionId}> {t("player.menus.subtitles.offChoice")} diff --git a/src/components/player/display/displayInterface.ts b/src/components/player/display/displayInterface.ts index 604bdeca..8ba8480a 100644 --- a/src/components/player/display/displayInterface.ts +++ b/src/components/player/display/displayInterface.ts @@ -41,6 +41,7 @@ export interface DisplayMeta { } export interface DisplayCaption { + id: string; srtData: string; language: string; url?: string; diff --git a/src/components/player/hooks/useCaptions.ts b/src/components/player/hooks/useCaptions.ts index 9f96c41c..0f79aa51 100644 --- a/src/components/player/hooks/useCaptions.ts +++ b/src/components/player/hooks/useCaptions.ts @@ -14,12 +14,30 @@ export function useCaptions() { const lastSelectedLanguage = useSubtitleStore((s) => s.lastSelectedLanguage); const captionList = usePlayerStore((s) => s.captionList); + const selectCaptionById = useCallback( + async (captionId: string) => { + const caption = captionList.find((v) => v.id === captionId); + if (!caption) return; + const srtData = await downloadCaption(caption); + setCaption({ + id: caption.id, + language: caption.language, + srtData, + url: caption.url, + }); + resetSubtitleSpecificSettings(); + setLanguage(caption.language); + }, + [setLanguage, captionList, setCaption, resetSubtitleSpecificSettings], + ); + const selectLanguage = useCallback( async (language: string) => { const caption = captionList.find((v) => v.language === language); if (!caption) return; const srtData = await downloadCaption(caption); setCaption({ + id: caption.id, language: caption.language, srtData, url: caption.url, @@ -56,5 +74,6 @@ export function useCaptions() { selectLastUsedLanguage, toggleLastUsed, selectLastUsedLanguageIfEnabled, + selectCaptionById, }; } diff --git a/src/components/player/utils/captions.ts b/src/components/player/utils/captions.ts index abccee9f..bc2079db 100644 --- a/src/components/player/utils/captions.ts +++ b/src/components/player/utils/captions.ts @@ -80,6 +80,7 @@ export function convertProviderCaption( captions: RunOutput["stream"]["captions"], ): CaptionListItem[] { return captions.map((v) => ({ + id: v.id, language: v.language, url: v.url, needsProxy: v.hasCorsRestrictions, diff --git a/src/stores/player/slices/source.ts b/src/stores/player/slices/source.ts index 56e84f74..1e26abc2 100644 --- a/src/stores/player/slices/source.ts +++ b/src/stores/player/slices/source.ts @@ -42,12 +42,14 @@ export interface PlayerMeta { } export interface Caption { + id: string; language: string; url?: string; srtData: string; } export interface CaptionListItem { + id: string; language: string; url: string; needsProxy: boolean; From 32dd68c90e0965c0321aa5c8f16446d73703c3ea Mon Sep 17 00:00:00 2001 From: Ashutosh Shinde Date: Sat, 6 Jan 2024 23:18:54 +0530 Subject: [PATCH 002/151] updated CaptionOption key to use caption id instead of index and url in CaptionView --- src/components/player/atoms/settings/CaptionsView.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/player/atoms/settings/CaptionsView.tsx b/src/components/player/atoms/settings/CaptionsView.tsx index 3d89655d..09ab5685 100644 --- a/src/components/player/atoms/settings/CaptionsView.tsx +++ b/src/components/player/atoms/settings/CaptionsView.tsx @@ -138,8 +138,7 @@ export function CaptionsView({ id }: { id: string }) { return ( Date: Sat, 6 Jan 2024 23:19:06 +0530 Subject: [PATCH 003/151] updated selectLanguage callback to call selectCaptionById after searching for correct caption --- src/components/player/hooks/useCaptions.ts | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/components/player/hooks/useCaptions.ts b/src/components/player/hooks/useCaptions.ts index 0f79aa51..424edcad 100644 --- a/src/components/player/hooks/useCaptions.ts +++ b/src/components/player/hooks/useCaptions.ts @@ -35,17 +35,9 @@ export function useCaptions() { async (language: string) => { const caption = captionList.find((v) => v.language === language); if (!caption) return; - const srtData = await downloadCaption(caption); - setCaption({ - id: caption.id, - language: caption.language, - srtData, - url: caption.url, - }); - resetSubtitleSpecificSettings(); - setLanguage(language); + selectCaptionById(caption.id); }, - [setLanguage, captionList, setCaption, resetSubtitleSpecificSettings], + [captionList, selectCaptionById], ); const disable = useCallback(async () => { From d71d082ed12d2606205f55505dd3b80e8d59901b Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 7 Jan 2024 13:05:38 +0000 Subject: [PATCH 004/151] Update deploying.yml --- .github/workflows/deploying.yml | 35 ++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/.github/workflows/deploying.yml b/.github/workflows/deploying.yml index 9c642cf6..ebf9d131 100644 --- a/.github/workflows/deploying.yml +++ b/.github/workflows/deploying.yml @@ -12,16 +12,16 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: pnpm/action-setup@v2 with: version: 8 - name: Install Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 cache: 'pnpm' - name: Install pnpm packages @@ -31,7 +31,7 @@ jobs: run: pnpm run build:pwa - name: Upload production-ready build files - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: pwa path: ./dist @@ -42,16 +42,16 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: pnpm/action-setup@v2 with: version: 8 - name: Install Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 cache: 'pnpm' - name: Install pnpm packages @@ -61,7 +61,7 @@ jobs: run: pnpm run build - name: Upload production-ready build files - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: normal path: ./dist @@ -73,10 +73,10 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Download PWA artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: pwa path: ./dist_pwa @@ -85,7 +85,7 @@ jobs: run: cd dist_pwa && zip -r ../movie-web.pwa.zip . - name: Download normal artifact - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: normal path: ./dist_normal @@ -142,17 +142,17 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup Docker buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Get version id: package-version uses: martinbeentjes/npm-get-version-action@main - name: Log into registry ${{ env.REGISTRY }} - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} @@ -160,7 +160,7 @@ jobs: - name: Extract Docker metadata id: meta - uses: docker/metadata-action@v4 + uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} flavor: | @@ -170,9 +170,12 @@ jobs: - name: Build and push Docker image id: build-and-push - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: push: true + platforms: linux/amd64,linux/arm64,linux/arm context: . labels: ${{ steps.meta.outputs.labels }} tags: ${{ steps.meta.outputs.tags }} + cache-from: type=gha + cache-to: type=gha,mode=max From bb7f19fbae4aeafc72b5fb540b8cc52508537a86 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 7 Jan 2024 13:08:01 +0000 Subject: [PATCH 005/151] Update action and Node versions for linting and testing --- .github/workflows/linting_testing.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/linting_testing.yml b/.github/workflows/linting_testing.yml index 4b2c2caa..497131bc 100644 --- a/.github/workflows/linting_testing.yml +++ b/.github/workflows/linting_testing.yml @@ -14,16 +14,16 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: pnpm/action-setup@v2 with: version: 8 - name: Install Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 cache: 'pnpm' - name: Install pnpm packages @@ -38,16 +38,16 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 - uses: pnpm/action-setup@v2 with: version: 8 - name: Install Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: 18 + node-version: 20 cache: 'pnpm' - name: Install pnpm packages From ff8661a644be3231b4098e54e541b9f0ccb37922 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 7 Jan 2024 13:09:45 +0000 Subject: [PATCH 006/151] Update dockerfile to use Node 20 --- dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dockerfile b/dockerfile index 5dd5465b..cc9b84be 100644 --- a/dockerfile +++ b/dockerfile @@ -1,4 +1,4 @@ -FROM node:16.15-alpine as build +FROM node:20-alpine as build WORKDIR /app ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" From a62c029514277ac4b1f2fd03f6dfc4c430c5c6b7 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 7 Jan 2024 13:10:59 +0000 Subject: [PATCH 007/151] Rename dockerfile to have capital D --- dockerfile => Dockerfile | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename dockerfile => Dockerfile (100%) diff --git a/dockerfile b/Dockerfile similarity index 100% rename from dockerfile rename to Dockerfile From dcac36846805745a5ad9d11e5848b21be1b7e121 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 7 Jan 2024 16:43:22 +0000 Subject: [PATCH 008/151] Use @rollup/wasm-node to allow building on ARM --- package.json | 4 +- pnpm-lock.yaml | 213 ++++++++++--------------------------------------- 2 files changed, 47 insertions(+), 170 deletions(-) diff --git a/package.json b/package.json index 8620c18b..388054df 100644 --- a/package.json +++ b/package.json @@ -70,6 +70,7 @@ "@babel/core": "^7.23.6", "@babel/preset-env": "^7.23.6", "@babel/preset-typescript": "^7.23.3", + "@rollup/wasm-node": "^4.9.4", "@types/chromecast-caf-sender": "^1.0.8", "@types/crypto-js": "^4.2.1", "@types/dompurify": "^3.0.5", @@ -125,7 +126,8 @@ "get-func-name@<2.0.1": ">=2.0.1", "postcss@<8.4.31": ">=8.4.31", "@babel/traverse@<7.23.2": ">=7.23.2", - "crypto-js@<4.2.0": ">=4.2.0" + "crypto-js@<4.2.0": ">=4.2.0", + "rollup": "npm:@rollup/wasm-node" } } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 459ee71c..6d6bb9bd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,6 +9,7 @@ overrides: postcss@<8.4.31: '>=8.4.31' '@babel/traverse@<7.23.2': '>=7.23.2' crypto-js@<4.2.0: '>=4.2.0' + rollup: npm:@rollup/wasm-node dependencies: '@formkit/auto-animate': @@ -139,6 +140,9 @@ devDependencies: '@babel/preset-typescript': specifier: ^7.23.3 version: 7.23.3(@babel/core@7.23.6) + '@rollup/wasm-node': + specifier: ^4.9.4 + version: 4.9.4 '@types/chromecast-caf-sender': specifier: ^1.0.8 version: 1.0.8 @@ -252,7 +256,7 @@ devDependencies: version: 0.5.9(prettier@3.1.1) rollup-plugin-visualizer: specifier: ^5.11.0 - version: 5.11.0(rollup@2.79.1) + version: 5.11.0(@rollup/wasm-node@4.9.4) tailwind-scrollbar: specifier: ^3.0.5 version: 3.0.5(tailwindcss@3.4.0) @@ -2029,163 +2033,68 @@ packages: engines: {node: '>=14.0.0'} dev: false - /@rollup/plugin-babel@5.3.1(@babel/core@7.23.6)(rollup@2.79.1): + /@rollup/plugin-babel@5.3.1(@babel/core@7.23.6)(@rollup/wasm-node@4.9.4): resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==} engines: {node: '>= 10.0.0'} peerDependencies: '@babel/core': ^7.0.0 '@types/babel__core': ^7.1.9 - rollup: ^1.20.0||^2.0.0 + rollup: npm:@rollup/wasm-node peerDependenciesMeta: '@types/babel__core': optional: true dependencies: '@babel/core': 7.23.6 '@babel/helper-module-imports': 7.22.15 - '@rollup/pluginutils': 3.1.0(rollup@2.79.1) - rollup: 2.79.1 + '@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.9.4) + rollup: /@rollup/wasm-node@4.9.4 dev: true - /@rollup/plugin-node-resolve@11.2.1(rollup@2.79.1): + /@rollup/plugin-node-resolve@11.2.1(@rollup/wasm-node@4.9.4): resolution: {integrity: sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==} engines: {node: '>= 10.0.0'} peerDependencies: - rollup: ^1.20.0||^2.0.0 + rollup: npm:@rollup/wasm-node dependencies: - '@rollup/pluginutils': 3.1.0(rollup@2.79.1) + '@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.9.4) '@types/resolve': 1.17.1 builtin-modules: 3.3.0 deepmerge: 4.3.1 is-module: 1.0.0 resolve: 1.22.4 - rollup: 2.79.1 + rollup: /@rollup/wasm-node@4.9.4 dev: true - /@rollup/plugin-replace@2.4.2(rollup@2.79.1): + /@rollup/plugin-replace@2.4.2(@rollup/wasm-node@4.9.4): resolution: {integrity: sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==} peerDependencies: - rollup: ^1.20.0 || ^2.0.0 + rollup: npm:@rollup/wasm-node dependencies: - '@rollup/pluginutils': 3.1.0(rollup@2.79.1) + '@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.9.4) magic-string: 0.25.9 - rollup: 2.79.1 + rollup: /@rollup/wasm-node@4.9.4 dev: true - /@rollup/pluginutils@3.1.0(rollup@2.79.1): + /@rollup/pluginutils@3.1.0(@rollup/wasm-node@4.9.4): resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} engines: {node: '>= 8.0.0'} peerDependencies: - rollup: ^1.20.0||^2.0.0 + rollup: npm:@rollup/wasm-node dependencies: '@types/estree': 0.0.39 estree-walker: 1.0.1 picomatch: 2.3.1 - rollup: 2.79.1 + rollup: /@rollup/wasm-node@4.9.4 dev: true - /@rollup/rollup-android-arm-eabi@4.9.1: - resolution: {integrity: sha512-6vMdBZqtq1dVQ4CWdhFwhKZL6E4L1dV6jUjuBvsavvNJSppzi6dLBbuV+3+IyUREaj9ZFvQefnQm28v4OCXlig==} - cpu: [arm] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-android-arm64@4.9.1: - resolution: {integrity: sha512-Jto9Fl3YQ9OLsTDWtLFPtaIMSL2kwGyGoVCmPC8Gxvym9TCZm4Sie+cVeblPO66YZsYH8MhBKDMGZ2NDxuk/XQ==} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-arm64@4.9.1: - resolution: {integrity: sha512-LtYcLNM+bhsaKAIGwVkh5IOWhaZhjTfNOkGzGqdHvhiCUVuJDalvDxEdSnhFzAn+g23wgsycmZk1vbnaibZwwA==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-darwin-x64@4.9.1: - resolution: {integrity: sha512-KyP/byeXu9V+etKO6Lw3E4tW4QdcnzDG/ake031mg42lob5tN+5qfr+lkcT/SGZaH2PdW4Z1NX9GHEkZ8xV7og==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm-gnueabihf@4.9.1: - resolution: {integrity: sha512-Yqz/Doumf3QTKplwGNrCHe/B2p9xqDghBZSlAY0/hU6ikuDVQuOUIpDP/YcmoT+447tsZTmirmjgG3znvSCR0Q==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-gnu@4.9.1: - resolution: {integrity: sha512-u3XkZVvxcvlAOlQJ3UsD1rFvLWqu4Ef/Ggl40WAVCuogf4S1nJPHh5RTgqYFpCOvuGJ7H5yGHabjFKEZGExk5Q==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-arm64-musl@4.9.1: - resolution: {integrity: sha512-0XSYN/rfWShW+i+qjZ0phc6vZ7UWI8XWNz4E/l+6edFt+FxoEghrJHjX1EY/kcUGCnZzYYRCl31SNdfOi450Aw==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-riscv64-gnu@4.9.1: - resolution: {integrity: sha512-LmYIO65oZVfFt9t6cpYkbC4d5lKHLYv5B4CSHRpnANq0VZUQXGcCPXHzbCXCz4RQnx7jvlYB1ISVNCE/omz5cw==} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-gnu@4.9.1: - resolution: {integrity: sha512-kr8rEPQ6ns/Lmr/hiw8sEVj9aa07gh1/tQF2Y5HrNCCEPiCBGnBUt9tVusrcBBiJfIt1yNaXN6r1CCmpbFEDpg==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-linux-x64-musl@4.9.1: - resolution: {integrity: sha512-t4QSR7gN+OEZLG0MiCgPqMWZGwmeHhsM4AkegJ0Kiy6TnJ9vZ8dEIwHw1LcZKhbHxTY32hp9eVCMdR3/I8MGRw==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-arm64-msvc@4.9.1: - resolution: {integrity: sha512-7XI4ZCBN34cb+BH557FJPmh0kmNz2c25SCQeT9OiFWEgf8+dL6ZwJ8f9RnUIit+j01u07Yvrsuu1rZGxJCc51g==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-ia32-msvc@4.9.1: - resolution: {integrity: sha512-yE5c2j1lSWOH5jp+Q0qNL3Mdhr8WuqCNVjc6BxbVfS5cAS6zRmdiw7ktb8GNpDCEUJphILY6KACoFoRtKoqNQg==} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /@rollup/rollup-win32-x64-msvc@4.9.1: - resolution: {integrity: sha512-PyJsSsafjmIhVgaI1Zdj7m8BB8mMckFah/xbpplObyHfiXzKcI5UOUXRyOdHW7nz4DpMCuzLnF7v5IWHenCwYA==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true + /@rollup/wasm-node@4.9.4: + resolution: {integrity: sha512-K9ZPYMCxP7sBElj5du0En/zpbhXTQxpWI7RlF+8bNpLUozhzg2Pcx2h3cBCzV7xtiUt0dc+pF2Ib3/Sg8R0JMA==} + 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==} @@ -2274,6 +2183,9 @@ packages: resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} dev: true + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + /@types/filesystem@0.0.32: resolution: {integrity: sha512-Yuf4jR5YYMR2DVgwuCiP11s0xuVRyPKmz8vo6HBY3CGdeMj8af93CFZX+T82+VD1+UqHOxTq31lO7MI7lepBtQ==} dependencies: @@ -5142,7 +5054,7 @@ packages: '@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.23.6) '@babel/types': 7.23.6 kleur: 4.1.5 - rollup: 3.29.4 + rollup: /@rollup/wasm-node@4.9.4 unplugin: 1.5.1 transitivePeerDependencies: - supports-color @@ -6064,73 +5976,36 @@ packages: glob: 7.2.3 dev: true - /rollup-plugin-terser@7.0.2(rollup@2.79.1): + /rollup-plugin-terser@7.0.2(@rollup/wasm-node@4.9.4): resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==} deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser peerDependencies: - rollup: ^2.0.0 + rollup: npm:@rollup/wasm-node dependencies: '@babel/code-frame': 7.23.5 jest-worker: 26.6.2 - rollup: 2.79.1 + rollup: /@rollup/wasm-node@4.9.4 serialize-javascript: 4.0.0 terser: 5.19.3 dev: true - /rollup-plugin-visualizer@5.11.0(rollup@2.79.1): + /rollup-plugin-visualizer@5.11.0(@rollup/wasm-node@4.9.4): resolution: {integrity: sha512-exM0Ms2SN3AgTzMeW7y46neZQcyLY7eKwWAop1ZoRTCZwyrIRdMMJ6JjToAJbML77X/9N8ZEpmXG4Z/Clb9k8g==} engines: {node: '>=14'} hasBin: true peerDependencies: - rollup: 2.x || 3.x || 4.x + rollup: npm:@rollup/wasm-node peerDependenciesMeta: rollup: optional: true dependencies: open: 8.4.2 picomatch: 2.3.1 - rollup: 2.79.1 + rollup: /@rollup/wasm-node@4.9.4 source-map: 0.7.4 yargs: 17.7.2 dev: true - /rollup@2.79.1: - resolution: {integrity: sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==} - engines: {node: '>=10.0.0'} - hasBin: true - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /rollup@3.29.4: - resolution: {integrity: sha512-oWzmBZwvYrU0iJHtDmhsm662rC15FRXmcjCk1xD771dFDx5jJ02ufAQQTn0etB2emNk4J9EZg/yWKpsn9BWGRw==} - engines: {node: '>=14.18.0', npm: '>=8.0.0'} - hasBin: true - optionalDependencies: - fsevents: 2.3.3 - dev: false - - /rollup@4.9.1: - resolution: {integrity: sha512-pgPO9DWzLoW/vIhlSoDByCzcpX92bKEorbgXuZrqxByte3JFk2xSW2JEeAcyLc9Ru9pqcNNW+Ob7ntsk2oT/Xw==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.9.1 - '@rollup/rollup-android-arm64': 4.9.1 - '@rollup/rollup-darwin-arm64': 4.9.1 - '@rollup/rollup-darwin-x64': 4.9.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.9.1 - '@rollup/rollup-linux-arm64-gnu': 4.9.1 - '@rollup/rollup-linux-arm64-musl': 4.9.1 - '@rollup/rollup-linux-riscv64-gnu': 4.9.1 - '@rollup/rollup-linux-x64-gnu': 4.9.1 - '@rollup/rollup-linux-x64-musl': 4.9.1 - '@rollup/rollup-win32-arm64-msvc': 4.9.1 - '@rollup/rollup-win32-ia32-msvc': 4.9.1 - '@rollup/rollup-win32-x64-msvc': 4.9.1 - fsevents: 2.3.3 - dev: true - /rrweb-cssom@0.6.0: resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} dev: true @@ -7109,7 +6984,7 @@ packages: '@types/node': 20.10.5 esbuild: 0.19.10 postcss: 8.4.32 - rollup: 4.9.1 + rollup: /@rollup/wasm-node@4.9.4 optionalDependencies: fsevents: 2.3.3 dev: true @@ -7371,9 +7246,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@2.79.1) - '@rollup/plugin-node-resolve': 11.2.1(rollup@2.79.1) - '@rollup/plugin-replace': 2.4.2(rollup@2.79.1) + '@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) '@surma/rollup-plugin-off-main-thread': 2.2.3 ajv: 8.12.0 common-tags: 1.8.2 @@ -7382,8 +7257,8 @@ packages: glob: 7.2.3 lodash: 4.17.21 pretty-bytes: 5.6.0 - rollup: 2.79.1 - rollup-plugin-terser: 7.0.2(rollup@2.79.1) + rollup: /@rollup/wasm-node@4.9.4 + rollup-plugin-terser: 7.0.2(@rollup/wasm-node@4.9.4) source-map: 0.8.0-beta.0 stringify-object: 3.3.0 strip-comments: 2.0.1 From 75a2c31800631958e23c14c434b2fba626a71573 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 7 Jan 2024 16:56:49 +0000 Subject: [PATCH 009/151] Add Docker build to test workflow --- .github/workflows/linting_testing.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/workflows/linting_testing.yml b/.github/workflows/linting_testing.yml index 497131bc..6f41126f 100644 --- a/.github/workflows/linting_testing.yml +++ b/.github/workflows/linting_testing.yml @@ -55,3 +55,21 @@ jobs: - name: Build Project run: pnpm run build + + docker: + name: Build Docker + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Docker buildx + uses: docker/setup-buildx-action@v3 + + - name: Build Docker image + uses: docker/build-push-action@v5 + with: + push: false + platforms: linux/amd64,linux/arm64,linux/arm + context: . From 93d8f7263ee2d613ea5fd511568d57b59a577106 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sun, 7 Jan 2024 17:05:59 +0000 Subject: [PATCH 010/151] Remove ARM 32-bit from testing --- .github/workflows/linting_testing.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/linting_testing.yml b/.github/workflows/linting_testing.yml index 6f41126f..c782bcb1 100644 --- a/.github/workflows/linting_testing.yml +++ b/.github/workflows/linting_testing.yml @@ -71,5 +71,5 @@ jobs: uses: docker/build-push-action@v5 with: push: false - platforms: linux/amd64,linux/arm64,linux/arm + platforms: linux/amd64,linux/arm64 context: . From ef85c217f7a6288321eb8c785c8bb33f23b582df Mon Sep 17 00:00:00 2001 From: Jorrin Date: Mon, 8 Jan 2024 17:06:27 +0100 Subject: [PATCH 011/151] first mvp extension --- package.json | 1 + pnpm-lock.yaml | 21 +++ src/@types/plasmo.d.ts | 37 ++++++ src/components/player/display/base.ts | 120 ++++++++++-------- .../player/utils/convertRunoutputToSource.ts | 2 + src/stores/player/utils/qualities.ts | 5 +- src/utils/providers.ts | 4 +- 7 files changed, 134 insertions(+), 56 deletions(-) create mode 100644 src/@types/plasmo.d.ts diff --git a/package.json b/package.json index 388054df..3148f860 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@ladjs/country-language": "^1.0.3", "@movie-web/providers": "^2.0.5", "@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", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6d6bb9bd..5c1d1c9e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -27,6 +27,9 @@ dependencies: '@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) @@ -1980,6 +1983,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: @@ -5156,6 +5171,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} diff --git a/src/@types/plasmo.d.ts b/src/@types/plasmo.d.ts new file mode 100644 index 00000000..4570cae4 --- /dev/null +++ b/src/@types/plasmo.d.ts @@ -0,0 +1,37 @@ +/* eslint-disable @typescript-eslint/ban-types */ +import "@plasmohq/messaging"; + +export interface PlasmoRequestBody { + ruleId: number; + domain: string; + requestHeaders?: Record; + responseHeaders?: Record; +} + +export type PlasmoResponseBody = + | { + success: true; + ruleId: number; + } + | { + success: false; + error: string; + }; + +interface MmMetadata { + "declarative-net-request": { + req: PlasmoRequestBody; + res: PlasmoResponseBody; + }; + "proxy-request": { + req: PlasmoRequestBody; + res: PlasmoResponseBody; + }; +} + +interface MpMetadata {} + +declare module "@plasmohq/messaging" { + interface MessagesMetadata extends MmMetadata {} + interface PortsMetadata extends MpMetadata {} +} diff --git a/src/components/player/display/base.ts b/src/components/player/display/base.ts index 7a9ce041..11a0799c 100644 --- a/src/components/player/display/base.ts +++ b/src/components/player/display/base.ts @@ -1,6 +1,8 @@ +import { sendToBackgroundViaRelay } from "@plasmohq/messaging"; import fscreen from "fscreen"; import Hls, { Level } from "hls.js"; +import { PlasmoRequestBody, PlasmoResponseBody } from "@/@types/plasmo"; import { DisplayInterface, DisplayInterfaceEvents, @@ -100,65 +102,75 @@ export function makeVideoElementDisplayInterface(): DisplayInterface { } function setupSource(vid: HTMLVideoElement, src: LoadableSource) { - if (src.type === "hls") { - if (canPlayHlsNatively(vid)) { - vid.src = processCdnLink(src.url); + // TODO: Add check whether the extension is installed + sendToBackgroundViaRelay({ + name: "declarative-net-request", + body: { + ruleId: 1, + domain: src.type === "hls" ? new URL(src.url).hostname : src.url, + requestHeaders: src.preferredHeaders, + }, + }).then(() => { + if (src.type === "hls") { + if (canPlayHlsNatively(vid)) { + vid.src = processCdnLink(src.url); + vid.currentTime = startAt; + return; + } + + if (!Hls.isSupported()) throw new Error("HLS not supported"); + if (!hls) { + hls = new Hls({ + maxBufferSize: 500 * 1000 * 1000, // 500 mb of buffering, should load more fragments at once + fragLoadPolicy: { + default: { + maxLoadTimeMs: 30 * 1000, // allow it load extra long, fragments are slow if requested for the first time on an origin + maxTimeToFirstByteMs: 30 * 1000, + errorRetry: { + maxNumRetry: 2, + retryDelayMs: 1000, + maxRetryDelayMs: 8000, + }, + timeoutRetry: { + maxNumRetry: 3, + maxRetryDelayMs: 0, + retryDelayMs: 0, + }, + }, + }, + }); + hls.on(Hls.Events.ERROR, (event, data) => { + console.error("HLS error", data); + if (data.fatal) { + emit("error", { + message: data.error.message, + stackTrace: data.error.stack, + errorName: data.error.name, + type: "hls", + }); + } + }); + hls.on(Hls.Events.MANIFEST_LOADED, () => { + if (!hls) return; + reportLevels(); + setupQualityForHls(); + }); + hls.on(Hls.Events.LEVEL_SWITCHED, () => { + if (!hls) return; + const quality = hlsLevelToQuality(hls.levels[hls.currentLevel]); + emit("changedquality", quality); + }); + } + + hls.attachMedia(vid); + hls.loadSource(processCdnLink(src.url)); vid.currentTime = startAt; return; } - if (!Hls.isSupported()) throw new Error("HLS not supported"); - if (!hls) { - hls = new Hls({ - maxBufferSize: 500 * 1000 * 1000, // 500 mb of buffering, should load more fragments at once - fragLoadPolicy: { - default: { - maxLoadTimeMs: 30 * 1000, // allow it load extra long, fragments are slow if requested for the first time on an origin - maxTimeToFirstByteMs: 30 * 1000, - errorRetry: { - maxNumRetry: 2, - retryDelayMs: 1000, - maxRetryDelayMs: 8000, - }, - timeoutRetry: { - maxNumRetry: 3, - maxRetryDelayMs: 0, - retryDelayMs: 0, - }, - }, - }, - }); - hls.on(Hls.Events.ERROR, (event, data) => { - console.error("HLS error", data); - if (data.fatal) { - emit("error", { - message: data.error.message, - stackTrace: data.error.stack, - errorName: data.error.name, - type: "hls", - }); - } - }); - hls.on(Hls.Events.MANIFEST_LOADED, () => { - if (!hls) return; - reportLevels(); - setupQualityForHls(); - }); - hls.on(Hls.Events.LEVEL_SWITCHED, () => { - if (!hls) return; - const quality = hlsLevelToQuality(hls.levels[hls.currentLevel]); - emit("changedquality", quality); - }); - } - - hls.attachMedia(vid); - hls.loadSource(processCdnLink(src.url)); + vid.src = processCdnLink(src.url); vid.currentTime = startAt; - return; - } - - vid.src = processCdnLink(src.url); - vid.currentTime = startAt; + }); } function setSource() { diff --git a/src/components/player/utils/convertRunoutputToSource.ts b/src/components/player/utils/convertRunoutputToSource.ts index fba59e63..f54c5396 100644 --- a/src/components/player/utils/convertRunoutputToSource.ts +++ b/src/components/player/utils/convertRunoutputToSource.ts @@ -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"); diff --git a/src/stores/player/utils/qualities.ts b/src/stores/player/utils/qualities.ts index dbd84b5c..e5140d53 100644 --- a/src/stores/player/utils/qualities.ts +++ b/src/stores/player/utils/qualities.ts @@ -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>; + preferredHeaders?: Stream["preferredHeaders"]; } | { type: "hls"; url: string; + preferredHeaders?: Stream["preferredHeaders"]; }; const qualitySorting: Record = { diff --git a/src/utils/providers.ts b/src/utils/providers.ts index e5c8503c..73c95662 100644 --- a/src/utils/providers.ts +++ b/src/utils/providers.ts @@ -62,5 +62,7 @@ function makeLoadBalancedSimpleProxyFetcher() { export const providers = makeProviders({ fetcher: makeStandardFetcher(fetch), proxiedFetcher: makeLoadBalancedSimpleProxyFetcher(), - target: targets.BROWSER, + // TODO: Add check whether the extension is installed + // target: targets.BROWSER, + target: targets.BROWSER_EXTENSION, }) as any as ProviderControls; From 803668b49289effa63b11ef95e023156e7340f2b Mon Sep 17 00:00:00 2001 From: Ashutosh Shinde Date: Tue, 9 Jan 2024 10:43:20 +0530 Subject: [PATCH 012/151] added return value of selectCaptionById from selectLanguage function --- src/components/player/hooks/useCaptions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/player/hooks/useCaptions.ts b/src/components/player/hooks/useCaptions.ts index 424edcad..458c704a 100644 --- a/src/components/player/hooks/useCaptions.ts +++ b/src/components/player/hooks/useCaptions.ts @@ -35,7 +35,7 @@ export function useCaptions() { async (language: string) => { const caption = captionList.find((v) => v.language === language); if (!caption) return; - selectCaptionById(caption.id); + return selectCaptionById(caption.id); }, [captionList, selectCaptionById], ); From f70d13f2c9e3b91b5b3caccbdf29e9ae77827944 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Tue, 9 Jan 2024 20:07:22 +0100 Subject: [PATCH 013/151] Clean up extension code --- src/backend/extension/messaging.ts | 51 ++++++++ .../extension/plasmo.ts} | 17 ++- src/backend/helpers/fetch.ts | 2 +- .../providers/fetchers.ts} | 25 ++-- src/backend/providers/providers.ts | 26 ++++ src/components/player/display/base.ts | 120 ++++++++---------- .../player/hooks/useSourceSelection.ts | 9 +- src/hooks/useProviderScrape.tsx | 5 +- src/pages/parts/player/MetaPart.tsx | 15 ++- 9 files changed, 172 insertions(+), 98 deletions(-) create mode 100644 src/backend/extension/messaging.ts rename src/{@types/plasmo.d.ts => backend/extension/plasmo.ts} (72%) rename src/{utils/providers.ts => backend/providers/fetchers.ts} (74%) create mode 100644 src/backend/providers/providers.ts diff --git a/src/backend/extension/messaging.ts b/src/backend/extension/messaging.ts new file mode 100644 index 00000000..ec0b4bf6 --- /dev/null +++ b/src/backend/extension/messaging.ts @@ -0,0 +1,51 @@ +import { + MessagesMetadata, + sendToBackgroundViaRelay, +} from "@plasmohq/messaging"; + +let activeExtension = false; + +export interface ExtensionHello { + version: string; +} + +function sendMessage( + message: keyof MessagesMetadata, + payload: any, + timeout: number = -1, +) { + return new Promise((resolve) => { + if (timeout >= 0) setTimeout(() => resolve(null), timeout); + sendToBackgroundViaRelay({ + name: message, + body: payload, + }) + .then((res) => { + activeExtension = true; + resolve(res); + }) + .catch(() => { + activeExtension = false; + resolve(null); + }); + }); +} + +export async function sendExtensionRequest( + url: string, + ops: any, +): Promise { + return sendMessage("proxy-request", { url, ...ops }); +} + +export async function extensionInfo(): Promise { + return sendMessage("hello", null, 300); +} + +export function isExtensionActiveCached(): boolean { + return activeExtension; +} + +export async function isExtensionActive(): Promise { + return !!(await extensionInfo()); +} diff --git a/src/@types/plasmo.d.ts b/src/backend/extension/plasmo.ts similarity index 72% rename from src/@types/plasmo.d.ts rename to src/backend/extension/plasmo.ts index 4570cae4..2e9cacbf 100644 --- a/src/@types/plasmo.d.ts +++ b/src/backend/extension/plasmo.ts @@ -1,6 +1,3 @@ -/* eslint-disable @typescript-eslint/ban-types */ -import "@plasmohq/messaging"; - export interface PlasmoRequestBody { ruleId: number; domain: string; @@ -8,7 +5,11 @@ export interface PlasmoRequestBody { responseHeaders?: Record; } -export type PlasmoResponseBody = +export interface ExtensionHelloReply { + version: string; +} + +export type ExtensionRequestReply = | { success: true; ruleId: number; @@ -21,11 +22,15 @@ export type PlasmoResponseBody = interface MmMetadata { "declarative-net-request": { req: PlasmoRequestBody; - res: PlasmoResponseBody; + res: ExtensionRequestReply; }; "proxy-request": { req: PlasmoRequestBody; - res: PlasmoResponseBody; + res: ExtensionRequestReply; + }; + hello: { + req: null; + res: ExtensionHelloReply; }; } diff --git a/src/backend/helpers/fetch.ts b/src/backend/helpers/fetch.ts index cc3e735e..f9aa145a 100644 --- a/src/backend/helpers/fetch.ts +++ b/src/backend/helpers/fetch.ts @@ -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 = Parameters>; type R = ReturnType>; diff --git a/src/utils/providers.ts b/src/backend/providers/fetchers.ts similarity index 74% rename from src/utils/providers.ts rename to src/backend/providers/fetchers.ts index 73c95662..596e8376 100644 --- a/src/utils/providers.ts +++ b/src/backend/providers/fetchers.ts @@ -1,12 +1,6 @@ -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"; @@ -48,7 +42,7 @@ async function fetchButWithApiTokens( return response; } -function makeLoadBalancedSimpleProxyFetcher() { +export function makeLoadBalancedSimpleProxyFetcher() { const fetcher: Fetcher = async (a, b) => { const currentFetcher = makeSimpleProxyFetcher( getLoadbalancedProxyUrl(), @@ -59,10 +53,9 @@ function makeLoadBalancedSimpleProxyFetcher() { return fetcher; } -export const providers = makeProviders({ - fetcher: makeStandardFetcher(fetch), - proxiedFetcher: makeLoadBalancedSimpleProxyFetcher(), - // TODO: Add check whether the extension is installed - // target: targets.BROWSER, - target: targets.BROWSER_EXTENSION, -}) as any as ProviderControls; +export function makeExtensionFetcher() { + const fetcher: Fetcher = async (a, b) => { + return sendExtensionRequest(a, b) as any; + }; + return fetcher; +} diff --git a/src/backend/providers/providers.ts b/src/backend/providers/providers.ts new file mode 100644 index 00000000..1a7b484a --- /dev/null +++ b/src/backend/providers/providers.ts @@ -0,0 +1,26 @@ +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, + }); + } + + return makeProviders({ + fetcher: makeStandardFetcher(fetch), + proxiedFetcher: makeLoadBalancedSimpleProxyFetcher(), + target: targets.BROWSER, + }); +} diff --git a/src/components/player/display/base.ts b/src/components/player/display/base.ts index 11a0799c..91f36722 100644 --- a/src/components/player/display/base.ts +++ b/src/components/player/display/base.ts @@ -1,8 +1,6 @@ -import { sendToBackgroundViaRelay } from "@plasmohq/messaging"; import fscreen from "fscreen"; import Hls, { Level } from "hls.js"; -import { PlasmoRequestBody, PlasmoResponseBody } from "@/@types/plasmo"; import { DisplayInterface, DisplayInterfaceEvents, @@ -43,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)) @@ -103,74 +102,65 @@ export function makeVideoElementDisplayInterface(): DisplayInterface { function setupSource(vid: HTMLVideoElement, src: LoadableSource) { // TODO: Add check whether the extension is installed - sendToBackgroundViaRelay({ - name: "declarative-net-request", - body: { - ruleId: 1, - domain: src.type === "hls" ? new URL(src.url).hostname : src.url, - requestHeaders: src.preferredHeaders, - }, - }).then(() => { - if (src.type === "hls") { - if (canPlayHlsNatively(vid)) { - vid.src = processCdnLink(src.url); - vid.currentTime = startAt; - return; - } - - if (!Hls.isSupported()) throw new Error("HLS not supported"); - if (!hls) { - hls = new Hls({ - maxBufferSize: 500 * 1000 * 1000, // 500 mb of buffering, should load more fragments at once - fragLoadPolicy: { - default: { - maxLoadTimeMs: 30 * 1000, // allow it load extra long, fragments are slow if requested for the first time on an origin - maxTimeToFirstByteMs: 30 * 1000, - errorRetry: { - maxNumRetry: 2, - retryDelayMs: 1000, - maxRetryDelayMs: 8000, - }, - timeoutRetry: { - maxNumRetry: 3, - maxRetryDelayMs: 0, - retryDelayMs: 0, - }, - }, - }, - }); - hls.on(Hls.Events.ERROR, (event, data) => { - console.error("HLS error", data); - if (data.fatal) { - emit("error", { - message: data.error.message, - stackTrace: data.error.stack, - errorName: data.error.name, - type: "hls", - }); - } - }); - hls.on(Hls.Events.MANIFEST_LOADED, () => { - if (!hls) return; - reportLevels(); - setupQualityForHls(); - }); - hls.on(Hls.Events.LEVEL_SWITCHED, () => { - if (!hls) return; - const quality = hlsLevelToQuality(hls.levels[hls.currentLevel]); - emit("changedquality", quality); - }); - } - - hls.attachMedia(vid); - hls.loadSource(processCdnLink(src.url)); + if (src.type === "hls") { + if (canPlayHlsNatively(vid)) { + vid.src = processCdnLink(src.url); vid.currentTime = startAt; return; } - vid.src = processCdnLink(src.url); + if (!Hls.isSupported()) throw new Error("HLS not supported"); + if (!hls) { + hls = new Hls({ + maxBufferSize: 500 * 1000 * 1000, // 500 mb of buffering, should load more fragments at once + fragLoadPolicy: { + default: { + maxLoadTimeMs: 30 * 1000, // allow it load extra long, fragments are slow if requested for the first time on an origin + maxTimeToFirstByteMs: 30 * 1000, + errorRetry: { + maxNumRetry: 2, + retryDelayMs: 1000, + maxRetryDelayMs: 8000, + }, + timeoutRetry: { + maxNumRetry: 3, + maxRetryDelayMs: 0, + retryDelayMs: 0, + }, + }, + }, + }); + hls.on(Hls.Events.ERROR, (event, data) => { + console.error("HLS error", data); + if (data.fatal) { + emit("error", { + message: data.error.message, + stackTrace: data.error.stack, + errorName: data.error.name, + type: "hls", + }); + } + }); + hls.on(Hls.Events.MANIFEST_LOADED, () => { + if (!hls) return; + reportLevels(); + setupQualityForHls(); + }); + hls.on(Hls.Events.LEVEL_SWITCHED, () => { + if (!hls) return; + const quality = hlsLevelToQuality(hls.levels[hls.currentLevel]); + emit("changedquality", quality); + }); + } + + hls.attachMedia(vid); + hls.loadSource(processCdnLink(src.url)); vid.currentTime = startAt; - }); + return; + } + + vid.src = processCdnLink(src.url); + vid.currentTime = startAt; } function setSource() { diff --git a/src/components/player/hooks/useSourceSelection.ts b/src/components/player/hooks/useSourceSelection.ts index e28507cf..bca884f7 100644 --- a/src/components/player/hooks/useSourceSelection.ts +++ b/src/components/player/hooks/useSourceSelection.ts @@ -13,12 +13,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, @@ -47,7 +48,7 @@ export function useEmbedScraping( ); result = await conn.promise(); } else { - result = await providers.runEmbedScraper({ + result = await getProviders().runEmbedScraper({ id: embedId, url, }); @@ -111,7 +112,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, }); @@ -155,7 +156,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, }); diff --git a/src/hooks/useProviderScrape.tsx b/src/hooks/useProviderScrape.tsx index 43328184..21cb985e 100644 --- a/src/hooks/useProviderScrape.tsx +++ b/src/hooks/useProviderScrape.tsx @@ -10,7 +10,8 @@ import { 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; @@ -172,8 +173,8 @@ export function useScrape() { return getResult(sseOutput === "" ? null : sseOutput); } - if (!providers) return null; startScrape(); + const providers = getProviders(); const output = await providers.runAll({ media, events: { diff --git a/src/pages/parts/player/MetaPart.tsx b/src/pages/parts/player/MetaPart.tsx index 4930fffb..6d5b64ef 100644 --- a/src/pages/parts/player/MetaPart.tsx +++ b/src/pages/parts/player/MetaPart.tsx @@ -3,6 +3,7 @@ import { useNavigate, useParams } from "react-router-dom"; import { useAsync } from "react-use"; import type { AsyncReturnType } from "type-fest"; +import { isExtensionActive } from "@/backend/extension/messaging"; import { fetchMetadata, setCachedMetadata, @@ -10,6 +11,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 +21,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 +43,12 @@ export function MetaPart(props: MetaPartProps) { const navigate = useNavigate(); const { error, value, loading } = useAsync(async () => { + // check extension + const isActive = await isExtensionActive(); + + // use api metadata or providers metadata const providerApiUrl = getLoadbalancedProviderApiUrl(); - if (providerApiUrl) { + if (providerApiUrl && !isActive) { try { await fetchMetadata(providerApiUrl); } catch (err) { @@ -50,11 +56,12 @@ export function MetaPart(props: MetaPartProps) { } } else { setCachedMetadata([ - ...providers.listSources(), - ...providers.listEmbeds(), + ...getProviders().listSources(), + ...getProviders().listEmbeds(), ]); } + // get media meta data let data: ReturnType = null; try { if (!params.media) throw new Error("no media params"); From dc67ef0c3a8867c1555e9d847862ae1703cfdd96 Mon Sep 17 00:00:00 2001 From: Astrid Date: Tue, 9 Jan 2024 20:50:27 +0100 Subject: [PATCH 014/151] remove unused vars --- src/pages/parts/auth/AccountCreatePart.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/parts/auth/AccountCreatePart.tsx b/src/pages/parts/auth/AccountCreatePart.tsx index 674a3be6..6f8b9ad4 100644 --- a/src/pages/parts/auth/AccountCreatePart.tsx +++ b/src/pages/parts/auth/AccountCreatePart.tsx @@ -5,7 +5,6 @@ import { Avatar } from "@/components/Avatar"; import { Button } from "@/components/buttons/Button"; import { ColorPicker, initialColor } from "@/components/form/ColorPicker"; import { IconPicker, initialIcon } from "@/components/form/IconPicker"; -import { Icon, Icons } from "@/components/Icon"; import { LargeCard, LargeCardButtons, From dec967418bcf1b9ba5efb5ca32de623f1ec89852 Mon Sep 17 00:00:00 2001 From: Astrid Date: Tue, 9 Jan 2024 20:50:45 +0100 Subject: [PATCH 015/151] Mark cursor-not-allowed as important so that cursor-pointer gets overridden --- src/components/buttons/Button.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/buttons/Button.tsx b/src/components/buttons/Button.tsx index ed0eebf8..70e2c780 100644 --- a/src/components/buttons/Button.tsx +++ b/src/components/buttons/Button.tsx @@ -41,7 +41,7 @@ export function Button(props: Props) { props.padding ?? "px-4 py-3", props.className, colorClasses, - props.disabled ? "cursor-not-allowed bg-opacity-60 text-opacity-60" : null, + props.disabled ? "!cursor-not-allowed bg-opacity-60 text-opacity-60" : null, ); if (props.disabled) From 421186cb54737655446c3c87469697b4f82d180c Mon Sep 17 00:00:00 2001 From: mrjvs Date: Tue, 9 Jan 2024 21:56:39 +0100 Subject: [PATCH 016/151] Version checking + preparing streams --- src/backend/extension/compatibility.ts | 5 +++ src/backend/extension/messaging.ts | 17 +++++++- src/backend/extension/plasmo.ts | 4 +- src/backend/extension/streams.ts | 40 +++++++++++++++++++ .../player/hooks/useSourceSelection.ts | 3 ++ src/hooks/useProviderScrape.tsx | 3 ++ 6 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 src/backend/extension/compatibility.ts create mode 100644 src/backend/extension/streams.ts diff --git a/src/backend/extension/compatibility.ts b/src/backend/extension/compatibility.ts new file mode 100644 index 00000000..31471d26 --- /dev/null +++ b/src/backend/extension/compatibility.ts @@ -0,0 +1,5 @@ +const allowedExtensionVersion = ["0.0.1"]; + +export function isAllowedExtensionVersion(version: string): boolean { + return allowedExtensionVersion.includes(version); +} diff --git a/src/backend/extension/messaging.ts b/src/backend/extension/messaging.ts index ec0b4bf6..3c5480c1 100644 --- a/src/backend/extension/messaging.ts +++ b/src/backend/extension/messaging.ts @@ -3,6 +3,8 @@ import { sendToBackgroundViaRelay, } from "@plasmohq/messaging"; +import { isAllowedExtensionVersion } from "@/backend/extension/compatibility"; + let activeExtension = false; export interface ExtensionHello { @@ -35,7 +37,14 @@ export async function sendExtensionRequest( url: string, ops: any, ): Promise { - return sendMessage("proxy-request", { url, ...ops }); + return sendMessage("make-request", { url, ...ops }); +} + +export async function setDomainRule( + domains: string[], + headers: Record, +): Promise { + return sendMessage("prepare-stream", { domains, headers }); } export async function extensionInfo(): Promise { @@ -47,5 +56,9 @@ export function isExtensionActiveCached(): boolean { } export async function isExtensionActive(): Promise { - return !!(await extensionInfo()); + const info = await extensionInfo(); + if (!info) return false; + const allowedVersion = isAllowedExtensionVersion(info.version); + if (!allowedVersion) return false; + return true; } diff --git a/src/backend/extension/plasmo.ts b/src/backend/extension/plasmo.ts index 2e9cacbf..8c0093f0 100644 --- a/src/backend/extension/plasmo.ts +++ b/src/backend/extension/plasmo.ts @@ -20,11 +20,11 @@ export type ExtensionRequestReply = }; interface MmMetadata { - "declarative-net-request": { + "prepare-stream": { req: PlasmoRequestBody; res: ExtensionRequestReply; }; - "proxy-request": { + "make-request": { req: PlasmoRequestBody; res: ExtensionRequestReply; }; diff --git a/src/backend/extension/streams.ts b/src/backend/extension/streams.ts new file mode 100644 index 00000000..8d202992 --- /dev/null +++ b/src/backend/extension/streams.ts @@ -0,0 +1,40 @@ +import { Stream } from "@movie-web/providers"; + +import { setDomainRule } from "@/backend/extension/messaging"; + +function extractDomain(url: string): string { + try { + const u = new URL(url); + return u.hostname; + } catch { + return url; + } +} + +function extractDomainsFromStream(stream: Stream): string[] { + if (stream.type === "hls") { + return [extractDomain(stream.playlist)]; + } + if (stream.type === "file") { + return Object.values(stream.qualities).map((v) => extractDomain(v.url)); + } + return []; +} + +function buildHeadersFromStream(stream: Stream): Record { + const headers: Record = {}; + 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( + extractDomainsFromStream(stream), + buildHeadersFromStream(stream), + ); +} diff --git a/src/components/player/hooks/useSourceSelection.ts b/src/components/player/hooks/useSourceSelection.ts index bca884f7..b9e167d6 100644 --- a/src/components/player/hooks/useSourceSelection.ts +++ b/src/components/player/hooks/useSourceSelection.ts @@ -5,6 +5,7 @@ import { } from "@movie-web/providers"; import { useAsyncFn } from "react-use"; +import { prepareStream } from "@/backend/extension/streams"; import { connectServerSideEvents, makeProviderUrl, @@ -131,6 +132,7 @@ export function useSourceScraping(sourceId: string | null, routerId: string) { ]); if (result.stream) { + await prepareStream(result.stream[0]); setCaption(null); setSource( convertRunoutputToSource({ stream: result.stream[0] }), @@ -187,6 +189,7 @@ export function useSourceScraping(sourceId: string | null, routerId: string) { ]); setSourceId(sourceId); setCaption(null); + await prepareStream(embedResult.stream[0]); setSource( convertRunoutputToSource({ stream: embedResult.stream[0] }), convertProviderCaption(embedResult.stream[0].captions), diff --git a/src/hooks/useProviderScrape.tsx b/src/hooks/useProviderScrape.tsx index 21cb985e..d6b48063 100644 --- a/src/hooks/useProviderScrape.tsx +++ b/src/hooks/useProviderScrape.tsx @@ -5,6 +5,7 @@ import { } from "@movie-web/providers"; import { RefObject, useCallback, useEffect, useRef, useState } from "react"; +import { prepareStream } from "@/backend/extension/streams"; import { connectServerSideEvents, getCachedMetadata, @@ -169,6 +170,7 @@ export function useScrape() { conn.on("update", updateEvent); conn.on("discoverEmbeds", discoverEmbedsEvent); const sseOutput = await conn.promise(); + if (sseOutput) await prepareStream(sseOutput.stream); return getResult(sseOutput === "" ? null : sseOutput); } @@ -184,6 +186,7 @@ export function useScrape() { discoverEmbeds: discoverEmbedsEvent, }, }); + if (output) await prepareStream(output.stream); return getResult(output); }, [ From ffea08f3d93a936f4cf2de5a37649bc37512ae0c Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 9 Jan 2024 21:02:39 +0000 Subject: [PATCH 017/151] Remove ARM-32 bit from Docker build --- .github/workflows/deploying.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploying.yml b/.github/workflows/deploying.yml index ebf9d131..e07a60a5 100644 --- a/.github/workflows/deploying.yml +++ b/.github/workflows/deploying.yml @@ -173,7 +173,7 @@ jobs: uses: docker/build-push-action@v5 with: push: true - platforms: linux/amd64,linux/arm64,linux/arm + platforms: linux/amd64,linux/arm64 context: . labels: ${{ steps.meta.outputs.labels }} tags: ${{ steps.meta.outputs.tags }} From 52bc66e7dd934c22913a562757048ec48bde0e58 Mon Sep 17 00:00:00 2001 From: Jorrin Date: Tue, 9 Jan 2024 23:00:54 +0100 Subject: [PATCH 018/151] improve typings --- src/backend/extension/messaging.ts | 51 ++++++++++++++--------- src/backend/extension/plasmo.ts | 67 ++++++++++++++++++++---------- src/backend/extension/streams.ts | 9 ++-- src/backend/providers/fetchers.ts | 9 +++- 4 files changed, 87 insertions(+), 49 deletions(-) diff --git a/src/backend/extension/messaging.ts b/src/backend/extension/messaging.ts index 3c5480c1..28f80ad2 100644 --- a/src/backend/extension/messaging.ts +++ b/src/backend/extension/messaging.ts @@ -7,18 +7,17 @@ import { isAllowedExtensionVersion } from "@/backend/extension/compatibility"; let activeExtension = false; -export interface ExtensionHello { - version: string; -} - -function sendMessage( - message: keyof MessagesMetadata, - payload: any, +function sendMessage( + message: MessageKey, + payload: MessagesMetadata[MessageKey]["req"], timeout: number = -1, ) { - return new Promise((resolve) => { + return new Promise((resolve) => { if (timeout >= 0) setTimeout(() => resolve(null), timeout); - sendToBackgroundViaRelay({ + sendToBackgroundViaRelay< + MessagesMetadata[MessageKey]["req"], + MessagesMetadata[MessageKey]["res"] + >({ name: message, body: payload, }) @@ -34,21 +33,33 @@ function sendMessage( } export async function sendExtensionRequest( - url: string, - ops: any, -): Promise { - return sendMessage("make-request", { url, ...ops }); + ops: Omit, +): Promise { + return sendMessage("makeRequest", { + requestDomain: window.location.origin, + ...ops, + }); } export async function setDomainRule( - domains: string[], - headers: Record, -): Promise { - return sendMessage("prepare-stream", { domains, headers }); + ops: Omit, +): Promise { + return sendMessage("prepareStream", { + requestDomain: window.location.origin, + ...ops, + }); } -export async function extensionInfo(): Promise { - return sendMessage("hello", null, 300); +export async function extensionInfo(): Promise< + MessagesMetadata["hello"]["res"] | null +> { + return sendMessage( + "hello", + { + requestDomain: window.location.origin, + }, + 300, + ); } export function isExtensionActiveCached(): boolean { @@ -57,7 +68,7 @@ export function isExtensionActiveCached(): boolean { export async function isExtensionActive(): Promise { const info = await extensionInfo(); - if (!info) return false; + if (!info?.success) return false; const allowedVersion = isAllowedExtensionVersion(info.version); if (!allowedVersion) return false; return true; diff --git a/src/backend/extension/plasmo.ts b/src/backend/extension/plasmo.ts index 8c0093f0..6c37ad14 100644 --- a/src/backend/extension/plasmo.ts +++ b/src/backend/extension/plasmo.ts @@ -1,6 +1,37 @@ -export interface PlasmoRequestBody { +export interface ExtensionBaseRequest { + requestDomain: string; +} + +export type ExtensionBaseResponse = + | ({ + success: true; + } & T) + | { + success: false; + error: string; + }; + +export type ExtensionHelloResponse = ExtensionBaseResponse<{ + version: string; +}>; + +export interface ExtensionMakeRequest extends ExtensionBaseRequest { + url: string; + method: string; + headers?: Record; + body?: string | FormData | URLSearchParams | Record; +} + +export type ExtensionMakeRequestResponse = ExtensionBaseResponse<{ + status: number; + requestHeaders: Record; + responseHeaders: Record; + data: string | Record; +}>; + +export interface ExtensionPrepareStreamRequest extends ExtensionBaseRequest { ruleId: number; - domain: string; + targetDomains: string[]; requestHeaders?: Record; responseHeaders?: Record; } @@ -9,28 +40,18 @@ export interface ExtensionHelloReply { version: string; } -export type ExtensionRequestReply = - | { - success: true; - ruleId: number; - } - | { - success: false; - error: string; - }; - -interface MmMetadata { - "prepare-stream": { - req: PlasmoRequestBody; - res: ExtensionRequestReply; - }; - "make-request": { - req: PlasmoRequestBody; - res: ExtensionRequestReply; - }; +export interface MmMetadata { hello: { - req: null; - res: ExtensionHelloReply; + req: ExtensionBaseRequest; + res: ExtensionHelloResponse; + }; + makeRequest: { + req: ExtensionMakeRequest; + res: ExtensionMakeRequestResponse; + }; + prepareStream: { + req: ExtensionPrepareStreamRequest; + res: ExtensionBaseResponse; }; } diff --git a/src/backend/extension/streams.ts b/src/backend/extension/streams.ts index 8d202992..2afb900d 100644 --- a/src/backend/extension/streams.ts +++ b/src/backend/extension/streams.ts @@ -33,8 +33,9 @@ function buildHeadersFromStream(stream: Stream): Record { } export async function prepareStream(stream: Stream) { - await setDomainRule( - extractDomainsFromStream(stream), - buildHeadersFromStream(stream), - ); + await setDomainRule({ + ruleId: 1, + targetDomains: extractDomainsFromStream(stream), + requestHeaders: buildHeadersFromStream(stream), + }); } diff --git a/src/backend/providers/fetchers.ts b/src/backend/providers/fetchers.ts index 596e8376..e133199c 100644 --- a/src/backend/providers/fetchers.ts +++ b/src/backend/providers/fetchers.ts @@ -54,8 +54,13 @@ export function makeLoadBalancedSimpleProxyFetcher() { } export function makeExtensionFetcher() { - const fetcher: Fetcher = async (a, b) => { - return sendExtensionRequest(a, b) as any; + const fetcher: Fetcher = async (url, ops) => { + return sendExtensionRequest({ + url, + method: ops?.method ?? "GET", + headers: ops?.headers, + body: ops?.body, + }) as any; }; return fetcher; } From 4bdb95ed0fd88fb456f03691c5a689c17b381a28 Mon Sep 17 00:00:00 2001 From: Jorrin Date: Tue, 9 Jan 2024 23:35:23 +0100 Subject: [PATCH 019/151] fix --- src/backend/providers/fetchers.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/backend/providers/fetchers.ts b/src/backend/providers/fetchers.ts index e133199c..f1dbbfb8 100644 --- a/src/backend/providers/fetchers.ts +++ b/src/backend/providers/fetchers.ts @@ -57,9 +57,7 @@ export function makeExtensionFetcher() { const fetcher: Fetcher = async (url, ops) => { return sendExtensionRequest({ url, - method: ops?.method ?? "GET", - headers: ops?.headers, - body: ops?.body, + ...ops, }) as any; }; return fetcher; From caa82e15a3d5bc2c5eb3e9f3b710b90278d65281 Mon Sep 17 00:00:00 2001 From: Isra Date: Tue, 9 Jan 2024 21:14:03 -0600 Subject: [PATCH 020/151] Instructions --- src/assets/locales/en.json | 4 ++-- src/pages/parts/settings/ConnectionsPart.tsx | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index 9329ec0e..425f6c32 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -393,14 +393,14 @@ }, "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.", "label": "Custom server", "urlLabel": "Custom server URL" }, "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.", "emptyState": "No workers yet, add one below", "label": "Use custom proxy workers", "urlLabel": "Worker URLs", diff --git a/src/pages/parts/settings/ConnectionsPart.tsx b/src/pages/parts/settings/ConnectionsPart.tsx index 007a6220..11aa8171 100644 --- a/src/pages/parts/settings/ConnectionsPart.tsx +++ b/src/pages/parts/settings/ConnectionsPart.tsx @@ -1,10 +1,11 @@ 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"; @@ -52,7 +53,9 @@ function ProxyEdit({ proxyUrls, setProxyUrls }: ProxyEditProps) { {t("settings.connections.workers.label")}

- {t("settings.connections.workers.description")} + + Google +

@@ -118,7 +121,9 @@ function BackendEdit({ backendUrl, setBackendUrl }: BackendEditProps) { {t("settings.connections.server.label")}

- {t("settings.connections.server.description")} + + Google +

From b11a7016be6874956a5f33e4d25ad90cc3064ab4 Mon Sep 17 00:00:00 2001 From: Isra Date: Tue, 9 Jan 2024 21:18:41 -0600 Subject: [PATCH 021/151] Actual links --- src/pages/parts/settings/ConnectionsPart.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/pages/parts/settings/ConnectionsPart.tsx b/src/pages/parts/settings/ConnectionsPart.tsx index 11aa8171..e9183764 100644 --- a/src/pages/parts/settings/ConnectionsPart.tsx +++ b/src/pages/parts/settings/ConnectionsPart.tsx @@ -54,7 +54,9 @@ function ProxyEdit({ proxyUrls, setProxyUrls }: ProxyEditProps) {

- Google + + Proxy documentation +

@@ -122,7 +124,9 @@ function BackendEdit({ backendUrl, setBackendUrl }: BackendEditProps) {

- Google + + Backend documentation +

From e1be30dde9ad62760b44300b945556791cad5e13 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Wed, 10 Jan 2024 18:20:51 +0100 Subject: [PATCH 022/151] Request messaging --- src/backend/extension/messaging.ts | 5 +++-- src/backend/extension/plasmo.ts | 14 ++++++++------ src/backend/providers/fetchers.ts | 24 ++++++++++++++++++++++-- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/backend/extension/messaging.ts b/src/backend/extension/messaging.ts index 28f80ad2..3d835a0e 100644 --- a/src/backend/extension/messaging.ts +++ b/src/backend/extension/messaging.ts @@ -4,6 +4,7 @@ import { } from "@plasmohq/messaging"; import { isAllowedExtensionVersion } from "@/backend/extension/compatibility"; +import { ExtensionMakeRequestResponse } from "@/backend/extension/plasmo"; let activeExtension = false; @@ -32,9 +33,9 @@ function sendMessage( }); } -export async function sendExtensionRequest( +export async function sendExtensionRequest( ops: Omit, -): Promise { +): Promise | null> { return sendMessage("makeRequest", { requestDomain: window.location.origin, ...ops, diff --git a/src/backend/extension/plasmo.ts b/src/backend/extension/plasmo.ts index 6c37ad14..0a2b3dc5 100644 --- a/src/backend/extension/plasmo.ts +++ b/src/backend/extension/plasmo.ts @@ -22,11 +22,13 @@ export interface ExtensionMakeRequest extends ExtensionBaseRequest { body?: string | FormData | URLSearchParams | Record; } -export type ExtensionMakeRequestResponse = ExtensionBaseResponse<{ - status: number; - requestHeaders: Record; - responseHeaders: Record; - data: string | Record; +export type ExtensionMakeRequestResponse = ExtensionBaseResponse<{ + response: { + statusCode: number; + headers: Record; + finalUrl: string; + body: T; + }; }>; export interface ExtensionPrepareStreamRequest extends ExtensionBaseRequest { @@ -47,7 +49,7 @@ export interface MmMetadata { }; makeRequest: { req: ExtensionMakeRequest; - res: ExtensionMakeRequestResponse; + res: ExtensionMakeRequestResponse; }; prepareStream: { req: ExtensionPrepareStreamRequest; diff --git a/src/backend/providers/fetchers.ts b/src/backend/providers/fetchers.ts index f1dbbfb8..9db649f5 100644 --- a/src/backend/providers/fetchers.ts +++ b/src/backend/providers/fetchers.ts @@ -53,12 +53,32 @@ export function makeLoadBalancedSimpleProxyFetcher() { return fetcher; } +function makeFinalHeaders( + readHeaders: string[], + headers: Record, +): 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) => { - return sendExtensionRequest({ + const result = await sendExtensionRequest({ url, ...ops, - }) as any; + }); + 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; } From d32ef6ed9ae88db294a8c232c65018a65f1b4abc Mon Sep 17 00:00:00 2001 From: Jorrin Date: Wed, 10 Jan 2024 19:43:54 +0100 Subject: [PATCH 023/151] fix extension not preparing stream on embed selection --- src/components/player/hooks/useSourceSelection.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/player/hooks/useSourceSelection.ts b/src/components/player/hooks/useSourceSelection.ts index b9e167d6..3016e332 100644 --- a/src/components/player/hooks/useSourceSelection.ts +++ b/src/components/player/hooks/useSourceSelection.ts @@ -72,6 +72,7 @@ export function useEmbedScraping( report([ scrapeSourceOutputToProviderMetric(meta, sourceId, null, "success", null), ]); + await prepareStream(result.stream[0]); setSourceId(sourceId); setCaption(null); setSource( From 3704dfba10ae8ada3573c084848c7e0ebf8fb5c4 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Wed, 10 Jan 2024 22:04:21 +0100 Subject: [PATCH 024/151] Fix styling bugs, fix player not switching source after error, fix allowed state in extension, add ip locked sourced for extension Co-authored-by: Jip Frijlink --- src/backend/extension/messaging.ts | 7 +++++-- src/backend/extension/plasmo.ts | 5 +---- src/backend/providers/providers.ts | 1 + .../player/atoms/settings/SourceSelectingView.tsx | 2 +- src/stores/player/slices/source.ts | 10 +++++++++- src/utils/language.ts | 2 +- 6 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/backend/extension/messaging.ts b/src/backend/extension/messaging.ts index 3d835a0e..4594fb23 100644 --- a/src/backend/extension/messaging.ts +++ b/src/backend/extension/messaging.ts @@ -37,7 +37,7 @@ export async function sendExtensionRequest( ops: Omit, ): Promise | null> { return sendMessage("makeRequest", { - requestDomain: window.location.origin, + requestDomain: window.location.origin, // TODO unsafe ...ops, }); } @@ -54,13 +54,16 @@ export async function setDomainRule( export async function extensionInfo(): Promise< MessagesMetadata["hello"]["res"] | null > { - return sendMessage( + const message = await sendMessage( "hello", { requestDomain: window.location.origin, }, 300, ); + if (!message?.success) return null; + if (!message.allowed) return null; + return message; } export function isExtensionActiveCached(): boolean { diff --git a/src/backend/extension/plasmo.ts b/src/backend/extension/plasmo.ts index 0a2b3dc5..e142ef6a 100644 --- a/src/backend/extension/plasmo.ts +++ b/src/backend/extension/plasmo.ts @@ -13,6 +13,7 @@ export type ExtensionBaseResponse = export type ExtensionHelloResponse = ExtensionBaseResponse<{ version: string; + allowed: boolean; }>; export interface ExtensionMakeRequest extends ExtensionBaseRequest { @@ -38,10 +39,6 @@ export interface ExtensionPrepareStreamRequest extends ExtensionBaseRequest { responseHeaders?: Record; } -export interface ExtensionHelloReply { - version: string; -} - export interface MmMetadata { hello: { req: ExtensionBaseRequest; diff --git a/src/backend/providers/providers.ts b/src/backend/providers/providers.ts index 1a7b484a..ac4a7dfa 100644 --- a/src/backend/providers/providers.ts +++ b/src/backend/providers/providers.ts @@ -15,6 +15,7 @@ export function getProviders() { return makeProviders({ fetcher: makeExtensionFetcher(), target: targets.BROWSER_EXTENSION, + consistentIpForRequests: true, }); } diff --git a/src/components/player/atoms/settings/SourceSelectingView.tsx b/src/components/player/atoms/settings/SourceSelectingView.tsx index 03d0875d..f995308e 100644 --- a/src/components/player/atoms/settings/SourceSelectingView.tsx +++ b/src/components/player/atoms/settings/SourceSelectingView.tsx @@ -147,7 +147,7 @@ export function SourceSelectionView({ router.navigate("/")}> {t("player.menus.sources.title")} - + {sources.map((v) => ( = (set, get) => ({ }, setSourceId(id) { set((s) => { + s.status = playerStatus.PLAYING; s.sourceId = id; }); }, @@ -153,6 +154,8 @@ export const createSourceSlice: MakeSlice = (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); @@ -166,7 +169,10 @@ export const createSourceSlice: MakeSlice = (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, @@ -182,6 +188,8 @@ export const createSourceSlice: MakeSlice = (set, get) => ({ if (!selectedQuality) return; set((s) => { s.currentQuality = quality; + s.status = playerStatus.PLAYING; + s.interface.error = undefined; }); store.display?.load({ source: selectedQuality, diff --git a/src/utils/language.ts b/src/utils/language.ts index 6fda7df8..41b8168b 100644 --- a/src/utils/language.ts +++ b/src/utils/language.ts @@ -86,7 +86,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; From 6c7f1aceceab21bd5db888d2e1c2604084f0c0ae Mon Sep 17 00:00:00 2001 From: mrjvs Date: Thu, 11 Jan 2024 19:16:22 +0100 Subject: [PATCH 025/151] Remove requestDomain --- src/backend/extension/messaging.ts | 18 +++--------------- src/backend/extension/plasmo.ts | 4 +--- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/src/backend/extension/messaging.ts b/src/backend/extension/messaging.ts index 4594fb23..6d1f32fd 100644 --- a/src/backend/extension/messaging.ts +++ b/src/backend/extension/messaging.ts @@ -36,31 +36,19 @@ function sendMessage( export async function sendExtensionRequest( ops: Omit, ): Promise | null> { - return sendMessage("makeRequest", { - requestDomain: window.location.origin, // TODO unsafe - ...ops, - }); + return sendMessage("makeRequest", ops); } export async function setDomainRule( ops: Omit, ): Promise { - return sendMessage("prepareStream", { - requestDomain: window.location.origin, - ...ops, - }); + return sendMessage("prepareStream", ops); } export async function extensionInfo(): Promise< MessagesMetadata["hello"]["res"] | null > { - const message = await sendMessage( - "hello", - { - requestDomain: window.location.origin, - }, - 300, - ); + const message = await sendMessage("hello", {}, 300); if (!message?.success) return null; if (!message.allowed) return null; return message; diff --git a/src/backend/extension/plasmo.ts b/src/backend/extension/plasmo.ts index e142ef6a..12222b22 100644 --- a/src/backend/extension/plasmo.ts +++ b/src/backend/extension/plasmo.ts @@ -1,6 +1,4 @@ -export interface ExtensionBaseRequest { - requestDomain: string; -} +export interface ExtensionBaseRequest {} export type ExtensionBaseResponse = | ({ From ccbf888946082d339234f06317517a09aa65fa69 Mon Sep 17 00:00:00 2001 From: Jorrin Date: Thu, 11 Jan 2024 23:45:33 +0100 Subject: [PATCH 026/151] firefox support (kinda with manual permission set) --- src/backend/extension/streams.ts | 2 +- src/backend/providers/fetchers.ts | 36 ++++++++++++++++++++++--------- src/backend/providers/utils.ts | 29 +++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 src/backend/providers/utils.ts diff --git a/src/backend/extension/streams.ts b/src/backend/extension/streams.ts index 2afb900d..daa7a54c 100644 --- a/src/backend/extension/streams.ts +++ b/src/backend/extension/streams.ts @@ -34,7 +34,7 @@ function buildHeadersFromStream(stream: Stream): Record { export async function prepareStream(stream: Stream) { await setDomainRule({ - ruleId: 1, + ruleId: 2, targetDomains: extractDomainsFromStream(stream), requestHeaders: buildHeadersFromStream(stream), }); diff --git a/src/backend/providers/fetchers.ts b/src/backend/providers/fetchers.ts index 9db649f5..83e42835 100644 --- a/src/backend/providers/fetchers.ts +++ b/src/backend/providers/fetchers.ts @@ -1,9 +1,11 @@ import { Fetcher, makeSimpleProxyFetcher } from "@movie-web/providers"; -import { sendExtensionRequest } from "@/backend/extension/messaging"; +import { setDomainRule } from "@/backend/extension/messaging"; import { getApiToken, setApiToken } from "@/backend/helpers/providerApi"; import { getProviderApiUrls, getProxyUrls } from "@/utils/proxyUrls"; +import { makeFullUrl } from "./utils"; + function makeLoadbalancedList(getter: () => string[]) { let listIndex = -1; return () => { @@ -67,17 +69,31 @@ function makeFinalHeaders( export function makeExtensionFetcher() { const fetcher: Fetcher = async (url, ops) => { - const result = await sendExtensionRequest({ - url, - ...ops, + const fullUrl = makeFullUrl(url, ops); + const res = await setDomainRule({ + ruleId: 1, + targetDomains: [fullUrl], + requestHeaders: ops.headers, }); - if (!result?.success) throw new Error(`extension error: ${result?.error}`); - const res = result.response; + console.log(res, fullUrl); + const response = await fetch(fullUrl, { + method: ops.method, + headers: ops.headers, + body: ops.body as any, + }); + const contentType = response.headers.get("content-type"); + const body = contentType?.includes("application/json") + ? await response.json() + : await response.text(); + return { - body: res.body, - finalUrl: res.finalUrl, - statusCode: res.statusCode, - headers: makeFinalHeaders(ops.readHeaders, res.headers), + body, + finalUrl: response.url, + statusCode: response.status, + headers: makeFinalHeaders( + ops.readHeaders, + Object.fromEntries(response.headers.entries()), + ), }; }; return fetcher; diff --git a/src/backend/providers/utils.ts b/src/backend/providers/utils.ts new file mode 100644 index 00000000..7149046c --- /dev/null +++ b/src/backend/providers/utils.ts @@ -0,0 +1,29 @@ +import { DefaultedFetcherOptions } from "@movie-web/providers"; + +export function makeFullUrl( + url: string, + ops?: DefaultedFetcherOptions, +): string { + // glue baseUrl and rest of url together + let leftSide = ops?.baseUrl ?? ""; + let rightSide = url; + + // left side should always end with slash, if its set + if (leftSide.length > 0 && !leftSide.endsWith("/")) leftSide += "/"; + + // right side should never start with slash + if (rightSide.startsWith("/")) rightSide = rightSide.slice(1); + + const fullUrl = leftSide + rightSide; + if (!fullUrl.startsWith("http://") && !fullUrl.startsWith("https://")) + throw new Error( + `Invald URL -- URL doesn't start with a http scheme: '${fullUrl}'`, + ); + + const parsedUrl = new URL(fullUrl); + Object.entries(ops?.query ?? {}).forEach(([k, v]) => { + parsedUrl.searchParams.set(k, v as string); + }); + + return parsedUrl.toString(); +} From a4b925dc1b7749aa4caed3b4b4c174d38f018795 Mon Sep 17 00:00:00 2001 From: Jorrin Date: Fri, 12 Jan 2024 18:46:51 +0100 Subject: [PATCH 027/151] revert back to makeRequest --- src/backend/extension/streams.ts | 2 +- src/backend/providers/fetchers.ts | 38 +++++++++---------------------- src/backend/providers/utils.ts | 29 ----------------------- 3 files changed, 12 insertions(+), 57 deletions(-) delete mode 100644 src/backend/providers/utils.ts diff --git a/src/backend/extension/streams.ts b/src/backend/extension/streams.ts index daa7a54c..2afb900d 100644 --- a/src/backend/extension/streams.ts +++ b/src/backend/extension/streams.ts @@ -34,7 +34,7 @@ function buildHeadersFromStream(stream: Stream): Record { export async function prepareStream(stream: Stream) { await setDomainRule({ - ruleId: 2, + ruleId: 1, targetDomains: extractDomainsFromStream(stream), requestHeaders: buildHeadersFromStream(stream), }); diff --git a/src/backend/providers/fetchers.ts b/src/backend/providers/fetchers.ts index 83e42835..95267595 100644 --- a/src/backend/providers/fetchers.ts +++ b/src/backend/providers/fetchers.ts @@ -1,11 +1,9 @@ import { Fetcher, makeSimpleProxyFetcher } from "@movie-web/providers"; -import { setDomainRule } from "@/backend/extension/messaging"; +import { sendExtensionRequest } from "@/backend/extension/messaging"; import { getApiToken, setApiToken } from "@/backend/helpers/providerApi"; import { getProviderApiUrls, getProxyUrls } from "@/utils/proxyUrls"; -import { makeFullUrl } from "./utils"; - function makeLoadbalancedList(getter: () => string[]) { let listIndex = -1; return () => { @@ -69,31 +67,17 @@ function makeFinalHeaders( export function makeExtensionFetcher() { const fetcher: Fetcher = async (url, ops) => { - const fullUrl = makeFullUrl(url, ops); - const res = await setDomainRule({ - ruleId: 1, - targetDomains: [fullUrl], - requestHeaders: ops.headers, - }); - console.log(res, fullUrl); - const response = await fetch(fullUrl, { - method: ops.method, - headers: ops.headers, - body: ops.body as any, - }); - const contentType = response.headers.get("content-type"); - const body = contentType?.includes("application/json") - ? await response.json() - : await response.text(); - + const result = (await sendExtensionRequest({ + url, + ...ops, + })) as any; + if (!result?.success) throw new Error(`extension error: ${result?.error}`); + const res = result.response; return { - body, - finalUrl: response.url, - statusCode: response.status, - headers: makeFinalHeaders( - ops.readHeaders, - Object.fromEntries(response.headers.entries()), - ), + body: res.body, + finalUrl: res.finalUrl, + statusCode: res.statusCode, + headers: makeFinalHeaders(ops.readHeaders, res.headers), }; }; return fetcher; diff --git a/src/backend/providers/utils.ts b/src/backend/providers/utils.ts deleted file mode 100644 index 7149046c..00000000 --- a/src/backend/providers/utils.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { DefaultedFetcherOptions } from "@movie-web/providers"; - -export function makeFullUrl( - url: string, - ops?: DefaultedFetcherOptions, -): string { - // glue baseUrl and rest of url together - let leftSide = ops?.baseUrl ?? ""; - let rightSide = url; - - // left side should always end with slash, if its set - if (leftSide.length > 0 && !leftSide.endsWith("/")) leftSide += "/"; - - // right side should never start with slash - if (rightSide.startsWith("/")) rightSide = rightSide.slice(1); - - const fullUrl = leftSide + rightSide; - if (!fullUrl.startsWith("http://") && !fullUrl.startsWith("https://")) - throw new Error( - `Invald URL -- URL doesn't start with a http scheme: '${fullUrl}'`, - ); - - const parsedUrl = new URL(fullUrl); - Object.entries(ops?.query ?? {}).forEach(([k, v]) => { - parsedUrl.searchParams.set(k, v as string); - }); - - return parsedUrl.toString(); -} From 948843769820630fdc49e323bd64a788d968f7e6 Mon Sep 17 00:00:00 2001 From: Jorrin Date: Sun, 14 Jan 2024 18:19:38 +0100 Subject: [PATCH 028/151] check if extension has permissions --- src/backend/extension/messaging.ts | 10 +++++-- src/backend/extension/plasmo.ts | 8 ++++++ src/pages/parts/player/MetaPart.tsx | 43 ++++++++++++++++++++++++++--- 3 files changed, 55 insertions(+), 6 deletions(-) diff --git a/src/backend/extension/messaging.ts b/src/backend/extension/messaging.ts index 6d1f32fd..2e2747c1 100644 --- a/src/backend/extension/messaging.ts +++ b/src/backend/extension/messaging.ts @@ -34,17 +34,23 @@ function sendMessage( } export async function sendExtensionRequest( - ops: Omit, + ops: MessagesMetadata["makeRequest"]["req"], ): Promise | null> { return sendMessage("makeRequest", ops); } export async function setDomainRule( - ops: Omit, + ops: MessagesMetadata["prepareStream"]["req"], ): Promise { return sendMessage("prepareStream", ops); } +export async function sendPage( + ops: MessagesMetadata["openPage"]["req"], +): Promise { + return sendMessage("openPage", ops); +} + export async function extensionInfo(): Promise< MessagesMetadata["hello"]["res"] | null > { diff --git a/src/backend/extension/plasmo.ts b/src/backend/extension/plasmo.ts index 12222b22..c13898be 100644 --- a/src/backend/extension/plasmo.ts +++ b/src/backend/extension/plasmo.ts @@ -12,6 +12,7 @@ export type ExtensionBaseResponse = export type ExtensionHelloResponse = ExtensionBaseResponse<{ version: string; allowed: boolean; + hasPermission: boolean; }>; export interface ExtensionMakeRequest extends ExtensionBaseRequest { @@ -50,6 +51,13 @@ export interface MmMetadata { req: ExtensionPrepareStreamRequest; res: ExtensionBaseResponse; }; + openPage: { + req: ExtensionBaseRequest & { + page: string; + redirectUrl: string; + }; + res: ExtensionBaseResponse; + }; } interface MpMetadata {} diff --git a/src/pages/parts/player/MetaPart.tsx b/src/pages/parts/player/MetaPart.tsx index 6d5b64ef..fb40379a 100644 --- a/src/pages/parts/player/MetaPart.tsx +++ b/src/pages/parts/player/MetaPart.tsx @@ -3,7 +3,8 @@ import { useNavigate, useParams } from "react-router-dom"; import { useAsync } from "react-use"; import type { AsyncReturnType } from "type-fest"; -import { isExtensionActive } from "@/backend/extension/messaging"; +import { isAllowedExtensionVersion } from "@/backend/extension/compatibility"; +import { extensionInfo, sendPage } from "@/backend/extension/messaging"; import { fetchMetadata, setCachedMetadata, @@ -43,12 +44,16 @@ export function MetaPart(props: MetaPartProps) { const navigate = useNavigate(); const { error, value, loading } = useAsync(async () => { - // check extension - const isActive = await isExtensionActive(); + const info = await extensionInfo(); + const isAllowed = info?.success && isAllowedExtensionVersion(info.version); + + if (isAllowed) { + if (!info.hasPermission) throw new Error("extension-no-permission"); + } // use api metadata or providers metadata const providerApiUrl = getLoadbalancedProviderApiUrl(); - if (providerApiUrl && !isActive) { + if (providerApiUrl && !isAllowed) { try { await fetchMetadata(providerApiUrl); } catch (err) { @@ -105,6 +110,36 @@ export function MetaPart(props: MetaPartProps) { props.onGetMeta?.(meta, epId); }, []); + if (error && error.message === "extension-no-permission") { + return ( + + + + {t("player.metadata.failed.badge")} + + Configure the extension + + You have the browser extension, but we need your permission to get + started using the extension. + + + + + ); + } + if (error && error.message === "dmca") { return ( From fa2b610ea6f3e4fc3d6481ed5f5c2090478adbd4 Mon Sep 17 00:00:00 2001 From: Jorrin Date: Sun, 14 Jan 2024 22:33:46 +0100 Subject: [PATCH 029/151] fix permission check on domain level --- src/backend/extension/messaging.ts | 6 ++---- src/pages/parts/player/MetaPart.tsx | 10 ++++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/backend/extension/messaging.ts b/src/backend/extension/messaging.ts index 2e2747c1..b738184a 100644 --- a/src/backend/extension/messaging.ts +++ b/src/backend/extension/messaging.ts @@ -10,7 +10,7 @@ let activeExtension = false; function sendMessage( message: MessageKey, - payload: MessagesMetadata[MessageKey]["req"], + payload: MessagesMetadata[MessageKey]["req"] | undefined = undefined, timeout: number = -1, ) { return new Promise((resolve) => { @@ -54,9 +54,7 @@ export async function sendPage( export async function extensionInfo(): Promise< MessagesMetadata["hello"]["res"] | null > { - const message = await sendMessage("hello", {}, 300); - if (!message?.success) return null; - if (!message.allowed) return null; + const message = await sendMessage("hello", undefined, 300); return message; } diff --git a/src/pages/parts/player/MetaPart.tsx b/src/pages/parts/player/MetaPart.tsx index fb40379a..1e18b6d1 100644 --- a/src/pages/parts/player/MetaPart.tsx +++ b/src/pages/parts/player/MetaPart.tsx @@ -45,15 +45,17 @@ export function MetaPart(props: MetaPartProps) { const { error, value, loading } = useAsync(async () => { const info = await extensionInfo(); - const isAllowed = info?.success && isAllowedExtensionVersion(info.version); + const isValidExtension = + info?.success && isAllowedExtensionVersion(info.version); - if (isAllowed) { - if (!info.hasPermission) throw new Error("extension-no-permission"); + if (isValidExtension) { + if (!info.allowed || !info.hasPermission) + throw new Error("extension-no-permission"); } // use api metadata or providers metadata const providerApiUrl = getLoadbalancedProviderApiUrl(); - if (providerApiUrl && !isAllowed) { + if (providerApiUrl && !isValidExtension) { try { await fetchMetadata(providerApiUrl); } catch (err) { From 925f3dff199fc6457eb9f97209addf780700e565 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Tue, 16 Jan 2024 20:28:33 +0100 Subject: [PATCH 030/151] Basic onboarding structure --- src/components/layout/Stepper.tsx | 25 ++++++++++ src/components/layout/ThinContainer.tsx | 14 ++++++ src/pages/PlayerView.tsx | 32 ++++++++++++- src/pages/layouts/MinimalPageLayout.tsx | 28 ++++++++++++ src/pages/onboarding/Onboarding.tsx | 48 ++++++++++++++++++++ src/pages/onboarding/OnboardingExtension.tsx | 27 +++++++++++ src/pages/onboarding/OnboardingProxy.tsx | 27 +++++++++++ src/pages/onboarding/onboardingHooks.ts | 22 +++++++++ src/setup/App.tsx | 9 ++++ src/setup/config.ts | 4 ++ src/stores/history/index.ts | 3 +- src/stores/onboarding/index.tsx | 22 +++++++++ src/utils/onboarding.ts | 23 ++++++++++ 13 files changed, 281 insertions(+), 3 deletions(-) create mode 100644 src/components/layout/Stepper.tsx create mode 100644 src/pages/layouts/MinimalPageLayout.tsx create mode 100644 src/pages/onboarding/Onboarding.tsx create mode 100644 src/pages/onboarding/OnboardingExtension.tsx create mode 100644 src/pages/onboarding/OnboardingProxy.tsx create mode 100644 src/pages/onboarding/onboardingHooks.ts create mode 100644 src/stores/onboarding/index.tsx create mode 100644 src/utils/onboarding.ts diff --git a/src/components/layout/Stepper.tsx b/src/components/layout/Stepper.tsx new file mode 100644 index 00000000..d0c9c499 --- /dev/null +++ b/src/components/layout/Stepper.tsx @@ -0,0 +1,25 @@ +export interface StepperProps { + current: number; + steps: number; + className?: string; +} + +export function Stepper(props: StepperProps) { + const percentage = (props.current / (props.steps + 1)) * 100; + + return ( +
+

+ {props.current}/{props.steps} +

+
+
+
+
+ ); +} diff --git a/src/components/layout/ThinContainer.tsx b/src/components/layout/ThinContainer.tsx index f7f90acb..345afa5c 100644 --- a/src/components/layout/ThinContainer.tsx +++ b/src/components/layout/ThinContainer.tsx @@ -1,3 +1,4 @@ +import classNames from "classnames"; import { ReactNode } from "react"; interface ThinContainerProps { @@ -16,3 +17,16 @@ export function ThinContainer(props: ThinContainerProps) {
); } + +export function CenterContainer(props: ThinContainerProps) { + return ( +
+
{props.children}
+
+ ); +} diff --git a/src/pages/PlayerView.tsx b/src/pages/PlayerView.tsx index aa73bd83..5282d9b3 100644 --- a/src/pages/PlayerView.tsx +++ b/src/pages/PlayerView.tsx @@ -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 ( + + ); + return ; +} + export default PlayerView; diff --git a/src/pages/layouts/MinimalPageLayout.tsx b/src/pages/layouts/MinimalPageLayout.tsx new file mode 100644 index 00000000..6d2cf34d --- /dev/null +++ b/src/pages/layouts/MinimalPageLayout.tsx @@ -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 ( +
+ + {/* Main page */} +
+ + + +
+
{props.children}
+
+ ); +} diff --git a/src/pages/onboarding/Onboarding.tsx b/src/pages/onboarding/Onboarding.tsx new file mode 100644 index 00000000..439cc87d --- /dev/null +++ b/src/pages/onboarding/Onboarding.tsx @@ -0,0 +1,48 @@ +import { useNavigate } from "react-router-dom"; + +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 { Heading2, Paragraph } from "@/components/utils/Text"; +import { MinimalPageLayout } from "@/pages/layouts/MinimalPageLayout"; +import { useRedirectBack } from "@/pages/onboarding/onboardingHooks"; +import { PageTitle } from "@/pages/parts/util/PageTitle"; + +export function OnboardingPage() { + const navigate = useNavigate(); + const skipModal = useModal("skip"); + const { skipAndRedirect } = useRedirectBack(); + + return ( + + + + + + Lorem ipsum + Lorem ipsum Lorem ipsum Lorem ipsum + + + + + + + + Lorem ipsum + Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum + + + + + + ); +} diff --git a/src/pages/onboarding/OnboardingExtension.tsx b/src/pages/onboarding/OnboardingExtension.tsx new file mode 100644 index 00000000..8ee85be7 --- /dev/null +++ b/src/pages/onboarding/OnboardingExtension.tsx @@ -0,0 +1,27 @@ +import { useNavigate } from "react-router-dom"; + +import { Button } from "@/components/buttons/Button"; +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 { PageTitle } from "@/pages/parts/util/PageTitle"; + +export function OnboardingExtensionPage() { + const navigate = useNavigate(); + + return ( + + + + + Lorem ipsum + Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum + + + + + ); +} diff --git a/src/pages/onboarding/OnboardingProxy.tsx b/src/pages/onboarding/OnboardingProxy.tsx new file mode 100644 index 00000000..45d22aea --- /dev/null +++ b/src/pages/onboarding/OnboardingProxy.tsx @@ -0,0 +1,27 @@ +import { useNavigate } from "react-router-dom"; + +import { Button } from "@/components/buttons/Button"; +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 { PageTitle } from "@/pages/parts/util/PageTitle"; + +export function OnboardingProxyPage() { + const navigate = useNavigate(); + + return ( + + + + + Lorem ipsum + Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum + + + + + ); +} diff --git a/src/pages/onboarding/onboardingHooks.ts b/src/pages/onboarding/onboardingHooks.ts new file mode 100644 index 00000000..e80234e7 --- /dev/null +++ b/src/pages/onboarding/onboardingHooks.ts @@ -0,0 +1,22 @@ +import { useCallback } from "react"; +import { 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 setSkipped = useOnboardingStore((s) => s.setSkipped); + + const redirectBack = useCallback(() => { + navigate(url ?? "/"); + }, [navigate, url]); + + const skipAndRedirect = useCallback(() => { + setSkipped(true); + redirectBack(); + }, [redirectBack, setSkipped]); + + return { redirectBack, skipAndRedirect }; +} diff --git a/src/setup/App.tsx b/src/setup/App.tsx index afa5f8ba..37c55e0f 100644 --- a/src/setup/App.tsx +++ b/src/setup/App.tsx @@ -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() { } /> } /> } /> + } /> + } + /> + } /> {shouldHaveDmcaPage() ? ( } /> diff --git a/src/setup/config.ts b/src/setup/config.ts index 2e1634a4..d6aca1cb 100644 --- a/src/setup/config.ts +++ b/src/setup/config.ts @@ -19,6 +19,7 @@ interface Config { DISALLOWED_IDS: string; TURNSTILE_KEY: string; CDN_REPLACEMENTS: string; + HAS_ONBOARDING: string; } export interface RuntimeConfig { @@ -34,6 +35,7 @@ export interface RuntimeConfig { DISALLOWED_IDS: string[]; TURNSTILE_KEY: string | null; CDN_REPLACEMENTS: Array; + HAS_ONBOARDING: boolean; } const env: Record = { @@ -49,6 +51,7 @@ const env: Record = { 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) @@ -82,6 +85,7 @@ export function conf(): RuntimeConfig { .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(",") diff --git a/src/stores/history/index.ts b/src/stores/history/index.ts index c90a7309..c1f507ee 100644 --- a/src/stores/history/index.ts +++ b/src/stores/history/index.ts @@ -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]); diff --git a/src/stores/onboarding/index.tsx b/src/stores/onboarding/index.tsx new file mode 100644 index 00000000..17d1965d --- /dev/null +++ b/src/stores/onboarding/index.tsx @@ -0,0 +1,22 @@ +import { create } from "zustand"; +import { persist } from "zustand/middleware"; +import { immer } from "zustand/middleware/immer"; + +export interface OnboardingStore { + skipped: boolean; + setSkipped(v: boolean): void; +} + +export const useOnboardingStore = create( + persist( + immer((set) => ({ + skipped: false, + setSkipped(v) { + set((s) => { + s.skipped = v; + }); + }, + })), + { name: "__MW::onboarding" }, + ), +); diff --git a/src/utils/onboarding.ts b/src/utils/onboarding.ts new file mode 100644 index 00000000..7289fd1c --- /dev/null +++ b/src/utils/onboarding.ts @@ -0,0 +1,23 @@ +import { isExtensionActive } from "@/backend/extension/messaging"; +import { conf } from "@/setup/config"; +import { useAuthStore } from "@/stores/auth"; +import { useOnboardingStore } from "@/stores/onboarding"; + +export async function needsOnboarding(): Promise { + // if onboarding is dislabed, no onboarding needed + if (!conf().HAS_ONBOARDING) return false; + + // if extension is active and working, no onboarding needed + const extensionActive = await isExtensionActive(); + if (extensionActive) return false; + + // if there is any custom proxy urls, no onboarding needed + const proxyUrls = useAuthStore.getState().proxySet; + if (proxyUrls) return false; + + // if onboarding has been skipped, no onboarding needed + const skipped = useOnboardingStore.getState().skipped; + if (skipped) return false; + + return true; +} From a226f3347cb77affffca21dd00fb512f7bc0388b Mon Sep 17 00:00:00 2001 From: mrjvs Date: Tue, 16 Jan 2024 22:07:21 +0100 Subject: [PATCH 031/151] Add onboarding functionality --- src/pages/onboarding/Onboarding.tsx | 4 +- src/pages/onboarding/OnboardingExtension.tsx | 55 +++++++++++++++++++- src/pages/onboarding/OnboardingProxy.tsx | 27 ++++++++-- src/pages/onboarding/onboardingHooks.ts | 10 ++-- src/stores/onboarding/index.tsx | 10 ++-- src/utils/onboarding.ts | 6 +-- 6 files changed, 92 insertions(+), 20 deletions(-) diff --git a/src/pages/onboarding/Onboarding.tsx b/src/pages/onboarding/Onboarding.tsx index 439cc87d..3247a7ee 100644 --- a/src/pages/onboarding/Onboarding.tsx +++ b/src/pages/onboarding/Onboarding.tsx @@ -12,7 +12,7 @@ import { PageTitle } from "@/pages/parts/util/PageTitle"; export function OnboardingPage() { const navigate = useNavigate(); const skipModal = useModal("skip"); - const { skipAndRedirect } = useRedirectBack(); + const { completeAndRedirect } = useRedirectBack(); return ( @@ -25,7 +25,7 @@ export function OnboardingPage() { - diff --git a/src/pages/onboarding/OnboardingExtension.tsx b/src/pages/onboarding/OnboardingExtension.tsx index 8ee85be7..c3fa5380 100644 --- a/src/pages/onboarding/OnboardingExtension.tsx +++ b/src/pages/onboarding/OnboardingExtension.tsx @@ -1,14 +1,64 @@ +import { ReactNode } from "react"; import { useNavigate } from "react-router-dom"; +import { useAsyncFn, useInterval } from "react-use"; +import { isAllowedExtensionVersion } from "@/backend/extension/compatibility"; +import { extensionInfo } from "@/backend/extension/messaging"; import { Button } from "@/components/buttons/Button"; 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 { useRedirectBack } from "@/pages/onboarding/onboardingHooks"; import { PageTitle } from "@/pages/parts/util/PageTitle"; +type ExtensionStatus = + | "unknown" + | "failed" + | "disallowed" + | "noperms" + | "outdated" + | "success"; + +async function getExtensionState(): Promise { + 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 +} + +export function ExtensionStatus(props: { + status: ExtensionStatus; + loading: boolean; +}) { + let content: ReactNode = null; + if (props.loading || props.status === "unknown") + content =

waiting on extension...

; + if (props.status === "disallowed") + content =

Extension disabled for this page

; + else if (props.status === "failed") content =

Failed to request status

; + else if (props.status === "outdated") content =

Extension too old

; + else if (props.status === "noperms") content =

No permissions to act

; + else if (props.status === "success") content =

Extension is working!

; + return
{content}
; +} + export function OnboardingExtensionPage() { const navigate = useNavigate(); + const { completeAndRedirect } = useRedirectBack(); + + const [{ loading, value }, exec] = useAsyncFn( + async (triggeredManually: boolean = false) => { + const status = await getExtensionState(); + if (status === "success" && triggeredManually) completeAndRedirect(); + return status; + }, + [completeAndRedirect], + ); + useInterval(exec, 1000); return ( @@ -17,9 +67,10 @@ export function OnboardingExtensionPage() { Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum + - diff --git a/src/pages/onboarding/OnboardingProxy.tsx b/src/pages/onboarding/OnboardingProxy.tsx index 45d22aea..0cb2b38b 100644 --- a/src/pages/onboarding/OnboardingProxy.tsx +++ b/src/pages/onboarding/OnboardingProxy.tsx @@ -1,14 +1,33 @@ +import { useState } from "react"; import { useNavigate } from "react-router-dom"; +import { useAsyncFn } from "react-use"; +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 { Heading2, Paragraph } from "@/components/utils/Text"; import { MinimalPageLayout } from "@/pages/layouts/MinimalPageLayout"; +import { useRedirectBack } from "@/pages/onboarding/onboardingHooks"; import { PageTitle } from "@/pages/parts/util/PageTitle"; +import { useAuthStore } from "@/stores/auth"; + +const testUrl = "https://postman-echo.com/get"; export function OnboardingProxyPage() { const navigate = useNavigate(); + const { completeAndRedirect } = useRedirectBack(); + const [url, setUrl] = useState(""); + const setProxySet = useAuthStore((s) => s.setProxySet); + + const [{ loading, error }, test] = useAsyncFn(async () => { + if (!url.startsWith("http")) throw new Error("Not a valid URL"); + const res = await singularProxiedFetch(url, testUrl, {}); + if (res.url !== testUrl) throw new Error("Not a proxy"); + setProxySet([url]); + completeAndRedirect(); + }, [url, completeAndRedirect, setProxySet]); return ( @@ -17,10 +36,12 @@ export function OnboardingProxyPage() { Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum - - + ); diff --git a/src/pages/onboarding/onboardingHooks.ts b/src/pages/onboarding/onboardingHooks.ts index e80234e7..bcbbea48 100644 --- a/src/pages/onboarding/onboardingHooks.ts +++ b/src/pages/onboarding/onboardingHooks.ts @@ -7,16 +7,16 @@ import { useOnboardingStore } from "@/stores/onboarding"; export function useRedirectBack() { const [url] = useQueryParam("redirect"); const navigate = useNavigate(); - const setSkipped = useOnboardingStore((s) => s.setSkipped); + const setCompleted = useOnboardingStore((s) => s.setCompleted); const redirectBack = useCallback(() => { navigate(url ?? "/"); }, [navigate, url]); - const skipAndRedirect = useCallback(() => { - setSkipped(true); + const completeAndRedirect = useCallback(() => { + setCompleted(true); redirectBack(); - }, [redirectBack, setSkipped]); + }, [redirectBack, setCompleted]); - return { redirectBack, skipAndRedirect }; + return { completeAndRedirect }; } diff --git a/src/stores/onboarding/index.tsx b/src/stores/onboarding/index.tsx index 17d1965d..be5af563 100644 --- a/src/stores/onboarding/index.tsx +++ b/src/stores/onboarding/index.tsx @@ -3,17 +3,17 @@ import { persist } from "zustand/middleware"; import { immer } from "zustand/middleware/immer"; export interface OnboardingStore { - skipped: boolean; - setSkipped(v: boolean): void; + completed: boolean; + setCompleted(v: boolean): void; } export const useOnboardingStore = create( persist( immer((set) => ({ - skipped: false, - setSkipped(v) { + completed: false, + setCompleted(v) { set((s) => { - s.skipped = v; + s.completed = v; }); }, })), diff --git a/src/utils/onboarding.ts b/src/utils/onboarding.ts index 7289fd1c..c2678b1c 100644 --- a/src/utils/onboarding.ts +++ b/src/utils/onboarding.ts @@ -15,9 +15,9 @@ export async function needsOnboarding(): Promise { const proxyUrls = useAuthStore.getState().proxySet; if (proxyUrls) return false; - // if onboarding has been skipped, no onboarding needed - const skipped = useOnboardingStore.getState().skipped; - if (skipped) return false; + // if onboarding has been completed, no onboarding needed + const completed = useOnboardingStore.getState().completed; + if (completed) return false; return true; } From 965cc56570424e4929ff0754b5d9ff731ceebc84 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Thu, 18 Jan 2024 19:21:43 +0100 Subject: [PATCH 032/151] Fix bug where stream freezes without extension Co-authored-by: Jip Frijlink --- src/hooks/useProviderScrape.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hooks/useProviderScrape.tsx b/src/hooks/useProviderScrape.tsx index d6b48063..fd27c06d 100644 --- a/src/hooks/useProviderScrape.tsx +++ b/src/hooks/useProviderScrape.tsx @@ -5,6 +5,7 @@ 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, @@ -186,7 +187,8 @@ export function useScrape() { discoverEmbeds: discoverEmbedsEvent, }, }); - if (output) await prepareStream(output.stream); + if (output && isExtensionActiveCached()) + await prepareStream(output.stream); return getResult(output); }, [ From 3b2be31691edd47f7cf9d07e5d79b9845733ce43 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Thu, 18 Jan 2024 19:22:39 +0100 Subject: [PATCH 033/151] Add thumbnail generation as a setting Co-authored-by: Jip Frijlink --- src/components/player/base/Container.tsx | 4 +++- src/hooks/useSettingsState.ts | 16 ++++++++++++- src/pages/Settings.tsx | 15 +++++++++--- .../{LocalePart.tsx => PreferencesPart.tsx} | 7 +++++- src/stores/preferences/index.tsx | 24 +++++++++++++++++++ 5 files changed, 60 insertions(+), 6 deletions(-) rename src/pages/parts/settings/{LocalePart.tsx => PreferencesPart.tsx} (83%) create mode 100644 src/stores/preferences/index.tsx diff --git a/src/components/player/base/Container.tsx b/src/components/player/base/Container.tsx index 9fc10bff..a4310ad8 100644 --- a/src/components/player/base/Container.tsx +++ b/src/components/player/base/Container.tsx @@ -11,6 +11,7 @@ import { VideoClickTarget } from "@/components/player/internals/VideoClickTarget import { VideoContainer } from "@/components/player/internals/VideoContainer"; import { PlayerHoverState } from "@/stores/player/slices/interface"; import { usePlayerStore } from "@/stores/player/store"; +import { usePreferencesStore } from "@/stores/preferences"; export interface PlayerProps { children?: ReactNode; @@ -78,6 +79,7 @@ function BaseContainer(props: { children?: ReactNode }) { export function Container(props: PlayerProps) { const propRef = useRef(props.onLoad); + const enableThumbnails = usePreferencesStore((s) => s.enableThumbnails); useEffect(() => { propRef.current?.(); }, []); @@ -86,7 +88,7 @@ export function Container(props: PlayerProps) {
- + {enableThumbnails ? : null} diff --git a/src/hooks/useSettingsState.ts b/src/hooks/useSettingsState.ts index 01d76610..d0946deb 100644 --- a/src/hooks/useSettingsState.ts +++ b/src/hooks/useSettingsState.ts @@ -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, + }, }; } diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx index 0fb27d85..18b755ca 100644 --- a/src/pages/Settings.tsx +++ b/src/pages/Settings.tsx @@ -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() { )}
-
- +
diff --git a/src/pages/parts/settings/LocalePart.tsx b/src/pages/parts/settings/PreferencesPart.tsx similarity index 83% rename from src/pages/parts/settings/LocalePart.tsx rename to src/pages/parts/settings/PreferencesPart.tsx index 87819451..ea06db6f 100644 --- a/src/pages/parts/settings/LocalePart.tsx +++ b/src/pages/parts/settings/PreferencesPart.tsx @@ -6,9 +6,11 @@ import { Heading1 } from "@/components/utils/Text"; import { appLanguageOptions } from "@/setup/i18n"; import { getLocaleInfo, sortLangCodes } from "@/utils/language"; -export function LocalePart(props: { +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)); @@ -39,6 +41,9 @@ export function LocalePart(props: { selectedItem={selected || options[0]} setSelectedItem={(opt) => props.setLanguage(opt.id)} /> +

props.setEnableThumbnails(!props.enableThumbnails)}> + thumbnails: {props.enableThumbnails.toString()} +

); } diff --git a/src/stores/preferences/index.tsx b/src/stores/preferences/index.tsx new file mode 100644 index 00000000..65fae22d --- /dev/null +++ b/src/stores/preferences/index.tsx @@ -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((set) => ({ + enableThumbnails: false, + setEnableThumbnails(v) { + set((s) => { + s.enableThumbnails = v; + }); + }, + })), + { + name: "__MW::preferences", + }, + ), +); From dc95bd7455adc85a3ef9fe7ee986c18b9486150f Mon Sep 17 00:00:00 2001 From: mrjvs Date: Thu, 18 Jan 2024 19:22:55 +0100 Subject: [PATCH 034/151] Add full layout and styling for the first step in onboarding Co-authored-by: Jip Frijlink --- src/components/layout/Stepper.tsx | 4 +- src/components/layout/ThinContainer.tsx | 2 +- src/pages/onboarding/Onboarding.tsx | 67 ++++++++++++++++++++++--- src/pages/onboarding/utils.tsx | 59 ++++++++++++++++++++++ themes/default.ts | 14 ++++++ 5 files changed, 137 insertions(+), 9 deletions(-) create mode 100644 src/pages/onboarding/utils.tsx diff --git a/src/components/layout/Stepper.tsx b/src/components/layout/Stepper.tsx index d0c9c499..867a438c 100644 --- a/src/components/layout/Stepper.tsx +++ b/src/components/layout/Stepper.tsx @@ -12,9 +12,9 @@ export function Stepper(props: StepperProps) {

{props.current}/{props.steps}

-
+
-
{props.children}
+
{props.children}
); } diff --git a/src/pages/onboarding/Onboarding.tsx b/src/pages/onboarding/Onboarding.tsx index 3247a7ee..05879507 100644 --- a/src/pages/onboarding/Onboarding.tsx +++ b/src/pages/onboarding/Onboarding.tsx @@ -1,14 +1,24 @@ +import classNames from "classnames"; import { useNavigate } from "react-router-dom"; 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 { Heading2, Paragraph } from "@/components/utils/Text"; +import { Heading1, Heading2, Paragraph } from "@/components/utils/Text"; import { MinimalPageLayout } from "@/pages/layouts/MinimalPageLayout"; import { 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 ( +
+
+
+ ); +} + export function OnboardingPage() { const navigate = useNavigate(); const skipModal = useModal("skip"); @@ -20,7 +30,7 @@ export function OnboardingPage() { - Lorem ipsum + Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum - + */} ); diff --git a/src/pages/onboarding/utils.tsx b/src/pages/onboarding/utils.tsx new file mode 100644 index 00000000..eaf722b2 --- /dev/null +++ b/src/pages/onboarding/utils.tsx @@ -0,0 +1,59 @@ +import classNames from "classnames"; + +import { Icon, Icons } from "@/components/Icon"; +import { Heading2, Heading3, Paragraph } from "@/components/utils/Text"; + +export function Card(props: { + children: React.ReactNode; + onClick: () => void; +}) { + return ( +
+ {props.children} +
+ ); +} + +export function CardContent(props: { + title: string; + description: string; + subtitle: string; + colorClass: string; + children?: React.ReactNode; +}) { + return ( +
+
+ + + {props.subtitle} + + {props.title} + + {props.description} + +
+
{props.children}
+
+ ); +} + +export function Link(props: { children: React.ReactNode }) { + return ( + + {props.children} + + + ); +} diff --git a/themes/default.ts b/themes/default.ts index 7a010338..bf2510ff 100644 --- a/themes/default.ts +++ b/themes/default.ts @@ -228,10 +228,24 @@ export const defaultTheme = { } }, + // Utilities utils: { divider: tokens.ash.c300, }, + // Onboarding + onboarding: { + bar: tokens.shade.c400, + barFilled: tokens.purple.c300, + divider: tokens.shade.c200, + card: tokens.shade.c800, + cardHover: tokens.shade.c700, + border: tokens.shade.c600, + good: tokens.purple.c100, + best: tokens.semantic.yellow.c100, + link: tokens.purple.c100, + }, + // Error page errors: { card: tokens.shade.c800, From b3222b130fdc32bddae05a8b92db6cf1fb26d90a Mon Sep 17 00:00:00 2001 From: mrjvs Date: Thu, 18 Jan 2024 19:29:58 +0100 Subject: [PATCH 035/151] Fix some thumbnail scraping setting logic Co-authored-by: Jip Frijlink --- src/components/player/base/Container.tsx | 4 +--- src/components/player/hooks/useSourceSelection.ts | 7 ++++--- src/components/player/internals/ThumbnailScraper.tsx | 10 ++++++---- src/hooks/useProviderScrape.tsx | 3 ++- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/components/player/base/Container.tsx b/src/components/player/base/Container.tsx index a4310ad8..9fc10bff 100644 --- a/src/components/player/base/Container.tsx +++ b/src/components/player/base/Container.tsx @@ -11,7 +11,6 @@ import { VideoClickTarget } from "@/components/player/internals/VideoClickTarget import { VideoContainer } from "@/components/player/internals/VideoContainer"; import { PlayerHoverState } from "@/stores/player/slices/interface"; import { usePlayerStore } from "@/stores/player/store"; -import { usePreferencesStore } from "@/stores/preferences"; export interface PlayerProps { children?: ReactNode; @@ -79,7 +78,6 @@ function BaseContainer(props: { children?: ReactNode }) { export function Container(props: PlayerProps) { const propRef = useRef(props.onLoad); - const enableThumbnails = usePreferencesStore((s) => s.enableThumbnails); useEffect(() => { propRef.current?.(); }, []); @@ -88,7 +86,7 @@ export function Container(props: PlayerProps) {
- {enableThumbnails ? : null} + diff --git a/src/components/player/hooks/useSourceSelection.ts b/src/components/player/hooks/useSourceSelection.ts index 3016e332..3813fa9f 100644 --- a/src/components/player/hooks/useSourceSelection.ts +++ b/src/components/player/hooks/useSourceSelection.ts @@ -5,6 +5,7 @@ import { } from "@movie-web/providers"; import { useAsyncFn } from "react-use"; +import { isExtensionActiveCached } from "@/backend/extension/messaging"; import { prepareStream } from "@/backend/extension/streams"; import { connectServerSideEvents, @@ -72,7 +73,7 @@ export function useEmbedScraping( report([ scrapeSourceOutputToProviderMetric(meta, sourceId, null, "success", null), ]); - await prepareStream(result.stream[0]); + if (isExtensionActiveCached()) await prepareStream(result.stream[0]); setSourceId(sourceId); setCaption(null); setSource( @@ -133,7 +134,7 @@ export function useSourceScraping(sourceId: string | null, routerId: string) { ]); if (result.stream) { - await prepareStream(result.stream[0]); + if (isExtensionActiveCached()) await prepareStream(result.stream[0]); setCaption(null); setSource( convertRunoutputToSource({ stream: result.stream[0] }), @@ -190,7 +191,7 @@ export function useSourceScraping(sourceId: string | null, routerId: string) { ]); setSourceId(sourceId); setCaption(null); - await prepareStream(embedResult.stream[0]); + if (isExtensionActiveCached()) await prepareStream(embedResult.stream[0]); setSource( convertRunoutputToSource({ stream: embedResult.stream[0] }), convertProviderCaption(embedResult.stream[0].captions), diff --git a/src/components/player/internals/ThumbnailScraper.tsx b/src/components/player/internals/ThumbnailScraper.tsx index b0fc8474..cede84c8 100644 --- a/src/components/player/internals/ThumbnailScraper.tsx +++ b/src/components/player/internals/ThumbnailScraper.tsx @@ -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(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; } diff --git a/src/hooks/useProviderScrape.tsx b/src/hooks/useProviderScrape.tsx index fd27c06d..84aeec4e 100644 --- a/src/hooks/useProviderScrape.tsx +++ b/src/hooks/useProviderScrape.tsx @@ -171,7 +171,8 @@ export function useScrape() { conn.on("update", updateEvent); conn.on("discoverEmbeds", discoverEmbedsEvent); const sseOutput = await conn.promise(); - if (sseOutput) await prepareStream(sseOutput.stream); + if (sseOutput && isExtensionActiveCached()) + await prepareStream(sseOutput.stream); return getResult(sseOutput === "" ? null : sseOutput); } From 47d680da8a18662d3ec9fb2366284378a5fecf69 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Thu, 18 Jan 2024 20:37:27 +0100 Subject: [PATCH 036/151] Add some hover effects --- src/pages/onboarding/Onboarding.tsx | 4 ++-- src/pages/onboarding/utils.tsx | 14 +++++++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/pages/onboarding/Onboarding.tsx b/src/pages/onboarding/Onboarding.tsx index 05879507..3387f044 100644 --- a/src/pages/onboarding/Onboarding.tsx +++ b/src/pages/onboarding/Onboarding.tsx @@ -70,7 +70,7 @@ export function OnboardingPage() { navigate("/onboarding/extension")}> @@ -84,7 +84,7 @@ export function OnboardingPage() { use the default setup diff --git a/src/pages/onboarding/utils.tsx b/src/pages/onboarding/utils.tsx index eaf722b2..410875b7 100644 --- a/src/pages/onboarding/utils.tsx +++ b/src/pages/onboarding/utils.tsx @@ -1,4 +1,5 @@ import classNames from "classnames"; +import { ReactNode } from "react"; import { Icon, Icons } from "@/components/Icon"; import { Heading2, Heading3, Paragraph } from "@/components/utils/Text"; @@ -18,9 +19,9 @@ export function Card(props: { } export function CardContent(props: { - title: string; - description: string; - subtitle: string; + title: ReactNode; + description: ReactNode; + subtitle: ReactNode; colorClass: string; children?: React.ReactNode; }) { @@ -51,9 +52,12 @@ export function CardContent(props: { export function Link(props: { children: React.ReactNode }) { return ( - + {props.children} - + ); } From a362559d9c482e9fba843900adf11cc87b1e0180 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Fri, 19 Jan 2024 19:30:25 +0100 Subject: [PATCH 037/151] Add onboarding state to settings --- src/pages/parts/settings/ConnectionsPart.tsx | 2 + src/pages/parts/settings/SetupPart.tsx | 79 ++++++++++++++++++++ src/pages/parts/settings/SidebarPart.tsx | 4 +- 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 src/pages/parts/settings/SetupPart.tsx diff --git a/src/pages/parts/settings/ConnectionsPart.tsx b/src/pages/parts/settings/ConnectionsPart.tsx index 007a6220..8a01f2b3 100644 --- a/src/pages/parts/settings/ConnectionsPart.tsx +++ b/src/pages/parts/settings/ConnectionsPart.tsx @@ -8,6 +8,7 @@ import { SettingsCard } from "@/components/layout/SettingsCard"; 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; @@ -147,6 +148,7 @@ export function ConnectionsPart(props: BackendEditProps & ProxyEditProps) {
{t("settings.connections.title")}
+ ((resolve, reject) => { + setTimeout(() => reject(new Error("Timed out!")), 1000); + 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 => { + 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, + }; +} + +export function SetupPart() { + const navigate = useNavigate(); + const { loading, setupStates, globalState } = useIsSetup(); + if (loading || !setupStates) return

Loading states...

; + return ( +
+

state: {globalState}

+

extension: {setupStates.extension}

+

proxy: {setupStates.proxy}

+

defaults: {setupStates.defaultProxy}

+ +
+ ); +} diff --git a/src/pages/parts/settings/SidebarPart.tsx b/src/pages/parts/settings/SidebarPart.tsx index 2b6e5c3f..560d9e5a 100644 --- a/src/pages/parts/settings/SidebarPart.tsx +++ b/src/pages/parts/settings/SidebarPart.tsx @@ -45,8 +45,8 @@ export function SidebarPart() { }, { textKey: "settings.locale.title", - id: "settings-locale", - icon: Icons.BOOKMARK, + id: "settings-preferences", + icon: Icons.SETTINGS, }, { textKey: "settings.appearance.title", From 2ec854843909c921b9187c00de03e662084c7fcd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Jan 2024 22:14:25 +0000 Subject: [PATCH 038/151] Bump vite from 5.0.10 to 5.0.12 Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.0.10 to 5.0.12. - [Release notes](https://github.com/vitejs/vite/releases) - [Changelog](https://github.com/vitejs/vite/blob/v5.0.12/packages/vite/CHANGELOG.md) - [Commits](https://github.com/vitejs/vite/commits/v5.0.12/packages/vite) --- updated-dependencies: - dependency-name: vite dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- package.json | 2 +- pnpm-lock.yaml | 98 +++++++++++++++++++++++++++----------------------- 2 files changed, 55 insertions(+), 45 deletions(-) diff --git a/package.json b/package.json index 388054df..0f61bb0b 100644 --- a/package.json +++ b/package.json @@ -114,7 +114,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", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6d6bb9bd..7a7203ea 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -196,7 +196,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 +256,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.5) tailwind-scrollbar: specifier: ^3.0.5 version: 3.0.5(tailwindcss@3.4.0) @@ -273,20 +273,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) @@ -2033,7 +2033,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.5): resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==} engines: {node: '>= 10.0.0'} peerDependencies: @@ -2046,36 +2046,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.5) + rollup: /@rollup/wasm-node@4.9.5 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.5): 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.5) '@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.5 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.5): 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.5) magic-string: 0.25.9 - rollup: /@rollup/wasm-node@4.9.4 + rollup: /@rollup/wasm-node@4.9.5 dev: true - /@rollup/pluginutils@3.1.0(@rollup/wasm-node@4.9.4): + /@rollup/pluginutils@3.1.0(@rollup/wasm-node@4.9.5): resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} engines: {node: '>= 8.0.0'} peerDependencies: @@ -2084,7 +2084,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.5 dev: true /@rollup/wasm-node@4.9.4: @@ -2095,6 +2095,16 @@ packages: '@types/estree': 1.0.5 optionalDependencies: fsevents: 2.3.3 + dev: true + + /@rollup/wasm-node@4.9.5: + resolution: {integrity: sha512-Xhabb9BwobkC3NFnI9spB+AvHt+iXruRAtBZRlrCDaBnkT7hWUcSF+J+T/nW/qqqGKtYJ/1RzBRv6vCCxEIgpg==} + 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==} @@ -2452,7 +2462,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 +2473,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 @@ -5054,7 +5064,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.5 unplugin: 1.5.1 transitivePeerDependencies: - supports-color @@ -5976,7 +5986,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.5): resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==} deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser peerDependencies: @@ -5984,12 +5994,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.5 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.5): resolution: {integrity: sha512-exM0Ms2SN3AgTzMeW7y46neZQcyLY7eKwWAop1ZoRTCZwyrIRdMMJ6JjToAJbML77X/9N8ZEpmXG4Z/Clb9k8g==} engines: {node: '>=14'} hasBin: true @@ -6001,7 +6011,7 @@ packages: dependencies: open: 8.4.2 picomatch: 2.3.1 - rollup: /@rollup/wasm-node@4.9.4 + rollup: /@rollup/wasm-node@4.9.5 source-map: 0.7.4 yargs: 17.7.2 dev: true @@ -6849,7 +6859,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 +6871,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 +6917,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 +6943,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 +6960,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 +6994,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.5 optionalDependencies: fsevents: 2.3.3 dev: true @@ -7034,7 +7044,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 +7256,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.5) + '@rollup/plugin-node-resolve': 11.2.1(@rollup/wasm-node@4.9.5) + '@rollup/plugin-replace': 2.4.2(@rollup/wasm-node@4.9.5) '@surma/rollup-plugin-off-main-thread': 2.2.3 ajv: 8.12.0 common-tags: 1.8.2 @@ -7257,8 +7267,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.5 + rollup-plugin-terser: 7.0.2(@rollup/wasm-node@4.9.5) source-map: 0.8.0-beta.0 stringify-object: 3.3.0 strip-comments: 2.0.1 From bb147a1367a43203e35058c4d25cd61592009b1f Mon Sep 17 00:00:00 2001 From: mrjvs Date: Sat, 20 Jan 2024 00:24:06 +0100 Subject: [PATCH 039/151] Fixed flares --- src/components/utils/Flare.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/utils/Flare.tsx b/src/components/utils/Flare.tsx index 1fc20825..9c19e027 100644 --- a/src/components/utils/Flare.tsx +++ b/src/components/utils/Flare.tsx @@ -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) {
Date: Sat, 20 Jan 2024 11:18:16 +0100 Subject: [PATCH 040/151] Style onboarding pages Co-authored-by: William Oldham --- src/components/layout/Stepper.tsx | 2 +- src/components/text-inputs/AuthInputBox.tsx | 5 +- src/components/utils/ErrorLine.tsx | 18 +++++++ src/pages/onboarding/Onboarding.tsx | 8 ---- src/pages/onboarding/OnboardingExtension.tsx | 42 +++++++++++++---- src/pages/onboarding/OnboardingProxy.tsx | 49 +++++++++++++++----- src/pages/onboarding/utils.tsx | 34 ++++++++++++-- 7 files changed, 123 insertions(+), 35 deletions(-) create mode 100644 src/components/utils/ErrorLine.tsx diff --git a/src/components/layout/Stepper.tsx b/src/components/layout/Stepper.tsx index 867a438c..75dc150b 100644 --- a/src/components/layout/Stepper.tsx +++ b/src/components/layout/Stepper.tsx @@ -5,7 +5,7 @@ export interface StepperProps { } export function Stepper(props: StepperProps) { - const percentage = (props.current / (props.steps + 1)) * 100; + const percentage = (props.current / props.steps) * 100; return (
diff --git a/src/components/text-inputs/AuthInputBox.tsx b/src/components/text-inputs/AuthInputBox.tsx index c79c079d..2e34594a 100644 --- a/src/components/text-inputs/AuthInputBox.tsx +++ b/src/components/text-inputs/AuthInputBox.tsx @@ -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 ( -
+
{props.label ? (

{props.label}

) : null} diff --git a/src/components/utils/ErrorLine.tsx b/src/components/utils/ErrorLine.tsx new file mode 100644 index 00000000..b0761fee --- /dev/null +++ b/src/components/utils/ErrorLine.tsx @@ -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 ( +

+ + {props.children} +

+ ); +} diff --git a/src/pages/onboarding/Onboarding.tsx b/src/pages/onboarding/Onboarding.tsx index 3387f044..01e4631b 100644 --- a/src/pages/onboarding/Onboarding.tsx +++ b/src/pages/onboarding/Onboarding.tsx @@ -89,14 +89,6 @@ export function OnboardingPage() { use the default setup

- - {/* - - */} ); diff --git a/src/pages/onboarding/OnboardingExtension.tsx b/src/pages/onboarding/OnboardingExtension.tsx index c3fa5380..b2e98c83 100644 --- a/src/pages/onboarding/OnboardingExtension.tsx +++ b/src/pages/onboarding/OnboardingExtension.tsx @@ -5,11 +5,13 @@ import { useAsyncFn, useInterval } from "react-use"; import { isAllowedExtensionVersion } from "@/backend/extension/compatibility"; import { extensionInfo } from "@/backend/extension/messaging"; import { Button } from "@/components/buttons/Button"; +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 { useRedirectBack } from "@/pages/onboarding/onboardingHooks"; +import { Card, Link } from "@/pages/onboarding/utils"; import { PageTitle } from "@/pages/parts/util/PageTitle"; type ExtensionStatus = @@ -36,14 +38,25 @@ export function ExtensionStatus(props: { }) { let content: ReactNode = null; if (props.loading || props.status === "unknown") - content =

waiting on extension...

; + content = ( + <> + +

waiting on extension

+ + ); if (props.status === "disallowed") content =

Extension disabled for this page

; else if (props.status === "failed") content =

Failed to request status

; else if (props.status === "outdated") content =

Extension too old

; else if (props.status === "noperms") content =

No permissions to act

; else if (props.status === "success") content =

Extension is working!

; - return
{content}
; + return ( + +
+ {content} +
+
+ ); } export function OnboardingExtensionPage() { @@ -65,13 +78,26 @@ export function OnboardingExtensionPage() { - Lorem ipsum - Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum + + Let's start with an extension + + + Using the browser extension, you can get the best streams we have to + offer. With just a simple install. + + + Install extension + + - - +
+ + +
); diff --git a/src/pages/onboarding/OnboardingProxy.tsx b/src/pages/onboarding/OnboardingProxy.tsx index 0cb2b38b..be001de6 100644 --- a/src/pages/onboarding/OnboardingProxy.tsx +++ b/src/pages/onboarding/OnboardingProxy.tsx @@ -7,9 +7,12 @@ 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 { MinimalPageLayout } from "@/pages/layouts/MinimalPageLayout"; import { useRedirectBack } from "@/pages/onboarding/onboardingHooks"; +import { Link } from "@/pages/onboarding/utils"; import { PageTitle } from "@/pages/parts/util/PageTitle"; import { useAuthStore } from "@/stores/auth"; @@ -23,10 +26,14 @@ export function OnboardingProxyPage() { const [{ loading, error }, test] = useAsyncFn(async () => { if (!url.startsWith("http")) throw new Error("Not a valid URL"); - const res = await singularProxiedFetch(url, testUrl, {}); - if (res.url !== testUrl) throw new Error("Not a proxy"); - setProxySet([url]); - completeAndRedirect(); + try { + const res = await singularProxiedFetch(url, testUrl, {}); + if (res.url !== testUrl) throw new Error("Not a proxy"); + setProxySet([url]); + completeAndRedirect(); + } catch (e) { + throw new Error("Could not connect to proxy"); + } }, [url, completeAndRedirect, setProxySet]); return ( @@ -34,14 +41,32 @@ export function OnboardingProxyPage() { - Lorem ipsum - Lorem ipsum Lorem ipsum Lorem ipsum Lorem ipsum - - {error ?

url invalid

: null} - - + + Let's setup a custom proxy + + + Using a custom proxy, you can get great quality streams! + + Learn how to make a custom proxy +
+ + {error ? {error.message} : null} +
+ +
+ + +
); diff --git a/src/pages/onboarding/utils.tsx b/src/pages/onboarding/utils.tsx index 410875b7..e8129230 100644 --- a/src/pages/onboarding/utils.tsx +++ b/src/pages/onboarding/utils.tsx @@ -1,16 +1,22 @@ 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; - onClick: () => void; + children?: React.ReactNode; + onClick?: () => void; }) { return (
{props.children} @@ -50,9 +56,27 @@ export function CardContent(props: { ); } -export function Link(props: { children: React.ReactNode }) { +export function Link(props: { + children?: React.ReactNode; + to?: string; + href?: string; + className?: string; + target?: "_blank"; +}) { + const navigate = useNavigate(); return ( - + { + 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} Date: Sat, 20 Jan 2024 11:53:24 +0100 Subject: [PATCH 041/151] Localize all onboarding screens --- src/assets/locales/en.json | 62 +++++++++++++++++++- src/pages/onboarding/Onboarding.tsx | 51 ++++++++-------- src/pages/onboarding/OnboardingExtension.tsx | 37 ++++++++---- src/pages/onboarding/OnboardingProxy.tsx | 28 +++++---- 4 files changed, 128 insertions(+), 50 deletions(-) diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index 9329ec0e..77ac5aab 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -97,7 +97,8 @@ "login": "Login", "pagetitle": "{{title}} - movie-web", "register": "Register", - "settings": "Settings" + "settings": "Settings", + "onboarding": "Setup" } }, "home": { @@ -429,5 +430,64 @@ } }, "unsaved": "You have unsaved changes" + }, + "onboarding": { + "start": { + "title": "Let's get you setup with movie-web", + "explainer": "To get the best streams possible. You will need to choose which streaming method you want to use.", + "options": { + "proxy": { + "quality": "Good quality", + "title": "Custom proxy", + "description": "Setup a proxy in just 5 minutes and gain access to great sources.", + "action": "Setup proxy" + }, + "extension": { + "quality": "Best quality", + "title": "Browser extension", + "description": "Install browser extension and gain access to the best sources.", + "action": "Install extension" + }, + "default": { + "text": "I don't want good quality streams,<0 /> <1>use the default setup" + } + } + }, + "proxy": { + "title": "Let's make a new proxy", + "explainer": "With the proxy method, you can get great quality streams by making a self-service proxy.", + "link": "Learn how to make a proxy", + "input": { + "label": "Proxy URL", + "placeholder": "https://", + "errorInvalidUrl": "Not a valid URL", + "errorConnection": "Could not connect to proxy", + "errorNotProxy": "Expected a proxy but got a website" + }, + "back": "Go back", + "submit": "Submit proxy" + }, + "extension": { + "title": "Let's start with an extension", + "explainer": "Using the browser extension, you can get the best streams we have to offer. With just a simple install.", + "link": "Install extension", + "back": "Go back", + "status": { + "loading": "Waiting on extension", + "disallowed": "Extension disabled for this page", + "failed": "Failed to request status", + "outdated": "Extension version too old", + "noperms": "Extension does not have sufficient permissions", + "success": "Extension is working as expected!" + }, + "submitCheck": "Check for extension", + "submitFinal": "Continue" + }, + "defaultConfirm": { + "title": "Are you sure?", + "description": "The default setup does not have the best streams and can be unbearably slow.", + "cancel": "Cancel", + "confirm": "Use default setup" + } } } diff --git a/src/pages/onboarding/Onboarding.tsx b/src/pages/onboarding/Onboarding.tsx index 01e4631b..0d1e5a06 100644 --- a/src/pages/onboarding/Onboarding.tsx +++ b/src/pages/onboarding/Onboarding.tsx @@ -1,4 +1,5 @@ import classNames from "classnames"; +import { Trans, useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; import { Button } from "@/components/buttons/Button"; @@ -23,20 +24,23 @@ export function OnboardingPage() { const navigate = useNavigate(); const skipModal = useModal("skip"); const { completeAndRedirect } = useRedirectBack(); + const { t } = useTranslation(); return ( - + - Lorem ipsum - Lorem ipsum Lorem ipsum Lorem ipsum + + {t("onboarding.defaultConfirm.title")} + + {t("onboarding.defaultConfirm.description")} @@ -44,22 +48,21 @@ export function OnboardingPage() { - Let's get you set up with movie-web + {t("onboarding.start.title")} - To get the best streams possible, you will need to choose which - streaming method you want to use. + {t("onboarding.start.explainer")}
navigate("/onboarding/proxy")}> - Set up proxy + {t("onboarding.start.options.proxy.action")}
@@ -70,24 +73,24 @@ export function OnboardingPage() { navigate("/onboarding/extension")}> - Install extension + {t("onboarding.start.options.extension.action")}

- I don't want good quality,
-
- use the default setup - + +
+ +

diff --git a/src/pages/onboarding/OnboardingExtension.tsx b/src/pages/onboarding/OnboardingExtension.tsx index b2e98c83..ce699884 100644 --- a/src/pages/onboarding/OnboardingExtension.tsx +++ b/src/pages/onboarding/OnboardingExtension.tsx @@ -1,4 +1,5 @@ import { ReactNode } from "react"; +import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; import { useAsyncFn, useInterval } from "react-use"; @@ -36,20 +37,26 @@ export function ExtensionStatus(props: { status: ExtensionStatus; loading: boolean; }) { + const { t } = useTranslation(); + let content: ReactNode = null; if (props.loading || props.status === "unknown") content = ( <> -

waiting on extension

+

{t("onboarding.extension.status.loading")}

); if (props.status === "disallowed") - content =

Extension disabled for this page

; - else if (props.status === "failed") content =

Failed to request status

; - else if (props.status === "outdated") content =

Extension too old

; - else if (props.status === "noperms") content =

No permissions to act

; - else if (props.status === "success") content =

Extension is working!

; + content =

{t("onboarding.extension.status.disallowed")}

; + else if (props.status === "failed") + content =

{t("onboarding.extension.status.failed")}

; + else if (props.status === "outdated") + content =

{t("onboarding.extension.status.outdated")}

; + else if (props.status === "noperms") + content =

{t("onboarding.extension.status.noperms")}

; + else if (props.status === "success") + content =

{t("onboarding.extension.status.success")}

; return (
@@ -60,6 +67,7 @@ export function ExtensionStatus(props: { } export function OnboardingExtensionPage() { + const { t } = useTranslation(); const navigate = useNavigate(); const { completeAndRedirect } = useRedirectBack(); @@ -75,27 +83,30 @@ export function OnboardingExtensionPage() { return ( - + - Let's start with an extension + {t("onboarding.extension.title")} - Using the browser extension, you can get the best streams we have to - offer. With just a simple install. + {t("onboarding.extension.explainer")} - Install extension + {t("onboarding.extension.link")}
diff --git a/src/pages/onboarding/OnboardingProxy.tsx b/src/pages/onboarding/OnboardingProxy.tsx index be001de6..24595568 100644 --- a/src/pages/onboarding/OnboardingProxy.tsx +++ b/src/pages/onboarding/OnboardingProxy.tsx @@ -1,4 +1,5 @@ import { useState } from "react"; +import { useTranslation } from "react-i18next"; import { useNavigate } from "react-router-dom"; import { useAsyncFn } from "react-use"; @@ -19,52 +20,55 @@ import { useAuthStore } from "@/stores/auth"; const testUrl = "https://postman-echo.com/get"; export function OnboardingProxyPage() { + const { t } = useTranslation(); const navigate = useNavigate(); const { completeAndRedirect } = useRedirectBack(); const [url, setUrl] = useState(""); const setProxySet = useAuthStore((s) => s.setProxySet); const [{ loading, error }, test] = useAsyncFn(async () => { - if (!url.startsWith("http")) throw new Error("Not a valid URL"); + 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("Not a proxy"); + if (res.url !== testUrl) + throw new Error("onboarding.proxy.input.errorNotProxy"); setProxySet([url]); completeAndRedirect(); } catch (e) { - throw new Error("Could not connect to proxy"); + throw new Error("onboarding.proxy.input.errorConnection"); } }, [url, completeAndRedirect, setProxySet]); return ( - + - Let's setup a custom proxy + {t("onboarding.proxy.title")} - Using a custom proxy, you can get great quality streams! + {t("onboarding.proxy.explainer")} - Learn how to make a custom proxy + {t("onboarding.proxy.link")}
- {error ? {error.message} : null} + {error ? {t(error.message)} : null}
From de5d47a7302e41c782263e7b40a7f487a1631986 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Sat, 20 Jan 2024 12:24:02 +0100 Subject: [PATCH 042/151] Theme skip setup card --- src/components/overlays/Modal.tsx | 2 +- src/pages/onboarding/Onboarding.tsx | 16 +++++++++------- themes/default.ts | 5 +++++ themes/list/blue.ts | 4 ++++ themes/list/gray.ts | 4 ++++ themes/list/red.ts | 4 ++++ themes/list/teal.ts | 4 ++++ 7 files changed, 31 insertions(+), 8 deletions(-) diff --git a/src/components/overlays/Modal.tsx b/src/components/overlays/Modal.tsx index fc2c97f4..08abdbba 100644 --- a/src/components/overlays/Modal.tsx +++ b/src/components/overlays/Modal.tsx @@ -19,7 +19,7 @@ export function useModal(id: string) { export function ModalCard(props: { children?: ReactNode }) { return (
-
+
{props.children}
diff --git a/src/pages/onboarding/Onboarding.tsx b/src/pages/onboarding/Onboarding.tsx index 0d1e5a06..f5bf1758 100644 --- a/src/pages/onboarding/Onboarding.tsx +++ b/src/pages/onboarding/Onboarding.tsx @@ -31,18 +31,20 @@ export function OnboardingPage() { - - - {t("onboarding.defaultConfirm.title")} - - {t("onboarding.defaultConfirm.description")} + + {t("onboarding.defaultConfirm.title")} + + + {t("onboarding.defaultConfirm.description")} + +
- - +
diff --git a/themes/default.ts b/themes/default.ts index bf2510ff..dfda2d86 100644 --- a/themes/default.ts +++ b/themes/default.ts @@ -137,6 +137,11 @@ export const defaultTheme = { accentA: tokens.purple.c500, accentB: tokens.blue.c500, }, + + // Modals + modal: { + background: tokens.shade.c800, + }, // typography type: { diff --git a/themes/list/blue.ts b/themes/list/blue.ts index e5b73409..e10592dc 100644 --- a/themes/list/blue.ts +++ b/themes/list/blue.ts @@ -95,6 +95,10 @@ export default createTheme({ accentB: tokens.blue.c500 }, + modal: { + background: tokens.shade.c800, + }, + type: { logo: tokens.purple.c100, text: tokens.shade.c50, diff --git a/themes/list/gray.ts b/themes/list/gray.ts index a0b9b742..c0c434e8 100644 --- a/themes/list/gray.ts +++ b/themes/list/gray.ts @@ -95,6 +95,10 @@ export default createTheme({ accentB: tokens.blue.c500 }, + modal: { + background: tokens.shade.c800, + }, + type: { logo: tokens.purple.c100, text: tokens.shade.c50, diff --git a/themes/list/red.ts b/themes/list/red.ts index 89614632..b42b935f 100644 --- a/themes/list/red.ts +++ b/themes/list/red.ts @@ -95,6 +95,10 @@ export default createTheme({ accentB: tokens.blue.c500 }, + modal: { + background: tokens.shade.c800, + }, + type: { logo: tokens.purple.c100, text: tokens.shade.c50, diff --git a/themes/list/teal.ts b/themes/list/teal.ts index cbae4748..742f4a32 100644 --- a/themes/list/teal.ts +++ b/themes/list/teal.ts @@ -95,6 +95,10 @@ export default createTheme({ accentB: tokens.blue.c500 }, + modal: { + background: tokens.shade.c800, + }, + type: { logo: tokens.purple.c100, text: tokens.shade.c50, From f96a0de373c81539f0db8ecf9a3fcb2598a5c6e3 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Sat, 20 Jan 2024 13:09:42 +0100 Subject: [PATCH 043/151] Style the settings onboarding card --- .../player/internals/ScrapeCard.tsx | 20 +-- .../player/internals/StatusCircle.tsx | 40 +++--- src/pages/parts/settings/SetupPart.tsx | 117 ++++++++++++++++-- themes/default.ts | 1 + 4 files changed, 145 insertions(+), 33 deletions(-) diff --git a/src/components/player/internals/ScrapeCard.tsx b/src/components/player/internals/ScrapeCard.tsx index 479bf2b1..dc057901 100644 --- a/src/components/player/internals/ScrapeCard.tsx +++ b/src/components/player/internals/ScrapeCard.tsx @@ -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> = { pending: "player.scraping.items.pending", }; -const statusMap: Record = { - failure: "error", - notfound: "noresult", - pending: "loading", - success: "success", - waiting: "waiting", -}; +const statusMap: Record = + { + failure: "error", + notfound: "noresult", + pending: "loading", + success: "success", + waiting: "waiting", + }; export function ScrapeItem(props: ScrapeItemProps) { const { t } = useTranslation(); diff --git a/src/components/player/internals/StatusCircle.tsx b/src/components/player/internals/StatusCircle.tsx index 32855321..ede7392e 100644 --- a/src/components/player/internals/StatusCircle.tsx +++ b/src/components/player/internals/StatusCircle.tsx @@ -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 (
diff --git a/src/pages/parts/settings/SetupPart.tsx b/src/pages/parts/settings/SetupPart.tsx index f639b43b..478722c6 100644 --- a/src/pages/parts/settings/SetupPart.tsx +++ b/src/pages/parts/settings/SetupPart.tsx @@ -1,9 +1,19 @@ +import classNames from "classnames"; +import { t } from "i18next"; +import { ReactNode } from "react"; 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 { 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"; @@ -63,17 +73,110 @@ function useIsSetup() { }; } +function SetupCheckList(props: { + status: Status; + grey?: boolean; + children?: ReactNode; +}) { + const statusMap: Record = { + error: "error", + success: "success", + unset: "noresult", + }; + + return ( +
+ +
+

+ {props.children} +

+ {props.status === "error" ? ( +

+ There is something wrong with this setting. Go through setup again + to fix it. +

+ ) : null} +
+
+ ); +} + export function SetupPart() { const navigate = useNavigate(); const { loading, setupStates, globalState } = useIsSetup(); if (loading || !setupStates) return

Loading states...

; + + const textLookupMap: Record = { + error: { + title: "err1", + desc: "err2", + }, + success: { + title: "success1", + desc: "success2", + }, + unset: { + title: "unset1", + desc: "unset2", + }, + }; + return ( -
-

state: {globalState}

-

extension: {setupStates.extension}

-

proxy: {setupStates.proxy}

-

defaults: {setupStates.defaultProxy}

- -
+ +
+
+
+ +
+
+
+ + {t(textLookupMap[globalState].title)} + +

+ {t(textLookupMap[globalState].desc)} +

+ + Extension + + + Custom proxy + + + Default setup + +
+
+ +
+
+
); } diff --git a/themes/default.ts b/themes/default.ts index dfda2d86..bd31b3ff 100644 --- a/themes/default.ts +++ b/themes/default.ts @@ -152,6 +152,7 @@ export const defaultTheme = { divider: tokens.ash.c500, secondary: tokens.ash.c100, danger: tokens.semantic.red.c100, + success: tokens.semantic.green.c100, link: tokens.purple.c100, linkHover: tokens.purple.c50, }, From 741a35dee8b9468a01251addd08275f41cd8af6f Mon Sep 17 00:00:00 2001 From: mrjvs Date: Sat, 20 Jan 2024 13:20:06 +0100 Subject: [PATCH 044/151] Style and localize the preference section of settings --- src/assets/locales/en.json | 7 ++- src/components/buttons/Toggle.tsx | 2 +- src/pages/parts/settings/PreferencesPart.tsx | 50 +++++++++++++------- src/pages/parts/settings/SidebarPart.tsx | 2 +- 4 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index 77ac5aab..845d2756 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -408,10 +408,13 @@ "urlPlaceholder": "https://" } }, - "locale": { + "preferences": { "language": "Application language", "languageDescription": "Language applied to the entire application.", - "title": "Locale" + "title": "Preferences", + "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" }, "reset": "Reset", "save": "Save", diff --git a/src/components/buttons/Toggle.tsx b/src/components/buttons/Toggle.tsx index 3fcb0071..8cedc245 100644 --- a/src/components/buttons/Toggle.tsx +++ b/src/components/buttons/Toggle.tsx @@ -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 (
From e4ad8789b9309509104e3fd0b381d05b2a50ceb9 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Sat, 20 Jan 2024 13:54:32 +0100 Subject: [PATCH 047/151] Add todos and fix some highlights --- src/pages/onboarding/OnboardingExtension.tsx | 2 ++ src/pages/onboarding/OnboardingProxy.tsx | 1 + src/pages/parts/settings/SetupPart.tsx | 14 ++++++++++---- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/pages/onboarding/OnboardingExtension.tsx b/src/pages/onboarding/OnboardingExtension.tsx index ce699884..ffa4bc84 100644 --- a/src/pages/onboarding/OnboardingExtension.tsx +++ b/src/pages/onboarding/OnboardingExtension.tsx @@ -47,6 +47,7 @@ export function ExtensionStatus(props: {

{t("onboarding.extension.status.loading")}

); + // TODO make proper actions for all of these states below if (props.status === "disallowed") content =

{t("onboarding.extension.status.disallowed")}

; else if (props.status === "failed") @@ -81,6 +82,7 @@ export function OnboardingExtensionPage() { ); useInterval(exec, 1000); + // TODO proper link to install extension return ( diff --git a/src/pages/onboarding/OnboardingProxy.tsx b/src/pages/onboarding/OnboardingProxy.tsx index 24595568..1d3b6b7c 100644 --- a/src/pages/onboarding/OnboardingProxy.tsx +++ b/src/pages/onboarding/OnboardingProxy.tsx @@ -40,6 +40,7 @@ export function OnboardingProxyPage() { } }, [url, completeAndRedirect, setProxySet]); + // TODO proper link to proxy deployment docs return ( diff --git a/src/pages/parts/settings/SetupPart.tsx b/src/pages/parts/settings/SetupPart.tsx index e9508d48..074f920d 100644 --- a/src/pages/parts/settings/SetupPart.tsx +++ b/src/pages/parts/settings/SetupPart.tsx @@ -76,6 +76,7 @@ function useIsSetup() { function SetupCheckList(props: { status: Status; grey?: boolean; + highlight?: boolean; children?: ReactNode; }) { const { t } = useTranslation(); @@ -98,9 +99,10 @@ function SetupCheckList(props: {

{props.children} @@ -119,7 +121,7 @@ export function SetupPart() { const { t } = useTranslation(); const navigate = useNavigate(); const { loading, setupStates, globalState } = useIsSetup(); - if (loading || !setupStates) return

Loading states...

; + if (loading || !setupStates) return

Loading states...

; // TODO proper loading screen const textLookupMap: Record< Status, @@ -174,7 +176,11 @@ export function SetupPart() { {t("settings.connections.setup.items.proxy")} - + {t("settings.connections.setup.items.default")}
From ad69c9381cd934fad459b07a923ae47015473966 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Sat, 20 Jan 2024 14:00:15 +0100 Subject: [PATCH 048/151] remove resolved TODO --- src/components/player/display/base.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/player/display/base.ts b/src/components/player/display/base.ts index 91f36722..481c1982 100644 --- a/src/components/player/display/base.ts +++ b/src/components/player/display/base.ts @@ -101,7 +101,6 @@ export function makeVideoElementDisplayInterface(): DisplayInterface { } function setupSource(vid: HTMLVideoElement, src: LoadableSource) { - // TODO: Add check whether the extension is installed if (src.type === "hls") { if (canPlayHlsNatively(vid)) { vid.src = processCdnLink(src.url); From ff045c95c77dfc57aa736928dee63dd3b75c15f1 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Sat, 20 Jan 2024 18:28:49 +0100 Subject: [PATCH 049/151] update provider package --- package.json | 2 +- pnpm-lock.yaml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index d4e8db77..c5dae16f 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "@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.0", "@noble/hashes": "^1.3.3", "@plasmohq/messaging": "^0.6.1", "@react-spring/web": "^9.7.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 34d4eea7..2fda1a32 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -22,8 +22,8 @@ dependencies: specifier: ^1.0.3 version: 1.0.3 '@movie-web/providers': - specifier: ^2.0.5 - version: 2.0.5 + specifier: ^2.1.0 + version: 2.1.0 '@noble/hashes': specifier: ^1.3.3 version: 1.3.3 @@ -1924,8 +1924,8 @@ packages: engines: {node: '>= 14'} dev: false - /@movie-web/providers@2.0.5: - resolution: {integrity: sha512-cefPTFXE7ctYeiibjk4HcNL3anRZ3lgYDAaJdzFzUrvkcSdxonP8GgGfDfPwmWWKip9dbP8Xv5aeauV/wrfaag==} + /@movie-web/providers@2.1.0: + resolution: {integrity: sha512-L7Nn5n1+0HNXha0A6bymJSGVLhyC4qd5S2r5Xk5FeqxMlqKBqOlMpUmfHiZOssog70sxTAvRfFqmKkM4UXV8kg==} dependencies: cheerio: 1.0.0-rc.12 crypto-js: 4.2.0 From 1918aa6d9b66e274a76bbee4613340c54102d2a1 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 20 Jan 2024 17:59:18 +0000 Subject: [PATCH 050/151] Extension should only be classed as active/valid when it's allowed on the domain --- src/backend/extension/messaging.ts | 2 +- src/pages/parts/player/MetaPart.tsx | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/backend/extension/messaging.ts b/src/backend/extension/messaging.ts index b738184a..1f2a2b00 100644 --- a/src/backend/extension/messaging.ts +++ b/src/backend/extension/messaging.ts @@ -67,5 +67,5 @@ export async function isExtensionActive(): Promise { if (!info?.success) return false; const allowedVersion = isAllowedExtensionVersion(info.version); if (!allowedVersion) return false; - return true; + return info.allowed && info.hasPermission; } diff --git a/src/pages/parts/player/MetaPart.tsx b/src/pages/parts/player/MetaPart.tsx index 1e18b6d1..17803219 100644 --- a/src/pages/parts/player/MetaPart.tsx +++ b/src/pages/parts/player/MetaPart.tsx @@ -46,11 +46,10 @@ export function MetaPart(props: MetaPartProps) { const { error, value, loading } = useAsync(async () => { const info = await extensionInfo(); const isValidExtension = - info?.success && isAllowedExtensionVersion(info.version); + info?.success && isAllowedExtensionVersion(info.version) && info.allowed; if (isValidExtension) { - if (!info.allowed || !info.hasPermission) - throw new Error("extension-no-permission"); + if (!info.hasPermission) throw new Error("extension-no-permission"); } // use api metadata or providers metadata From 9157220317ffe1baed51f4573274eaaad83fd579 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Sat, 20 Jan 2024 18:13:40 +0000 Subject: [PATCH 051/151] Add i81n strings for MetaPart --- src/assets/locales/en.json | 11 +++++++++++ src/pages/parts/player/MetaPart.tsx | 22 +++++++++------------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index 4db7eeaa..20ece967 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -277,6 +277,17 @@ "homeButton": "Back to home", "text": "We couldn't find the media you requested. Either it's been removed or you tampered with the URL.", "title": "Couldn't find that media." + }, + "extensionPermission": { + "badge": "Permission Missing", + "title": "Configure the extension", + "text": "You have the browser extension, but we need your permission to get started using the extension.", + "button": "Use extension" + }, + "dmca": { + "badge": "Removed", + "title": "Media has been removed", + "text": "This media is no longer available due to a takedown notice or copyright claim." } }, "nextEpisode": { diff --git a/src/pages/parts/player/MetaPart.tsx b/src/pages/parts/player/MetaPart.tsx index 17803219..1b84b7bf 100644 --- a/src/pages/parts/player/MetaPart.tsx +++ b/src/pages/parts/player/MetaPart.tsx @@ -116,13 +116,10 @@ export function MetaPart(props: MetaPartProps) { - {t("player.metadata.failed.badge")} + {t("player.metadata.extensionPermission.badge")} - Configure the extension - - You have the browser extension, but we need your permission to get - started using the extension. - + {t("player.metadata.extensionPermission.title")} + {t("player.metadata.extensionPermission.text")} @@ -145,12 +142,11 @@ export function MetaPart(props: MetaPartProps) { return ( - Removed - Media has been removed - - This media is no longer available due to a takedown notice or - copyright claim. - + + {t("player.metadata.dmca.badge")} + + {t("player.metadata.dmca.title")} + {t("player.metadata.dmca.text")} + + ); else if (props.status === "failed") content =

{t("onboarding.extension.status.failed")}

; else if (props.status === "outdated") content =

{t("onboarding.extension.status.outdated")}

; - else if (props.status === "noperms") - content =

{t("onboarding.extension.status.noperms")}

; else if (props.status === "success") - content =

{t("onboarding.extension.status.success")}

; + content = ( +

+ + {t("onboarding.extension.status.success")} +

+ ); return ( - -
- {content} -
-
+ <> + +
+ {content} +
+
+ +
+ +

+ , + }} + /> +

+
+
+ ); } @@ -103,13 +138,11 @@ export function OnboardingExtensionPage() { - + {value === "success" ? ( + + ) : null}
diff --git a/src/pages/onboarding/utils.tsx b/src/pages/onboarding/utils.tsx index e8129230..3a57952b 100644 --- a/src/pages/onboarding/utils.tsx +++ b/src/pages/onboarding/utils.tsx @@ -7,16 +7,20 @@ import { Heading2, Heading3, Paragraph } from "@/components/utils/Text"; export function Card(props: { children?: React.ReactNode; + className?: string; onClick?: () => void; }) { return (
{props.children} From 7a5a9fe6fb4193cd6d896ed4c12ba613d0ba509f Mon Sep 17 00:00:00 2001 From: mrjvs Date: Sun, 21 Jan 2024 15:33:01 +0100 Subject: [PATCH 054/151] Fix typo --- src/assets/locales/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/locales/en.json b/src/assets/locales/en.json index 29bf3647..15038d6f 100644 --- a/src/assets/locales/en.json +++ b/src/assets/locales/en.json @@ -512,7 +512,7 @@ "status": { "loading": "Waiting for you to install the extension", "disallowed": "Extension is not enabled for this page", - "disallowedAction": "Enabled extension", + "disallowedAction": "Enable extension", "failed": "Failed to request status", "outdated": "Extension version too old", "success": "Extension is working as expected!" From 6010c2bab00d78875616084e4e85a4cffb851f79 Mon Sep 17 00:00:00 2001 From: Mehdi Dara Date: Sun, 21 Jan 2024 21:28:10 +0330 Subject: [PATCH 055/151] =?UTF-8?q?=E2=9A=A1=20Backdrop=20blur=20for=20the?= =?UTF-8?q?=20navigation=20buttons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/LinksDropdown.tsx | 2 +- src/components/buttons/IconPatch.tsx | 2 +- src/components/layout/BrandPill.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/LinksDropdown.tsx b/src/components/LinksDropdown.tsx index 90be9a17..c0da66ee 100644 --- a/src/components/LinksDropdown.tsx +++ b/src/components/LinksDropdown.tsx @@ -109,7 +109,7 @@ export function LinksDropdown(props: { children: React.ReactNode }) { return (
evt.key === "Enter" && toggleOpen()} diff --git a/src/components/buttons/IconPatch.tsx b/src/components/buttons/IconPatch.tsx index 302d14b2..b9a7e525 100644 --- a/src/components/buttons/IconPatch.tsx +++ b/src/components/buttons/IconPatch.tsx @@ -25,7 +25,7 @@ export function IconPatch(props: IconPatchProps) { return (
diff --git a/src/components/layout/BrandPill.tsx b/src/components/layout/BrandPill.tsx index 814f90e6..109dbd2c 100644 --- a/src/components/layout/BrandPill.tsx +++ b/src/components/layout/BrandPill.tsx @@ -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" : "", )} > From 2064e42bcb387f0e4e1b21fb8a65426e5b3924e2 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Sun, 21 Jan 2024 20:31:34 +0100 Subject: [PATCH 056/151] handle errors for domain extraction --- src/backend/extension/streams.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/backend/extension/streams.ts b/src/backend/extension/streams.ts index 2afb900d..588718af 100644 --- a/src/backend/extension/streams.ts +++ b/src/backend/extension/streams.ts @@ -2,21 +2,23 @@ import { Stream } from "@movie-web/providers"; import { setDomainRule } from "@/backend/extension/messaging"; -function extractDomain(url: string): string { +function extractDomain(url: string): string | null { try { const u = new URL(url); return u.hostname; } catch { - return url; + return null; } } function extractDomainsFromStream(stream: Stream): string[] { if (stream.type === "hls") { - return [extractDomain(stream.playlist)]; + return [extractDomain(stream.playlist)].filter((v): v is string => !!v); } if (stream.type === "file") { - return Object.values(stream.qualities).map((v) => extractDomain(v.url)); + return Object.values(stream.qualities) + .map((v) => extractDomain(v.url)) + .filter((v): v is string => !!v); } return []; } From 20e35d05499936646d4055d91351af5502a39cc9 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Sun, 21 Jan 2024 20:33:49 +0100 Subject: [PATCH 057/151] fix linting problem --- src/components/player/atoms/settings/CaptionsView.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/player/atoms/settings/CaptionsView.tsx b/src/components/player/atoms/settings/CaptionsView.tsx index 09ab5685..92104f1b 100644 --- a/src/components/player/atoms/settings/CaptionsView.tsx +++ b/src/components/player/atoms/settings/CaptionsView.tsx @@ -134,7 +134,7 @@ export function CaptionsView({ id }: { id: string }) { [selectCaptionById, setCurrentlyDownloading], ); - const content = subtitleList.map((v, i) => { + const content = subtitleList.map((v) => { return ( Date: Sun, 21 Jan 2024 20:41:09 +0100 Subject: [PATCH 058/151] onboarding preserve params --- src/pages/onboarding/Onboarding.tsx | 8 +++++--- src/pages/onboarding/OnboardingExtension.tsx | 8 +++++--- src/pages/onboarding/OnboardingProxy.tsx | 8 +++++--- src/pages/onboarding/onboardingHooks.ts | 17 ++++++++++++++++- 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/pages/onboarding/Onboarding.tsx b/src/pages/onboarding/Onboarding.tsx index f5bf1758..525ed7df 100644 --- a/src/pages/onboarding/Onboarding.tsx +++ b/src/pages/onboarding/Onboarding.tsx @@ -1,6 +1,5 @@ import classNames from "classnames"; import { Trans, useTranslation } from "react-i18next"; -import { useNavigate } from "react-router-dom"; import { Button } from "@/components/buttons/Button"; import { Stepper } from "@/components/layout/Stepper"; @@ -8,7 +7,10 @@ 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 { useRedirectBack } from "@/pages/onboarding/onboardingHooks"; +import { + useNavigateOnboarding, + useRedirectBack, +} from "@/pages/onboarding/onboardingHooks"; import { Card, CardContent, Link } from "@/pages/onboarding/utils"; import { PageTitle } from "@/pages/parts/util/PageTitle"; @@ -21,7 +23,7 @@ function VerticalLine(props: { className?: string }) { } export function OnboardingPage() { - const navigate = useNavigate(); + const navigate = useNavigateOnboarding(); const skipModal = useModal("skip"); const { completeAndRedirect } = useRedirectBack(); const { t } = useTranslation(); diff --git a/src/pages/onboarding/OnboardingExtension.tsx b/src/pages/onboarding/OnboardingExtension.tsx index 75408f28..70472a1a 100644 --- a/src/pages/onboarding/OnboardingExtension.tsx +++ b/src/pages/onboarding/OnboardingExtension.tsx @@ -1,6 +1,5 @@ import { ReactNode } from "react"; import { Trans, useTranslation } from "react-i18next"; -import { useNavigate } from "react-router-dom"; import { useAsyncFn, useInterval } from "react-use"; import { isAllowedExtensionVersion } from "@/backend/extension/compatibility"; @@ -12,7 +11,10 @@ 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 { useRedirectBack } from "@/pages/onboarding/onboardingHooks"; +import { + useNavigateOnboarding, + useRedirectBack, +} from "@/pages/onboarding/onboardingHooks"; import { Card, Link } from "@/pages/onboarding/utils"; import { PageTitle } from "@/pages/parts/util/PageTitle"; @@ -104,7 +106,7 @@ export function ExtensionStatus(props: { export function OnboardingExtensionPage() { const { t } = useTranslation(); - const navigate = useNavigate(); + const navigate = useNavigateOnboarding(); const { completeAndRedirect } = useRedirectBack(); const [{ loading, value }, exec] = useAsyncFn( diff --git a/src/pages/onboarding/OnboardingProxy.tsx b/src/pages/onboarding/OnboardingProxy.tsx index 1d3b6b7c..e576779c 100644 --- a/src/pages/onboarding/OnboardingProxy.tsx +++ b/src/pages/onboarding/OnboardingProxy.tsx @@ -1,6 +1,5 @@ import { useState } from "react"; import { useTranslation } from "react-i18next"; -import { useNavigate } from "react-router-dom"; import { useAsyncFn } from "react-use"; import { singularProxiedFetch } from "@/backend/helpers/fetch"; @@ -12,7 +11,10 @@ import { Divider } from "@/components/utils/Divider"; import { ErrorLine } from "@/components/utils/ErrorLine"; import { Heading2, Paragraph } from "@/components/utils/Text"; import { MinimalPageLayout } from "@/pages/layouts/MinimalPageLayout"; -import { useRedirectBack } from "@/pages/onboarding/onboardingHooks"; +import { + useNavigateOnboarding, + useRedirectBack, +} from "@/pages/onboarding/onboardingHooks"; import { Link } from "@/pages/onboarding/utils"; import { PageTitle } from "@/pages/parts/util/PageTitle"; import { useAuthStore } from "@/stores/auth"; @@ -21,7 +23,7 @@ const testUrl = "https://postman-echo.com/get"; export function OnboardingProxyPage() { const { t } = useTranslation(); - const navigate = useNavigate(); + const navigate = useNavigateOnboarding(); const { completeAndRedirect } = useRedirectBack(); const [url, setUrl] = useState(""); const setProxySet = useAuthStore((s) => s.setProxySet); diff --git a/src/pages/onboarding/onboardingHooks.ts b/src/pages/onboarding/onboardingHooks.ts index bcbbea48..cccf8825 100644 --- a/src/pages/onboarding/onboardingHooks.ts +++ b/src/pages/onboarding/onboardingHooks.ts @@ -1,5 +1,5 @@ import { useCallback } from "react"; -import { useNavigate } from "react-router-dom"; +import { useLocation, useNavigate } from "react-router-dom"; import { useQueryParam } from "@/hooks/useQueryParams"; import { useOnboardingStore } from "@/stores/onboarding"; @@ -20,3 +20,18 @@ export function useRedirectBack() { 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; +} From e758f32483affc4e92173f49095343e90595ef80 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Tue, 23 Jan 2024 19:48:23 +0100 Subject: [PATCH 059/151] Add loading screen for SetupPart checks --- src/pages/parts/settings/SetupPart.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/pages/parts/settings/SetupPart.tsx b/src/pages/parts/settings/SetupPart.tsx index 074f920d..d188c759 100644 --- a/src/pages/parts/settings/SetupPart.tsx +++ b/src/pages/parts/settings/SetupPart.tsx @@ -8,6 +8,7 @@ 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, @@ -121,7 +122,15 @@ export function SetupPart() { const { t } = useTranslation(); const navigate = useNavigate(); const { loading, setupStates, globalState } = useIsSetup(); - if (loading || !setupStates) return

Loading states...

; // TODO proper loading screen + if (loading || !setupStates) { + return ( + +
+ +
+
+ ); + } const textLookupMap: Record< Status, From dbaba7ff1886eac6d1cff0a0a48cb9b350a3abb9 Mon Sep 17 00:00:00 2001 From: mrjvs Date: Tue, 23 Jan 2024 19:57:05 +0100 Subject: [PATCH 060/151] Add configurable links to onboarding --- src/pages/onboarding/OnboardingExtension.tsx | 11 +++++++---- src/pages/onboarding/OnboardingProxy.tsx | 9 +++++++-- src/setup/config.ts | 14 ++++++++++++++ 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/pages/onboarding/OnboardingExtension.tsx b/src/pages/onboarding/OnboardingExtension.tsx index 70472a1a..3c17e3b8 100644 --- a/src/pages/onboarding/OnboardingExtension.tsx +++ b/src/pages/onboarding/OnboardingExtension.tsx @@ -17,6 +17,7 @@ import { } from "@/pages/onboarding/onboardingHooks"; import { Card, Link } from "@/pages/onboarding/utils"; import { PageTitle } from "@/pages/parts/util/PageTitle"; +import { conf } from "@/setup/config"; type ExtensionStatus = | "unknown" @@ -108,6 +109,7 @@ export function OnboardingExtensionPage() { const { t } = useTranslation(); const navigate = useNavigateOnboarding(); const { completeAndRedirect } = useRedirectBack(); + const installLink = conf().ONBOARDING_EXTENSION_INSTALL_LINK; const [{ loading, value }, exec] = useAsyncFn( async (triggeredManually: boolean = false) => { @@ -119,7 +121,6 @@ export function OnboardingExtensionPage() { ); useInterval(exec, 1000); - // TODO proper link to install extension return ( @@ -131,9 +132,11 @@ export function OnboardingExtensionPage() { {t("onboarding.extension.explainer")} - - {t("onboarding.extension.link")} - + {installLink ? ( + + {t("onboarding.extension.link")} + + ) : null}
diff --git a/src/pages/onboarding/OnboardingProxy.tsx b/src/pages/onboarding/OnboardingProxy.tsx index e576779c..ae76b9aa 100644 --- a/src/pages/onboarding/OnboardingProxy.tsx +++ b/src/pages/onboarding/OnboardingProxy.tsx @@ -17,6 +17,7 @@ import { } 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"; @@ -27,6 +28,7 @@ export function OnboardingProxyPage() { const { completeAndRedirect } = useRedirectBack(); const [url, setUrl] = useState(""); const setProxySet = useAuthStore((s) => s.setProxySet); + const installLink = conf().ONBOARDING_PROXY_INSTALL_LINK; const [{ loading, error }, test] = useAsyncFn(async () => { if (!url.startsWith("http")) @@ -42,7 +44,6 @@ export function OnboardingProxyPage() { } }, [url, completeAndRedirect, setProxySet]); - // TODO proper link to proxy deployment docs return ( @@ -54,7 +55,11 @@ export function OnboardingProxyPage() { {t("onboarding.proxy.explainer")} - {t("onboarding.proxy.link")} + {installLink ? ( + + {t("onboarding.proxy.link")} + + ) : null}
; HAS_ONBOARDING: boolean; + ONBOARDING_EXTENSION_INSTALL_LINK: string | null; + ONBOARDING_PROXY_INSTALL_LINK: string | null; } const env: Record = { @@ -44,6 +48,10 @@ const env: Record = { GITHUB_LINK: undefined, DONATION_LINK: undefined, DISCORD_LINK: undefined, + ONBOARDING_EXTENSION_INSTALL_LINK: import.meta.env + .VITE_ONBOARDING_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, @@ -72,6 +80,8 @@ function getKey(key: keyof Config, defaultString?: string): string { export function conf(): RuntimeConfig { const dmcaEmail = getKey("DMCA_EMAIL"); + const extensionLink = getKey("ONBOARDING_EXTENSION_INSTALL_LINK"); + const proxyInstallLink = getKey("ONBOARDING_PROXY_INSTALL_LINK"); const turnstileKey = getKey("TURNSTILE_KEY"); return { APP_VERSION, @@ -79,6 +89,10 @@ export function conf(): RuntimeConfig { DONATION_LINK, DISCORD_LINK, DMCA_EMAIL: dmcaEmail.length > 0 ? dmcaEmail : null, + ONBOARDING_EXTENSION_INSTALL_LINK: + extensionLink.length > 0 ? extensionLink : 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") From c0241000d0fc54a610990a7706701a5fda378eb8 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 23 Jan 2024 19:32:51 +0000 Subject: [PATCH 061/151] Add semver extension version checking (#808) * Add semver extension version checking --- package.json | 2 + pnpm-lock.yaml | 65 ++++++++++++++------------ src/backend/extension/compatibility.ts | 6 ++- 3 files changed, 40 insertions(+), 33 deletions(-) diff --git a/package.json b/package.json index c5dae16f..4468753e 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,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" @@ -87,6 +88,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", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2fda1a32..a0e60397 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -123,6 +123,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 @@ -191,6 +194,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) @@ -259,7 +265,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.5) + version: 5.11.0(@rollup/wasm-node@4.9.6) tailwind-scrollbar: specifier: ^3.0.5 version: 3.0.5(tailwindcss@3.4.0) @@ -2048,7 +2054,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.5): + /@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: @@ -2061,36 +2067,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.5) - rollup: /@rollup/wasm-node@4.9.5 + '@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.5): + /@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.5) + '@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.5 + rollup: /@rollup/wasm-node@4.9.6 dev: true - /@rollup/plugin-replace@2.4.2(@rollup/wasm-node@4.9.5): + /@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.5) + '@rollup/pluginutils': 3.1.0(@rollup/wasm-node@4.9.6) magic-string: 0.25.9 - rollup: /@rollup/wasm-node@4.9.5 + rollup: /@rollup/wasm-node@4.9.6 dev: true - /@rollup/pluginutils@3.1.0(@rollup/wasm-node@4.9.5): + /@rollup/pluginutils@3.1.0(@rollup/wasm-node@4.9.6): resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} engines: {node: '>= 8.0.0'} peerDependencies: @@ -2099,7 +2105,7 @@ packages: '@types/estree': 0.0.39 estree-walker: 1.0.1 picomatch: 2.3.1 - rollup: /@rollup/wasm-node@4.9.5 + rollup: /@rollup/wasm-node@4.9.6 dev: true /@rollup/wasm-node@4.9.4: @@ -2112,8 +2118,8 @@ packages: fsevents: 2.3.3 dev: true - /@rollup/wasm-node@4.9.5: - resolution: {integrity: sha512-Xhabb9BwobkC3NFnI9spB+AvHt+iXruRAtBZRlrCDaBnkT7hWUcSF+J+T/nW/qqqGKtYJ/1RzBRv6vCCxEIgpg==} + /@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: @@ -2334,8 +2340,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: @@ -2454,7 +2460,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) @@ -5033,7 +5039,6 @@ packages: engines: {node: '>=10'} dependencies: yallist: 4.0.0 - dev: true /magic-string@0.25.9: resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} @@ -5079,7 +5084,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.5 + rollup: /@rollup/wasm-node@4.9.6 unplugin: 1.5.1 transitivePeerDependencies: - supports-color @@ -6007,7 +6012,7 @@ packages: glob: 7.2.3 dev: true - /rollup-plugin-terser@7.0.2(@rollup/wasm-node@4.9.5): + /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: @@ -6015,12 +6020,12 @@ packages: dependencies: '@babel/code-frame': 7.23.5 jest-worker: 26.6.2 - rollup: /@rollup/wasm-node@4.9.5 + 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.5): + /rollup-plugin-visualizer@5.11.0(@rollup/wasm-node@4.9.6): resolution: {integrity: sha512-exM0Ms2SN3AgTzMeW7y46neZQcyLY7eKwWAop1ZoRTCZwyrIRdMMJ6JjToAJbML77X/9N8ZEpmXG4Z/Clb9k8g==} engines: {node: '>=14'} hasBin: true @@ -6032,7 +6037,7 @@ packages: dependencies: open: 8.4.2 picomatch: 2.3.1 - rollup: /@rollup/wasm-node@4.9.5 + rollup: /@rollup/wasm-node@4.9.6 source-map: 0.7.4 yargs: 17.7.2 dev: true @@ -6146,7 +6151,6 @@ packages: hasBin: true dependencies: lru-cache: 6.0.0 - dev: true /serialize-javascript@4.0.0: resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==} @@ -7015,7 +7019,7 @@ packages: '@types/node': 20.10.5 esbuild: 0.19.10 postcss: 8.4.32 - rollup: /@rollup/wasm-node@4.9.5 + rollup: /@rollup/wasm-node@4.9.6 optionalDependencies: fsevents: 2.3.3 dev: true @@ -7277,9 +7281,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.5) - '@rollup/plugin-node-resolve': 11.2.1(@rollup/wasm-node@4.9.5) - '@rollup/plugin-replace': 2.4.2(@rollup/wasm-node@4.9.5) + '@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 @@ -7288,8 +7292,8 @@ packages: glob: 7.2.3 lodash: 4.17.21 pretty-bytes: 5.6.0 - rollup: /@rollup/wasm-node@4.9.5 - rollup-plugin-terser: 7.0.2(@rollup/wasm-node@4.9.5) + 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 @@ -7456,7 +7460,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==} diff --git a/src/backend/extension/compatibility.ts b/src/backend/extension/compatibility.ts index 31471d26..53ffd7a1 100644 --- a/src/backend/extension/compatibility.ts +++ b/src/backend/extension/compatibility.ts @@ -1,5 +1,7 @@ -const allowedExtensionVersion = ["0.0.1"]; +import { satisfies } from "semver"; + +const allowedExtensionRange = "~1.0.0"; export function isAllowedExtensionVersion(version: string): boolean { - return allowedExtensionVersion.includes(version); + return satisfies(version, allowedExtensionRange); } From ffdaa1916ea375a0dfa30ed7c3fb8b49cf678a0b Mon Sep 17 00:00:00 2001 From: Rafael Queiroz Date: Sun, 7 Jan 2024 01:20:37 +0000 Subject: [PATCH 062/151] Added translation using Weblate (Klingon (pIqaD)) Author: Rafael Queiroz --- src/assets/locales/tlh-qaak.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/assets/locales/tlh-qaak.json diff --git a/src/assets/locales/tlh-qaak.json b/src/assets/locales/tlh-qaak.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/src/assets/locales/tlh-qaak.json @@ -0,0 +1 @@ +{} From 466cb3ce4d922be4bfe1e52d15c26e77f91038d9 Mon Sep 17 00:00:00 2001 From: admin Date: Sun, 7 Jan 2024 01:22:48 +0000 Subject: [PATCH 063/151] Deleted translation using Weblate (Klingon (pIqaD)) Author: admin --- src/assets/locales/tlh-qaak.json | 1 - 1 file changed, 1 deletion(-) delete mode 100644 src/assets/locales/tlh-qaak.json diff --git a/src/assets/locales/tlh-qaak.json b/src/assets/locales/tlh-qaak.json deleted file mode 100644 index 0967ef42..00000000 --- a/src/assets/locales/tlh-qaak.json +++ /dev/null @@ -1 +0,0 @@ -{} From 0b4dbc709c0805fde718b9fa28729c34648a735f Mon Sep 17 00:00:00 2001 From: Rafael Queiroz Date: Sun, 7 Jan 2024 01:53:13 +0000 Subject: [PATCH 064/151] Added translation using Weblate (Portuguese) Author: Rafael Queiroz --- src/assets/locales/pt-PT.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/assets/locales/pt-PT.json diff --git a/src/assets/locales/pt-PT.json b/src/assets/locales/pt-PT.json new file mode 100644 index 00000000..0967ef42 --- /dev/null +++ b/src/assets/locales/pt-PT.json @@ -0,0 +1 @@ +{} From a41353cb6c965111de0503bacb6288611ecfa962 Mon Sep 17 00:00:00 2001 From: Nasir Date: Sun, 7 Jan 2024 16:02:27 +0000 Subject: [PATCH 065/151] Translated using Weblate (French) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/fr/ Author: Nasir --- src/assets/locales/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/locales/fr.json b/src/assets/locales/fr.json index 7c80dc24..9d0f4533 100644 --- a/src/assets/locales/fr.json +++ b/src/assets/locales/fr.json @@ -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" From 2015076e4114a605ceb7c721993eadc46b8ee8f4 Mon Sep 17 00:00:00 2001 From: Hank Dank Date: Sun, 7 Jan 2024 16:10:26 +0000 Subject: [PATCH 066/151] Translated using Weblate (Turkish) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/tr/ Author: Hank Dank --- src/assets/locales/tr.json | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/tr.json b/src/assets/locales/tr.json index 7ea3ec30..cf3a9a20 100644 --- a/src/assets/locales/tr.json +++ b/src/assets/locales/tr.json @@ -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", @@ -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": { From e50e03d74c586d517a36623c99d2810ea801ce8f Mon Sep 17 00:00:00 2001 From: cheesethesylv Date: Sat, 6 Jan 2024 16:48:17 +0000 Subject: [PATCH 067/151] Translated using Weblate (Vietnamese) Currently translated at 30.7% (79 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/vi/ Author: cheesethesylv --- src/assets/locales/vi.json | 42 ++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/assets/locales/vi.json b/src/assets/locales/vi.json index 3af12198..161df6b3 100644 --- a/src/assets/locales/vi.json +++ b/src/assets/locales/vi.json @@ -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,8 +52,34 @@ }, "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}} - 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": { + "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." } }, "global": { From 7566084723c0ef860de998ba7588fc36c08ce3c3 Mon Sep 17 00:00:00 2001 From: jan Kukisulasu Date: Sat, 6 Jan 2024 20:46:09 +0000 Subject: [PATCH 068/151] Translated using Weblate (Toki Pona) Currently translated at 89.8% (231 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/tok/ Author: jan Kukisulasu --- src/assets/locales/tok.json | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/assets/locales/tok.json b/src/assets/locales/tok.json index 50d2d862..074798f2 100644 --- a/src/assets/locales/tok.json +++ b/src/assets/locales/tok.json @@ -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,6 +375,11 @@ "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": { From 28bc4dcbbf82c8425f1a4fe8505c22bec6afe656 Mon Sep 17 00:00:00 2001 From: aryiu Date: Sun, 7 Jan 2024 12:02:25 +0000 Subject: [PATCH 069/151] Translated using Weblate (Catalan) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ca/ Author: aryiu --- src/assets/locales/ca.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/locales/ca.json b/src/assets/locales/ca.json index 7485a93d..6bad3c36 100644 --- a/src/assets/locales/ca.json +++ b/src/assets/locales/ca.json @@ -413,7 +413,7 @@ "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ó", From 594b6e38dbbba7016382bbf0a48911244d3b6c9f Mon Sep 17 00:00:00 2001 From: Rafael Queiroz Date: Sun, 7 Jan 2024 02:03:49 +0000 Subject: [PATCH 070/151] Translated using Weblate (Portuguese (Portugal)) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/pt_PT/ Author: Rafael Queiroz --- src/assets/locales/pt-PT.json | 438 +++++++++++++++++++++++++++++++++- 1 file changed, 437 insertions(+), 1 deletion(-) diff --git a/src/assets/locales/pt-PT.json b/src/assets/locales/pt-PT.json index 0967ef42..c1bc2e29 100644 --- a/src/assets/locales/pt-PT.json +++ b/src/assets/locales/pt-PT.json @@ -1 +1,437 @@ -{} +{ + "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.", + "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.", + "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}} - 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, toque e segure no vídeo, depois selecione guardar.", + "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 , depois em Guardar no Ficheiro .", + "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 Guardar vídeo como", + "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 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 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://" + } + }, + "locale": { + "language": "Idioma da aplicação", + "languageDescription": "Idioma aplicado a toda a aplicação.", + "title": "Localidade" + }, + "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" + } +} From 19de75333b604f898b6c79358470062290990902 Mon Sep 17 00:00:00 2001 From: Hank Dank Date: Tue, 9 Jan 2024 00:55:31 +0000 Subject: [PATCH 071/151] Translated using Weblate (Turkish) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/tr/ Author: Hank Dank --- src/assets/locales/tr.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/assets/locales/tr.json b/src/assets/locales/tr.json index cf3a9a20..d2eccc38 100644 --- a/src/assets/locales/tr.json +++ b/src/assets/locales/tr.json @@ -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": { @@ -301,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" @@ -428,7 +428,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" }, From 05e1991953879f9fac5acae6a396870cc6692452 Mon Sep 17 00:00:00 2001 From: Stella Vanella Date: Mon, 8 Jan 2024 06:22:24 +0000 Subject: [PATCH 072/151] Translated using Weblate (Vietnamese) Currently translated at 33.4% (86 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/vi/ Author: Stella Vanella --- src/assets/locales/vi.json | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/vi.json b/src/assets/locales/vi.json index 161df6b3..098a100d 100644 --- a/src/assets/locales/vi.json +++ b/src/assets/locales/vi.json @@ -79,11 +79,22 @@ }, "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": { From 9c17ab5fe5b1ed126f1560f0c4c82e602e381c41 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 9 Jan 2024 13:09:00 +0000 Subject: [PATCH 073/151] Translated using Weblate (Russian) Currently translated at 61.4% (158 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ru/ Author: Alex --- src/assets/locales/ru.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/assets/locales/ru.json b/src/assets/locales/ru.json index babbb343..6842fa18 100644 --- a/src/assets/locales/ru.json +++ b/src/assets/locales/ru.json @@ -216,6 +216,8 @@ "userIcon": "Значок пользователя" }, "register": { + "cta": "Начать", + "text": "Обменивайтесь информацией о прогрессе часов между устройствами и синхронизируйте их.", "title": "Синхронизировать с облаком" }, "title": "Аккаунт" @@ -241,7 +243,7 @@ "workers": { "addButton": "Добавить новый прокси-сервер", "description": "Для работы приложения весь трафик маршрутизируется через прокси. Включите это, если вы хотите использовать свои собственных прокси-серверы.", - "emptyState": "Прокси ещё нет, добавьте их ниже", + "emptyState": "Прокси отсутствуют, добавьте их ниже", "label": "Использовать прокси-сервера", "urlLabel": "URL-адреса", "urlPlaceholder": "https://" @@ -257,10 +259,14 @@ "sidebar": { "info": { "appVersion": "Версия приложения", + "backendUrl": "Внутренний URL-адрес", + "backendVersion": "Серверная версия", "hostname": "Имя хоста", + "insecure": "Небезопасно", "notLoggedIn": "Вы не авторизованы", "secure": "Безопасный", "title": "Информация о приложении", + "unknownVersion": "Неизвестный", "userId": "ID пользователя" } }, From b66a310c8af58d1779d2b42d210d711694cfcc7e Mon Sep 17 00:00:00 2001 From: Joydip Roy Date: Mon, 8 Jan 2024 05:02:28 +0000 Subject: [PATCH 074/151] Translated using Weblate (Bengali) Currently translated at 62.6% (161 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/bn/ Author: Joydip Roy --- src/assets/locales/bn.json | 56 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/bn.json b/src/assets/locales/bn.json index 719493ee..1a7e2c03 100644 --- a/src/assets/locales/bn.json +++ b/src/assets/locales/bn.json @@ -181,14 +181,43 @@ "disclaimer": "ডাউনলোড সরাসরি প্রদানকারী থেকে নেওয়া হয়. কিভাবে ডাউনলোড দেওয়া হয় তার উপর মুভি-ওয়েবের নিয়ন্ত্রণ নেই।", "downloadPlaylist": "প্লেলিস্ট ডাউনলোড করুন", "downloadSubtitle": "বর্তমান সাবটাইটেল ডাউনলোড করুন", - "downloadVideo": "ভিডিও ডাউনলোড" + "downloadVideo": "ভিডিও ডাউনলোড", + "hlsDisclaimer": "ডাউনলোড সরাসরি প্রদানকারী থেকে নেওয়া হয়. কিভাবে ডাউনলোড দেওয়া হয় তার উপর মুভি-ওয়েবের নিয়ন্ত্রণ নেই। অনুগ্রহ করে মনে রাখবেন যে আপনি একটি HLS প্লেলিস্ট ডাউনলোড করছেন, এটি উন্নত মাল্টিমিডিয়া স্ট্রিমিংয়ের সাথে পরিচিত ব্যবহারকারীদের জন্য।", + "onAndroid": { + "1": "অ্যান্ড্রয়েডে ডাউনলোড করতে, ডাউনলোড বোতামে ক্লিক করুন তারপর, নতুন পৃষ্ঠায়, ভিডিওতে ট্যাপ করুন এবং ধরে রাখুন, তারপরে সংরক্ষণ করুন নির্বাচন করুন।", + "shortTitle": "ডাউনলোড/অ্যান্ড্রয়েড", + "title": "অ্যান্ড্রয়েডে ডাউনলোড হচ্ছে" + }, + "onIos": { + "1": "iOS-এ ডাউনলোড করতে, ডাউনলোড বোতামে ক্লিক করুন তারপর, নতুন পৃষ্ঠায়, -এ ক্লিক করুন, তারপর ফাইলে সংরক্ষণ করুন ।", + "shortTitle": "ডাউনলোড / iOS", + "title": "iOS এ ডাউনলোড হচ্ছে" + }, + "onPc": { + "1": "পিসিতে, ডাউনলোড বোতামে ক্লিক করুন তারপর, নতুন পৃষ্ঠায়, ভিডিওটিতে ডান ক্লিক করুন এবং ভিডিওটিকে এই হিসাবে সংরক্ষণ করুন নির্বাচন করুন", + "shortTitle": "ডাউনলোড/পিসি", + "title": "পিসিতে ডাউনলোড হচ্ছে" + }, + "title": "ডাউনলোড করুন" }, "episodes": { "button": "পর্বগুলি", "emptyState": "এই মরসুমে কোন পর্ব নেই, পরে আবার চেক করুন!", + "episodeBadge": "E{{episode}}", "loadingError": "ঋতু লোড করার সময় ত্রুটি৷", "loadingList": "লোড হচ্ছে..।", - "loadingTitle": "লোড হচ্ছে..।" + "loadingTitle": "লোড হচ্ছে..।", + "unairedEpisodes": "এই সিজনের এক বা একাধিক পর্ব অক্ষম করা হয়েছে কারণ সেগুলি এখনও সম্প্রচার করা হয়নি।" + }, + "playback": { + "speedLabel": "প্লেব্যাক গতি", + "title": "প্লেব্যাক সেটিংস" + }, + "quality": { + "automaticLabel": "স্বয়ংক্রিয় গুণমান", + "hint": "আপনি বিভিন্ন গুণমানের বিকল্প পেতে <0>উৎস পরিবর্তন করে দেখতে পারেন।", + "iosNoQuality": "অ্যাপল-সংজ্ঞায়িত সীমাবদ্ধতার কারণে, এই উৎসের জন্য গুণমান নির্বাচন iOS-এ উপলব্ধ নয়। বিভিন্ন মানের বিকল্প পেতে আপনি <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": "আপনার মানবতা যাচাই করা হচ্ছে..।" } } } From 3bbb9cf0f6a115bc1b2ace20b5f8071573046969 Mon Sep 17 00:00:00 2001 From: Jakub Herda Date: Wed, 10 Jan 2024 14:42:26 +0000 Subject: [PATCH 075/151] Translated using Weblate (Polish) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/pl/ Author: Jakub Herda --- src/assets/locales/pl.json | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/assets/locales/pl.json b/src/assets/locales/pl.json index dd347592..2ecaac84 100644 --- a/src/assets/locales/pl.json +++ b/src/assets/locales/pl.json @@ -206,7 +206,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 +259,10 @@ } }, "metadata": { + "api": { + "text": "Nie można załadować metadanych API, sprawdź połączenie internetowe.", + "title": "Nie udało się załadować metadanych API" + }, "failed": { "badge": "Nie powiodło się", "homeButton": "Wróć na stronę główną", @@ -309,6 +314,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..." From 76a2be9c9c0123ede916124e9adb4fd8cabf6bb9 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 9 Jan 2024 22:05:19 +0000 Subject: [PATCH 076/151] Translated using Weblate (Russian) Currently translated at 64.2% (165 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ru/ Author: Alex --- src/assets/locales/ru.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/assets/locales/ru.json b/src/assets/locales/ru.json index 6842fa18..8ce30c75 100644 --- a/src/assets/locales/ru.json +++ b/src/assets/locales/ru.json @@ -164,6 +164,21 @@ "subtitleItem": "Настройки субтитров", "videoSection": "Настройки видео" }, + "sources": { + "failed": { + "text": "При попытке найти видео произошла ошибка, пожалуйста, попробуйте использовать другой источник." + }, + "noEmbeds": { + "text": "Мы не смогли найти ни одной вставки, пожалуйста, попробуйте использовать другой источник.", + "title": "Не найдено ни одной вставки" + }, + "noStream": { + "text": "В этом источнике нет потоков для этого фильма или сериала.", + "title": "Нет потока" + }, + "title": "Источники", + "unknownOption": "Неизвестный" + }, "subtitles": { "settings": { "backlink": "Пользовательские субтитры" From edb0de12ab35dc81b510cf6641015254e883432e Mon Sep 17 00:00:00 2001 From: aryiu Date: Sat, 13 Jan 2024 22:32:52 +0000 Subject: [PATCH 077/151] Translated using Weblate (Catalan) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ca/ Author: aryiu --- src/assets/locales/ca.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/ca.json b/src/assets/locales/ca.json index 6bad3c36..4779a430 100644 --- a/src/assets/locales/ca.json +++ b/src/assets/locales/ca.json @@ -18,7 +18,7 @@ }, "actions": { "copied": "S'ha copiat", - "copy": "Cipia" + "copy": "Copia" }, "auth": { "createAccount": "Encara no teniu un compte? <0>Creeu un compte.", @@ -108,7 +108,7 @@ "sectionTitle": "Continueu mirant" }, "mediaList": { - "stopEditing": "Atura l'edició" + "stopEditing": "Deixa d'editar" }, "search": { "allResults": "Això és tot el que tenim!", From 27f043c9cfcbf2eff66c78535bb4615cbb40319a Mon Sep 17 00:00:00 2001 From: Isra Date: Tue, 16 Jan 2024 06:37:43 +0000 Subject: [PATCH 078/151] Translated using Weblate (German) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/de/ Author: Isra --- src/assets/locales/de.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/de.json b/src/assets/locales/de.json index e5152a44..6b5b46f1 100644 --- a/src/assets/locales/de.json +++ b/src/assets/locales/de.json @@ -390,14 +390,14 @@ }, "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.", "label": "Eigener Server", "urlLabel": "Eigene Server-URL" }, "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.", "emptyState": "Keine Worker vorhanden, füge einen unten hinzu", "label": "Verwenden deinen eigenen Worker-Proxys", "urlLabel": "Worker-URLs", From 8d20d5ba4b440194e53584465cc1c0d623f0629d Mon Sep 17 00:00:00 2001 From: Aayush Shah Date: Tue, 16 Jan 2024 08:22:27 +0000 Subject: [PATCH 079/151] Translated using Weblate (Nepali) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ne/ Author: Aayush Shah --- src/assets/locales/ne.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/ne.json b/src/assets/locales/ne.json index e06617e9..0c0ddf8f 100644 --- a/src/assets/locales/ne.json +++ b/src/assets/locales/ne.json @@ -390,14 +390,14 @@ }, "connections": { "server": { - "description": "यदि तपाईं आफ्नो डेटा भण्डारण गर्न अनुकूलन ब्याकइन्डमा जडान गर्न चाहनुहुन्छ भने, यसलाई सक्षम गर्नुहोस् र URL प्रदान गर्नुहोस्।", + "description": "यदि तपाईं आफ्नो डेटा भण्डारण गर्न अनुकूलन ब्याकइन्डमा जडान गर्न चाहनुहुन्छ भने, यसलाई सक्षम गर्नुहोस् र URL प्रदान गर्नुहोस्। <0>निर्देशनहरू।", "label": "अनुकूलन सर्भर", "urlLabel": "अनुकूलन सर्भर URL" }, "title": "संबन्धहरु", "workers": { "addButton": "नया worker हरु हाल्नुहोस", - "description": "एप्लिकेसन प्रकार्य बनाउनको लागि, सबै ट्राफिक प्रोक्सीहरू मार्फत रूट गरिएको छ। यदि तपाईं आफ्नो कामदारहरू ल्याउन चाहनुहुन्छ भने यसलाई सक्षम गर्नुहोस्।", + "description": "एप्लिकेसन प्रकार्य बनाउनको लागि, सबै ट्राफिक प्रोक्सीहरू मार्फत रूट गरिएको छ। यदि तपाईं आफ्नो कामदारहरू ल्याउन चाहनुहुन्छ भने यसलाई सक्षम गर्नुहोस्। <0>निर्देशनहरू।", "emptyState": "अहिलेसम्म worker हरु छैनन्, तल एउटा थप्नुहोस्", "label": "आफ्नै proxy workers हरु चलाउनुहोस्", "urlLabel": "Worker URL हरु", From 4f7a2565d1a0681434e49f77ded29f51bf91ce8c Mon Sep 17 00:00:00 2001 From: blikje Date: Tue, 16 Jan 2024 12:24:12 +0000 Subject: [PATCH 080/151] Translated using Weblate (Dutch) Currently translated at 99.6% (256 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/nl/ Author: blikje --- src/assets/locales/nl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/locales/nl.json b/src/assets/locales/nl.json index 6cc614dd..276bb95f 100644 --- a/src/assets/locales/nl.json +++ b/src/assets/locales/nl.json @@ -390,7 +390,7 @@ }, "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.", "label": "Eigen server", "urlLabel": "Eigen server URL" }, From 2077eafa291d8552c3f30ee851ab884cf73bcfff Mon Sep 17 00:00:00 2001 From: Denys Savin Date: Tue, 16 Jan 2024 12:19:44 +0000 Subject: [PATCH 081/151] Translated using Weblate (Ukrainian) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/uk/ Author: Denys Savin --- src/assets/locales/uk.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/assets/locales/uk.json b/src/assets/locales/uk.json index 240a57ab..3fbe83d8 100644 --- a/src/assets/locales/uk.json +++ b/src/assets/locales/uk.json @@ -322,7 +322,7 @@ }, "screens": { "dmca": { - "text": "Ласкаво просимо на контактну сторінку DMCA від movie-web! Ми поважаємо права інтелектуальної власності і прагнемо швидко вирішувати будь-які проблеми, пов'язані з авторськими правами. Якщо ви вважаєте, що ваша робота, захищена авторським правом, була неналежним чином використана на нашій платформі, будь ласка, надішліть детальне повідомлення DMCA на електронну адресу нижче. Будь ласка, додайте опис матеріалу, захищеного авторським правом, ваші контактні дані та заяву з обґрунтуванням ваших сумлінних переконань. Ми прагнемо оперативно вирішити ці питання і будемо вдячні за вашу співпрацю у збереженні movie-web місцем, де поважають творчість і авторські права.", + "text": "Вітаємо на нашій сторінці зв'язку DMCA! Ми поважаємо права інтелектуальної власності і хочемо вирішити будь-які проблеми з авторськими правами швидко. Якщо ви вважаєте, що ваші авторські права були неправильно використані на нашій платформі, будь ласка, надішліть детальне повідомлення DMCA на електронну адресу нижче. Будь ласка, вкажіть опис авторського матеріалу, ваші контактні дані та заяву про добросовісну віру. Ми зобов'язані вирішити ці питання оперативно і вдячні за вашу співпрацю в збереженні movie-web місцем, яке поважає творчість та авторські права", "title": "DMCA" }, "loadingApp": "Завантаження застосунку", @@ -381,7 +381,7 @@ "activeTheme": "Активна тема", "themes": { "blue": "Блакитний", - "default": "Основний", + "default": "За замовчуванням", "gray": "Сірий", "red": "Червоний", "teal": "Бірюзовий" @@ -390,14 +390,14 @@ }, "connections": { "server": { - "description": "Якщо ви хочете підключитися до кастомного серверу для зберігання ваших даних, увімкніть це та надайте URL.", + "description": "Якщо ви хочете використовувати власний сервер, введіть його URL нижче. Якщо ви не знаєте, що це таке, ви, ймовірно, не повинні цього робити.", "label": "Власний сервер", "urlLabel": "URL сервера" }, "title": "З'єднання", "workers": { "addButton": "Додати нового працівника", - "description": "Щоб додаток працював, весь трафік маршрутизується через проксі-сервери. Увімкніть це, якщо ви хочете використовувати власні проксі воркери.", + "description": "Щоб додаток працював, весь трафік маршрутизується через проксі-сервери. Увімкніть це, якщо ви хочете використовувати власні проксі воркери. <0>Інструкція.", "emptyState": "Немає працівників", "label": "Використовувати власних проксі-працівників", "urlLabel": "URL-у працівника", From d7829b2978e7313c051b0095da3b6f2b1e996bcb Mon Sep 17 00:00:00 2001 From: blikje Date: Tue, 16 Jan 2024 12:25:00 +0000 Subject: [PATCH 082/151] Translated using Weblate (Dutch) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/nl/ Author: blikje --- src/assets/locales/nl.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/locales/nl.json b/src/assets/locales/nl.json index 276bb95f..16f350e5 100644 --- a/src/assets/locales/nl.json +++ b/src/assets/locales/nl.json @@ -397,7 +397,7 @@ "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.", "emptyState": "Nog geen workers, voeg er hieronder een toe", "label": "Eigen proxy werker gebruiken", "urlLabel": "Worker URLs", From 560e793a5d1a9957ff430e56731a0da38ee7a70c Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 16 Jan 2024 13:34:40 +0000 Subject: [PATCH 083/151] Translated using Weblate (Russian) Currently translated at 64.2% (165 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ru/ Author: Alex --- src/assets/locales/ru.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/assets/locales/ru.json b/src/assets/locales/ru.json index 8ce30c75..3097386b 100644 --- a/src/assets/locales/ru.json +++ b/src/assets/locales/ru.json @@ -197,6 +197,16 @@ }, "text": "При попытке воспроизвести медиа файл произошла ошибка. Пожалуйста, попробуйте ещё раз.", "title": "Не удалось воспроизвести видео!" + }, + "scraping": { + "notFound": { + "detailsButton": "Показать детали" + } + } + }, + "screens": { + "dmca": { + "title": "DMCA" } }, "settings": { From 25df1304befc752510bdd8d3781b5d80c73da472 Mon Sep 17 00:00:00 2001 From: n1ck Date: Tue, 16 Jan 2024 18:27:03 +0000 Subject: [PATCH 084/151] Translated using Weblate (Spanish) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/es/ Author: n1ck --- src/assets/locales/es.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/es.json b/src/assets/locales/es.json index f051ceb0..c0cd4246 100644 --- a/src/assets/locales/es.json +++ b/src/assets/locales/es.json @@ -390,14 +390,14 @@ }, "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.", "label": "Servidor personalizado", "urlLabel": "URL del servidor personalizado" }, "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.", "emptyState": "Aún no hay workers, agrega uno a continuación", "label": "Usar proxy workers personalizados", "urlLabel": "URL de los workers", From 6126299cd6a98b4509d903be26b500bbbd8a3095 Mon Sep 17 00:00:00 2001 From: n1ck Date: Tue, 16 Jan 2024 18:27:30 +0000 Subject: [PATCH 085/151] Translated using Weblate (Galician) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/gl/ Author: n1ck --- src/assets/locales/gl.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/gl.json b/src/assets/locales/gl.json index 63fe31fa..8d36470a 100644 --- a/src/assets/locales/gl.json +++ b/src/assets/locales/gl.json @@ -390,14 +390,14 @@ }, "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.", "label": "Servidor personalizado", "urlLabel": "Servidor personalizado URL" }, "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.", "emptyState": "Non hai workers aínda, engade un abaixo", "label": "Usar proxy workers personalizados", "urlLabel": "URLs dos workers", From 829bb7d2726c60cec77c7cfb29a660ac60e335e3 Mon Sep 17 00:00:00 2001 From: Nasir Date: Tue, 16 Jan 2024 19:25:03 +0000 Subject: [PATCH 086/151] Translated using Weblate (French) Currently translated at 99.6% (256 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/fr/ Author: Nasir --- src/assets/locales/fr.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/fr.json b/src/assets/locales/fr.json index 9d0f4533..ca08930f 100644 --- a/src/assets/locales/fr.json +++ b/src/assets/locales/fr.json @@ -390,14 +390,14 @@ }, "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 souhaitez vous connecter à une sauvegarde personnalisé pour stocker vos données, activez cette option et indiquez l'URL. <0>Instructions.", "label": "Serveur personnalisé", "urlLabel": "URL du serveur personnalisé" }, "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 travailleurs. <0>Instructions.", "emptyState": "Pas encore de workers, ajoutez-en un ci-dessous", "label": "Utiliser des agents proxy personnalisés", "urlLabel": "URLs des workers", From c1ffe921de9f651654f000d35cb3dcdeededbc8b Mon Sep 17 00:00:00 2001 From: Thais Palmer Date: Tue, 16 Jan 2024 19:29:54 +0000 Subject: [PATCH 087/151] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/pt_BR/ Author: Thais Palmer --- src/assets/locales/pt-BR.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/assets/locales/pt-BR.json b/src/assets/locales/pt-BR.json index 38de1037..88fa296f 100644 --- a/src/assets/locales/pt-BR.json +++ b/src/assets/locales/pt-BR.json @@ -122,7 +122,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": { @@ -390,14 +390,14 @@ }, "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.", "label": "Servidor personalizado", "urlLabel": "URL do servidor personalizado" }, "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.", "emptyState": "Ainda não há workers, adicione um abaixo", "label": "Usar proxy workers personalizados", "urlLabel": "URLs dos workers", From 909332ae756586545fc5f192ddd73e31429a628b Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 16 Jan 2024 20:36:21 +0000 Subject: [PATCH 088/151] Translated using Weblate (Russian) Currently translated at 64.9% (167 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ru/ Author: Alex --- src/assets/locales/ru.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/assets/locales/ru.json b/src/assets/locales/ru.json index 3097386b..52b12d3b 100644 --- a/src/assets/locales/ru.json +++ b/src/assets/locales/ru.json @@ -180,6 +180,8 @@ "unknownOption": "Неизвестный" }, "subtitles": { + "customChoice": "Выбрать субтитры из файла", + "offChoice": "Выключить", "settings": { "backlink": "Пользовательские субтитры" }, From c2f00d53a39d9783a663532b39fa66a37bffa2a2 Mon Sep 17 00:00:00 2001 From: Jamie Poznanski Date: Tue, 16 Jan 2024 22:34:31 +0000 Subject: [PATCH 089/151] Translated using Weblate (Italian) Currently translated at 99.6% (256 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/it/ Author: Jamie Poznanski --- src/assets/locales/it.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/locales/it.json b/src/assets/locales/it.json index 5ec260ec..fa01424f 100644 --- a/src/assets/locales/it.json +++ b/src/assets/locales/it.json @@ -390,7 +390,7 @@ }, "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>Instructions.", "label": "Server personalizzato", "urlLabel": "URL del server personalizzato" }, From 4c75c8e1c114a050220845ac04e3abc7c99ddc43 Mon Sep 17 00:00:00 2001 From: Jamie Poznanski Date: Tue, 16 Jan 2024 22:34:56 +0000 Subject: [PATCH 090/151] Translated using Weblate (Italian) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/it/ Author: Jamie Poznanski --- src/assets/locales/it.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/it.json b/src/assets/locales/it.json index fa01424f..382b7bf4 100644 --- a/src/assets/locales/it.json +++ b/src/assets/locales/it.json @@ -390,14 +390,14 @@ }, "connections": { "server": { - "description": "Se si desideri connettersi a un backend personalizzato per memorizzare i dati, attivare questo e fornire l'URL. <0>Instructions.", + "description": "Se si desideri connettersi a un backend personalizzato per memorizzare i dati, attivare questo e fornire l'URL. <0>Istruzioni.", "label": "Server personalizzato", "urlLabel": "URL del server personalizzato" }, "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.", "emptyState": "Non ci sono ancora lavoratori, aggiungetene uno sotto", "label": "Utilizzare proxy worker personalizzati", "urlLabel": "URL dei lavoratori", From 0e25d9b135922fa0e93ddbd3f69fbb8504112f6b Mon Sep 17 00:00:00 2001 From: Raymond Nee Date: Wed, 17 Jan 2024 13:35:59 +0000 Subject: [PATCH 091/151] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/zh_Hans/ Author: Raymond Nee --- src/assets/locales/zh.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/zh.json b/src/assets/locales/zh.json index 0f915770..8c3fb69d 100644 --- a/src/assets/locales/zh.json +++ b/src/assets/locales/zh.json @@ -390,14 +390,14 @@ }, "connections": { "server": { - "description": "若您想连接到自定义后端保存数据,请启用此选项并提供 URL。", + "description": "若您想连接到自定义后端保存数据,请启用此选项并提供 URL。 <0>查看指引。", "label": "自定义服务器", "urlLabel": "自定义服务器 URL" }, "title": "连接", "workers": { "addButton": "添加新的 Worker", - "description": "要让应用程序正常运作,所有流量会通过代理路由。若您想使用自己的 Worker,请启用该选项。", + "description": "要让应用程序正常运作,所有流量会通过代理路由。若您想使用自己的 Worker,请启用该选项。 <0>查看指引。", "emptyState": "还没有 Worker,在下方添加一个", "label": "使用自定义代理 Worker", "urlLabel": "Worker URL", From e0b633df09bd7f3cbf2897b118de7470b0714ddd Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 17 Jan 2024 17:03:55 +0000 Subject: [PATCH 092/151] Translated using Weblate (Russian) Currently translated at 65.7% (169 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ru/ Author: Alex --- src/assets/locales/ru.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/assets/locales/ru.json b/src/assets/locales/ru.json index 52b12d3b..97932763 100644 --- a/src/assets/locales/ru.json +++ b/src/assets/locales/ru.json @@ -202,8 +202,12 @@ }, "scraping": { "notFound": { - "detailsButton": "Показать детали" + "detailsButton": "Показать детали", + "title": "Мы не смогли найти" } + }, + "time": { + "regular": "{{timeWatched}} / {{duration}}" } }, "screens": { From 682ad93c228a37f03e2f7b6c4a68c33b2d88db4b Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 17 Jan 2024 19:59:28 +0000 Subject: [PATCH 093/151] Translated using Weblate (Russian) Currently translated at 67.3% (173 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ru/ Author: Alex --- src/assets/locales/ru.json | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/ru.json b/src/assets/locales/ru.json index 97932763..edd293ea 100644 --- a/src/assets/locales/ru.json +++ b/src/assets/locales/ru.json @@ -64,13 +64,17 @@ "description": "Пожалуйста, введите фразу, полученную ранее, чтобы подтвердить, что вы ее сохранили, и создать свой аккаунт", "invalidData": "Дата инвалидная", "noMatch": "Парольная фраза не совпадает", - "register": "Создать учётную запись" + "passphraseLabel": "Ваша 12-словная парольная фраза", + "recaptchaFailed": "Проверка ReCaptcha не удалась", + "register": "Создать учётную запись", + "title": "Подтвердите парольную фразу" } }, "errors": { "details": "Подробности ошибки", "reloadPage": "Перезагрузить страницу", - "showError": "Показать сведения об ошибке" + "showError": "Показать сведения об ошибке", + "title": "Мы столкнулись с ошибкой!" }, "footer": { "legal": { From 44ad21986576b79bb62de09af1f45bdb1ee5bf23 Mon Sep 17 00:00:00 2001 From: Guillaume Date: Thu, 18 Jan 2024 15:34:49 +0000 Subject: [PATCH 094/151] Translated using Weblate (French) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/fr/ Author: Guillaume --- src/assets/locales/fr.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/fr.json b/src/assets/locales/fr.json index ca08930f..482f3cfb 100644 --- a/src/assets/locales/fr.json +++ b/src/assets/locales/fr.json @@ -390,14 +390,14 @@ }, "connections": { "server": { - "description": "Si vous souhaitez vous connecter à une sauvegarde personnalisé pour stocker vos données, activez cette option et indiquez l'URL. <0>Instructions.", + "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.", "label": "Serveur personnalisé", "urlLabel": "URL du serveur personnalisé" }, "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 travailleurs. <0>Instructions.", + "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.", "emptyState": "Pas encore de workers, ajoutez-en un ci-dessous", "label": "Utiliser des agents proxy personnalisés", "urlLabel": "URLs des workers", From 4d7355217407b9a19ee29b71bd23d80eeee7fd73 Mon Sep 17 00:00:00 2001 From: aryiu Date: Fri, 19 Jan 2024 20:08:00 +0000 Subject: [PATCH 095/151] Translated using Weblate (Catalan) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ca/ Author: aryiu --- src/assets/locales/ca.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/ca.json b/src/assets/locales/ca.json index 4779a430..8e7a16c7 100644 --- a/src/assets/locales/ca.json +++ b/src/assets/locales/ca.json @@ -390,14 +390,14 @@ }, "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.", "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.", "emptyState": "Encara no hi ha «workers», afegiu-ne un a continuació", "label": "Utilitza «workers» intermediaris personalitzats", "urlLabel": "URL dels «workers»", From 4e5043f5793a6a16d95dccc5e38ca4aa13e9d0ff Mon Sep 17 00:00:00 2001 From: Jamie Poznanski Date: Sat, 20 Jan 2024 11:19:36 +0000 Subject: [PATCH 096/151] Translated using Weblate (Italian) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/it/ Author: Jamie Poznanski --- src/assets/locales/it.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/assets/locales/it.json b/src/assets/locales/it.json index 382b7bf4..1b58f0c2 100644 --- a/src/assets/locales/it.json +++ b/src/assets/locales/it.json @@ -120,19 +120,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." ] From adf24115ee6e6965015a6e640677d3824a92a73e Mon Sep 17 00:00:00 2001 From: Mehdi Date: Sat, 20 Jan 2024 12:20:53 +0000 Subject: [PATCH 097/151] Translated using Weblate (Persian) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/fa/ Author: Mehdi --- src/assets/locales/fa.json | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/assets/locales/fa.json b/src/assets/locales/fa.json index e68517d2..bb393cb8 100644 --- a/src/assets/locales/fa.json +++ b/src/assets/locales/fa.json @@ -206,7 +206,8 @@ "episodeBadge": "قسمت {{episode}}", "loadingError": "مشکلی در دریافت قسمت ها پیش آمده", "loadingList": "در حال دریافت...", - "loadingTitle": "در حال دریافت..." + "loadingTitle": "در حال دریافت...", + "unairedEpisodes": "یک یا چند قسمت در این فصل غیرفعال شده است به دلیل اینکه هنوز پخش نشده است." }, "playback": { "speedLabel": "سرعت پخش", @@ -258,6 +259,10 @@ } }, "metadata": { + "api": { + "text": "داده API بارگیری نشد، لطفا اتصال اینترنت خود را بررسی کنید.", + "title": "داده API بارگیری نشد" + }, "failed": { "badge": "ناموفق بود", "homeButton": "بازگشت به خانه", @@ -307,6 +312,12 @@ "remaining": "{{timeLeft}} مشاهده شده • {{timeFinished, datetime}} دیگر تمام می‌شود", "shortRegular": "{{timeWatched}}", "shortRemaining": "-{{timeLeft}}" + }, + "turnstile": { + "description": "لطفا انسانیت خود را با تموم کردن چالش های کپچا به طور درست ثابت کنید. برای امن نگه داشتن فیلم وب!", + "error": "انسانیت شما تأیید نشد. لطفا دوباره تلاش کنید.", + "title": "ما باید برسی کنیم که شما انسان هستید.", + "verifyingHumanity": "تایید کردن انسانیت شما..." } }, "screens": { @@ -379,14 +390,14 @@ }, "connections": { "server": { - "description": "اگر می خواهید برای ذخیره داده های خود به یک بک-اند سفارشی متصل شوید، این را فعال و لینک را وارد کنید.", + "description": "اگر میخواهید به یک بک-اند سفارشی برای ذخیره داده متصل شوید، با فعال و ارائه کردن این لینک ادامه دهید. <0>دستورالعمل ها.", "label": "سرور سفارشی", "urlLabel": "لینک سرور سفارشی" }, "title": "اتصالات", "workers": { "addButton": "اضافه کردن worker جدید", - "description": "برای کار کردن برنامه، تمام ترافیک از طریق پروکسی ها هدایت می شود. این کار را انجام دهید اگر می خواهید از worker های خود استفاده کنید.", + "description": "برای ایجاد عملکرد برنامه، تمام ترافیک از طریق پروکسی ها هدایت می شود. اگر میخواهید این کار انجام دهید حتما از worker های خودتان استفاده کنید. <0>دستورالعمل ها.", "emptyState": "هنوز هیچ worker ای وجود ندارد، یکی اضافه کنید", "label": "استفاده از worker های پروکسی سفارشی", "urlLabel": "لینک worker ها", From 4bb7a5074a5d1495a309db1dae8c7078fd35525c Mon Sep 17 00:00:00 2001 From: Hank Dank Date: Sun, 21 Jan 2024 10:30:59 +0000 Subject: [PATCH 098/151] Translated using Weblate (Turkish) Currently translated at 100.0% (257 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/tr/ Author: Hank Dank --- src/assets/locales/tr.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/tr.json b/src/assets/locales/tr.json index d2eccc38..9b05e84c 100644 --- a/src/assets/locales/tr.json +++ b/src/assets/locales/tr.json @@ -390,14 +390,14 @@ }, "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.", "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.", "emptyState": "Henüz işleyici yok, aşağıya bir tane ekleyin", "label": "Özel vekil sunucu işleyici kullan", "urlLabel": "İşleyici URL'leri", From dc6f8be5d8d3e317b57632835eb0b39fac1da68f Mon Sep 17 00:00:00 2001 From: Alex Date: Sun, 21 Jan 2024 13:53:01 +0000 Subject: [PATCH 099/151] Translated using Weblate (Russian) Currently translated at 67.7% (174 of 257 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ru/ Author: Alex --- src/assets/locales/ru.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/assets/locales/ru.json b/src/assets/locales/ru.json index edd293ea..40c0e182 100644 --- a/src/assets/locales/ru.json +++ b/src/assets/locales/ru.json @@ -132,6 +132,9 @@ "support": "Поддержка" } }, + "notFound": { + "title": "Не удалось найти эту страницу" + }, "overlays": { "close": "Закрыть" }, From dd19e0a2d2f70607c9c44ea1373031047323e538 Mon Sep 17 00:00:00 2001 From: Weblate Date: Sun, 21 Jan 2024 20:43:32 +0000 Subject: [PATCH 100/151] Update translation files Updated by "Cleanup translation files" hook in Weblate. Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ --- src/assets/locales/ar.json | 5 ----- src/assets/locales/ca.json | 5 ----- src/assets/locales/cs.json | 5 ----- src/assets/locales/de.json | 5 ----- src/assets/locales/el.json | 5 ----- src/assets/locales/es.json | 5 ----- src/assets/locales/et.json | 5 ----- src/assets/locales/fa.json | 5 ----- src/assets/locales/fr.json | 5 ----- src/assets/locales/gl.json | 5 ----- src/assets/locales/gu.json | 5 ----- src/assets/locales/he.json | 5 ----- src/assets/locales/hi.json | 5 ----- src/assets/locales/id.json | 5 ----- src/assets/locales/it.json | 5 ----- src/assets/locales/ko.json | 5 ----- src/assets/locales/lv.json | 5 ----- src/assets/locales/minion.json | 5 ----- src/assets/locales/ne.json | 5 ----- src/assets/locales/nl.json | 5 ----- src/assets/locales/pirate.json | 5 ----- src/assets/locales/pl.json | 5 ----- src/assets/locales/pt-BR.json | 5 ----- src/assets/locales/pt-PT.json | 5 ----- src/assets/locales/ro.json | 5 ----- src/assets/locales/ru.json | 5 ----- src/assets/locales/sl.json | 5 ----- src/assets/locales/sv.json | 5 ----- src/assets/locales/th.json | 5 ----- src/assets/locales/tok.json | 5 ----- src/assets/locales/tr.json | 5 ----- src/assets/locales/uk.json | 5 ----- src/assets/locales/zh.json | 5 ----- 33 files changed, 165 deletions(-) diff --git a/src/assets/locales/ar.json b/src/assets/locales/ar.json index 0fc20948..6138644c 100644 --- a/src/assets/locales/ar.json +++ b/src/assets/locales/ar.json @@ -394,11 +394,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "لغة التطبيق", - "languageDescription": "اللغة المطبقة على كامل التطبيق.", - "title": "اللغة" - }, "reset": "إعادة تعيين", "save": "حفظ", "sidebar": { diff --git a/src/assets/locales/ca.json b/src/assets/locales/ca.json index 8e7a16c7..f54e8948 100644 --- a/src/assets/locales/ca.json +++ b/src/assets/locales/ca.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "Llengua de l'aplicació", - "languageDescription": "La llengua s'aplica a tota l'aplicació.", - "title": "Llengua" - }, "reset": "Restableix", "save": "Desa", "sidebar": { diff --git a/src/assets/locales/cs.json b/src/assets/locales/cs.json index 1a6ea086..54f23e05 100644 --- a/src/assets/locales/cs.json +++ b/src/assets/locales/cs.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "Jazyk aplikace", - "languageDescription": "Jazyk použitý na celou aplikaci.", - "title": "Lokální" - }, "reset": "Resetovat", "save": "Uložit", "sidebar": { diff --git a/src/assets/locales/de.json b/src/assets/locales/de.json index 6b5b46f1..c6588f36 100644 --- a/src/assets/locales/de.json +++ b/src/assets/locales/de.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "App-Sprache", - "languageDescription": "Sprache für die ganze App.", - "title": "Sprache" - }, "reset": "Zurücksetzen", "save": "Speichern", "sidebar": { diff --git a/src/assets/locales/el.json b/src/assets/locales/el.json index 062ac419..3793e316 100644 --- a/src/assets/locales/el.json +++ b/src/assets/locales/el.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "Γλώσσα εφαρμογής", - "languageDescription": "Γλώσσα που εφαρμόζεται σε ολόκληρη την εφαρμογή.", - "title": "Τοποθεσία" - }, "reset": "Επαναφορά", "save": "Αποθήκευση", "sidebar": { diff --git a/src/assets/locales/es.json b/src/assets/locales/es.json index c0cd4246..075dd58a 100644 --- a/src/assets/locales/es.json +++ b/src/assets/locales/es.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "Idioma de la aplicación", - "languageDescription": "Idioma aplicado a toda la aplicación.", - "title": "Idioma" - }, "reset": "Restablecer", "save": "Guardar", "sidebar": { diff --git a/src/assets/locales/et.json b/src/assets/locales/et.json index 0663d58d..48280d66 100644 --- a/src/assets/locales/et.json +++ b/src/assets/locales/et.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "Rakenduse keel", - "languageDescription": "Keel on rakendatud kogu rakendusele.", - "title": "Lokaal" - }, "reset": "Lähtesta", "save": "Salvesta", "sidebar": { diff --git a/src/assets/locales/fa.json b/src/assets/locales/fa.json index bb393cb8..fc9b3906 100644 --- a/src/assets/locales/fa.json +++ b/src/assets/locales/fa.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "زبان", - "languageDescription": "زبانی در کل برنامه اعمال می‌شود.", - "title": "زبان" - }, "reset": "بازنشانی", "save": "ذخیره", "sidebar": { diff --git a/src/assets/locales/fr.json b/src/assets/locales/fr.json index 482f3cfb..6234126f 100644 --- a/src/assets/locales/fr.json +++ b/src/assets/locales/fr.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "Langue de l'application", - "languageDescription": "Langue appliquée dans l'ensemble de l'app.", - "title": "Local" - }, "reset": "Réinitialiser", "save": "Sauvegarder", "sidebar": { diff --git a/src/assets/locales/gl.json b/src/assets/locales/gl.json index 8d36470a..37218b8b 100644 --- a/src/assets/locales/gl.json +++ b/src/assets/locales/gl.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "Lingua da aplicación", - "languageDescription": "Lingua empregada en toda aplicación.", - "title": "Local" - }, "reset": "Reinicio", "save": "Gardar", "sidebar": { diff --git a/src/assets/locales/gu.json b/src/assets/locales/gu.json index b1a857ea..03974f70 100644 --- a/src/assets/locales/gu.json +++ b/src/assets/locales/gu.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "એપ્લિકેશન ભાષા", - "languageDescription": "સમગ્ર એપ્લિકેશન પર લાગુ ભાષા.", - "title": "સ્થળ" - }, "reset": "રીસેટ કરો", "save": "સાચવો", "sidebar": { diff --git a/src/assets/locales/he.json b/src/assets/locales/he.json index 10cef7af..a0ce15ce 100644 --- a/src/assets/locales/he.json +++ b/src/assets/locales/he.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "שפת האפליקציה", - "languageDescription": "השפה החלה על האפליקציה כולה.", - "title": "מקומי" - }, "reset": "איפוס", "save": "לשמור", "sidebar": { diff --git a/src/assets/locales/hi.json b/src/assets/locales/hi.json index 7ff5f443..944538c2 100644 --- a/src/assets/locales/hi.json +++ b/src/assets/locales/hi.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "अनुप्रयोग भाषा", - "languageDescription": "भाषा संपूर्ण अनुप्रयोग पर लागू होती है।", - "title": "स्थानीय" - }, "reset": "रीसेट", "save": "सेव", "sidebar": { diff --git a/src/assets/locales/id.json b/src/assets/locales/id.json index 08e19bfd..e542c475 100644 --- a/src/assets/locales/id.json +++ b/src/assets/locales/id.json @@ -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": { diff --git a/src/assets/locales/it.json b/src/assets/locales/it.json index 1b58f0c2..0074098f 100644 --- a/src/assets/locales/it.json +++ b/src/assets/locales/it.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "Lingua di applicazione", - "languageDescription": "Lingua applicata all'intera applicazione.", - "title": "Località" - }, "reset": "Reset", "save": "Salva", "sidebar": { diff --git a/src/assets/locales/ko.json b/src/assets/locales/ko.json index 7d3fd3f9..459ad986 100644 --- a/src/assets/locales/ko.json +++ b/src/assets/locales/ko.json @@ -378,11 +378,6 @@ "urlLabel": "워커 URL" } }, - "locale": { - "language": "애플리케이션 언어", - "languageDescription": "전체 애플리케이션에 적용되는 언어입니다.", - "title": "지" - }, "reset": "초기화", "save": "저장", "sidebar": { diff --git a/src/assets/locales/lv.json b/src/assets/locales/lv.json index de2ad471..0d5b3c99 100644 --- a/src/assets/locales/lv.json +++ b/src/assets/locales/lv.json @@ -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": { diff --git a/src/assets/locales/minion.json b/src/assets/locales/minion.json index b3f6cf4d..d69836ff 100644 --- a/src/assets/locales/minion.json +++ b/src/assets/locales/minion.json @@ -404,11 +404,6 @@ "urlPlaceholder": "banana://" } }, - "locale": { - "language": "Banana", - "languageDescription": "Banana applied to the entire banana.", - "title": "Banana" - }, "reset": "Banana", "save": "Banana", "sidebar": { diff --git a/src/assets/locales/ne.json b/src/assets/locales/ne.json index 0c0ddf8f..5046e60e 100644 --- a/src/assets/locales/ne.json +++ b/src/assets/locales/ne.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "एपको भाषा", - "languageDescription": "सम्पूर्ण अनुप्रयोगमा भाषा लागू गरियो।", - "title": "भाषा" - }, "reset": "रिसेट गर्नुहोस्", "save": "सेभ गर्नुहोस्", "sidebar": { diff --git a/src/assets/locales/nl.json b/src/assets/locales/nl.json index 16f350e5..28f2a20e 100644 --- a/src/assets/locales/nl.json +++ b/src/assets/locales/nl.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "Applicatietaal", - "languageDescription": "Taal wordt toegepast op de hele applicatie.", - "title": "Lokaal" - }, "reset": "Resetten", "save": "Wijzigingen opslaan", "sidebar": { diff --git a/src/assets/locales/pirate.json b/src/assets/locales/pirate.json index a42e8398..c6868b03 100644 --- a/src/assets/locales/pirate.json +++ b/src/assets/locales/pirate.json @@ -375,11 +375,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "Application language", - "languageDescription": "Language applied to the entire application.", - "title": "Locale" - }, "reset": "Reset", "save": "Save", "sidebar": { diff --git a/src/assets/locales/pl.json b/src/assets/locales/pl.json index 2ecaac84..312bfd07 100644 --- a/src/assets/locales/pl.json +++ b/src/assets/locales/pl.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "Język aplikacji", - "languageDescription": "Język zastosowany do całej aplikacji.", - "title": "Ustawienia regionalne" - }, "reset": "Reset", "save": "Zapisz", "sidebar": { diff --git a/src/assets/locales/pt-BR.json b/src/assets/locales/pt-BR.json index 88fa296f..ec76f7f6 100644 --- a/src/assets/locales/pt-BR.json +++ b/src/assets/locales/pt-BR.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "Idioma do aplicativo", - "languageDescription": "Idioma aplicado a todo o aplicativo.", - "title": "Região" - }, "reset": "Redefinir", "save": "Salvar", "sidebar": { diff --git a/src/assets/locales/pt-PT.json b/src/assets/locales/pt-PT.json index c1bc2e29..d5288b0a 100644 --- a/src/assets/locales/pt-PT.json +++ b/src/assets/locales/pt-PT.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "Idioma da aplicação", - "languageDescription": "Idioma aplicado a toda a aplicação.", - "title": "Localidade" - }, "reset": "Repor", "save": "Guardar", "sidebar": { diff --git a/src/assets/locales/ro.json b/src/assets/locales/ro.json index 6944648e..961526f6 100644 --- a/src/assets/locales/ro.json +++ b/src/assets/locales/ro.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "Limba aplicației", - "languageDescription": "Limbajul aplicat întregii aplicații.", - "title": "Local" - }, "reset": "Resetare", "save": "Salvează", "sidebar": { diff --git a/src/assets/locales/ru.json b/src/assets/locales/ru.json index 40c0e182..c547bba2 100644 --- a/src/assets/locales/ru.json +++ b/src/assets/locales/ru.json @@ -287,11 +287,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "Язык приложения", - "languageDescription": "Язык применяется ко всему приложению.", - "title": "Локализация" - }, "reset": "Сброс", "save": "Сохранить", "sidebar": { diff --git a/src/assets/locales/sl.json b/src/assets/locales/sl.json index 1bc86e22..2c2f6657 100644 --- a/src/assets/locales/sl.json +++ b/src/assets/locales/sl.json @@ -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": { diff --git a/src/assets/locales/sv.json b/src/assets/locales/sv.json index f5cc4f50..94263b93 100644 --- a/src/assets/locales/sv.json +++ b/src/assets/locales/sv.json @@ -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": { diff --git a/src/assets/locales/th.json b/src/assets/locales/th.json index 79b31e30..7f0f4943 100644 --- a/src/assets/locales/th.json +++ b/src/assets/locales/th.json @@ -389,11 +389,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "ภาษา", - "languageDescription": "ภาษาที่ใช้กับแอปพลิเคชันทั้งหมด", - "title": "ตำแหน่งที่ตั้ง" - }, "reset": "เริ่มใหม่", "save": "บันทึก", "sidebar": { diff --git a/src/assets/locales/tok.json b/src/assets/locales/tok.json index 074798f2..5fa05c9a 100644 --- a/src/assets/locales/tok.json +++ b/src/assets/locales/tok.json @@ -382,11 +382,6 @@ }, "title": "kulupu" }, - "locale": { - "language": "toki ilo", - "languageDescription": "ilo li toki kepeken toki ni:", - "title": "toki" - }, "reset": "o weka e ante", "save": "o ante", "subtitles": { diff --git a/src/assets/locales/tr.json b/src/assets/locales/tr.json index 9b05e84c..dd87cadb 100644 --- a/src/assets/locales/tr.json +++ b/src/assets/locales/tr.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "Uygulama dili", - "languageDescription": "Uygulamanın tamamına uygulanan dil.", - "title": "Yerelleştirme" - }, "reset": "Sıfırla", "save": "Kaydet", "sidebar": { diff --git a/src/assets/locales/uk.json b/src/assets/locales/uk.json index 3fbe83d8..2a83b67a 100644 --- a/src/assets/locales/uk.json +++ b/src/assets/locales/uk.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "Мова застосунку", - "languageDescription": "Виберіть мову, яку ви хочете використовувати.", - "title": "Налаштування локації" - }, "reset": "Скинути налаштування", "save": "Зберегти", "sidebar": { diff --git a/src/assets/locales/zh.json b/src/assets/locales/zh.json index 8c3fb69d..03fe3347 100644 --- a/src/assets/locales/zh.json +++ b/src/assets/locales/zh.json @@ -404,11 +404,6 @@ "urlPlaceholder": "https://" } }, - "locale": { - "language": "应用程序语言", - "languageDescription": "当前已应用到整个应用程序的语言。", - "title": "本地化" - }, "reset": "重设", "save": "保存", "sidebar": { From 5bc8fa100e90c3cce272e1c7089126596452154b Mon Sep 17 00:00:00 2001 From: Anonymous Date: Sun, 21 Jan 2024 20:53:24 +0000 Subject: [PATCH 101/151] Translated using Weblate (pirate (generated) (pirate)) Currently translated at 88.9% (226 of 254 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/pirate/ Author: Anonymous --- src/assets/locales/pirate.json | 41 +++++++++++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/src/assets/locales/pirate.json b/src/assets/locales/pirate.json index c6868b03..23d076a7 100644 --- a/src/assets/locales/pirate.json +++ b/src/assets/locales/pirate.json @@ -120,7 +120,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": [ + "" + ] }, "morning": { "default": "What be yer fancy for this mornin's viewing, me heartie?", @@ -176,7 +179,10 @@ "menus": { "downloads": { "disclaimer": "Downloads be taken directly from the provider. movie-web does not have control over how the downloads be provided.", + "downloadPlaylist": "", + "downloadSubtitle": "", "downloadVideo": "Download film", + "hlsDisclaimer": "", "onAndroid": { "1": "To download on Android, tap and hold on the film, then select save.", "shortTitle": "Download / Android", @@ -200,7 +206,8 @@ "episodeBadge": "E{{episode}}", "loadingError": "Error loadin' season", "loadingList": "Loading...", - "loadingTitle": "Loading..." + "loadingTitle": "Loading...", + "unairedEpisodes": "" }, "playback": { "speedLabel": "Playback speed", @@ -239,13 +246,22 @@ "unknownOption": "Unknown" }, "subtitles": { + "customChoice": "", "customizeLabel": "Tailor it to yer liking", + "offChoice": "", "settings": { + "backlink": "", + "delay": "", "fixCapitals": "Mend the capital letters" - } + }, + "unknownLanguage": "" } }, "metadata": { + "api": { + "text": "", + "title": "" + }, "failed": { "badge": "Failed", "homeButton": "Go home port", @@ -284,6 +300,7 @@ }, "notFound": { "badge": "Not found", + "detailsButton": "", "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 +311,23 @@ "remaining": "{{timeLeft}} left • Finish at {{timeFinished, datetime}}", "shortRegular": "{{timeWatched}}", "shortRemaining": "-{{timeLeft}}" + }, + "turnstile": { + "description": "", + "error": "", + "title": "", + "verifyingHumanity": "" } }, "screens": { + "dmca": { + "text": "", + "title": "" + }, "loadingApp": "Loadin' application", "loadingUser": "Loadin' yer pirate profile", "loadingUserError": { + "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?" @@ -391,6 +419,13 @@ "userId": "Pirate ID" } }, + "subtitles": { + "backgroundLabel": "", + "colorLabel": "", + "previewQuote": "", + "textSizeLabel": "", + "title": "" + }, "unsaved": "Ye have unsaved changes" } } From 44350360eb0c84223bbde7be93ff8a3c6af71abd Mon Sep 17 00:00:00 2001 From: Christian Furr Date: Sat, 30 Dec 2023 09:40:55 +0000 Subject: [PATCH 102/151] Translated using Weblate (pirate (generated) (pirate)) Currently translated at 88.9% (226 of 254 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/pirate/ Author: Christian Furr --- src/assets/locales/pirate.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/assets/locales/pirate.json b/src/assets/locales/pirate.json index 23d076a7..adfb6a84 100644 --- a/src/assets/locales/pirate.json +++ b/src/assets/locales/pirate.json @@ -254,6 +254,7 @@ "delay": "", "fixCapitals": "Mend the capital letters" }, + "title": "", "unknownLanguage": "" } }, From 4ae5a17fb1f0ffd22bc7ea1f73a4218f95191c83 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Sun, 21 Jan 2024 20:53:26 +0000 Subject: [PATCH 103/151] Translated using Weblate (Vietnamese) Currently translated at 27.1% (86 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/vi/ Author: Anonymous --- src/assets/locales/vi.json | 379 ++++++++++++++++++++++++++++++++++++- 1 file changed, 376 insertions(+), 3 deletions(-) diff --git a/src/assets/locales/vi.json b/src/assets/locales/vi.json index 098a100d..35a58031 100644 --- a/src/assets/locales/vi.json +++ b/src/assets/locales/vi.json @@ -92,8 +92,13 @@ "global": { "name": "movie-web", "pages": { + "about": "", + "dmca": "", + "login": "", + "onboarding": "", "pagetitle": "{{title}} - movie-web", - "register": "Đăng ký" + "register": "Đăng ký", + "settings": "" } }, "home": { @@ -103,6 +108,9 @@ "continueWatching": { "sectionTitle": "Tiếp tục xem" }, + "mediaList": { + "stopEditing": "" + }, "search": { "allResults": "Đó là tất cả chúng tôi có!", "failed": "Không thể tìm thấy nội dung, hãy thử lại!", @@ -110,6 +118,26 @@ "noResults": "Chúng tôi không thể tìm thấy gì!", "placeholder": "Bạn muốn xem gì?", "sectionTitle": "Kết quả tìm kiếm" + }, + "titles": { + "day": { + "default": "", + "extra": [ + "" + ] + }, + "morning": { + "default": "", + "extra": [ + "" + ] + }, + "night": { + "default": "", + "extra": [ + "" + ] + } } }, "media": { @@ -122,6 +150,14 @@ "navigation": { "banner": { "offline": "Hãy kiểm tra kết nối Internet của bạn" + }, + "menu": { + "about": "", + "donation": "", + "logout": "", + "register": "", + "settings": "", + "support": "" } }, "notFound": { @@ -130,22 +166,180 @@ "message": "Chúng tôi đã tìm kiếm khắp nơi: dưới thùng rác, trong tủ quần áo, đằng sau máy chủ proxy nhưng vẫn không thể tìm thấy trang bạn đang tìm kiếm.", "title": "Không thể tìm thấy trang" }, + "onboarding": { + "defaultConfirm": { + "cancel": "", + "confirm": "", + "description": "", + "title": "" + }, + "extension": { + "back": "", + "explainer": "", + "extensionHelp": "", + "link": "", + "status": { + "disallowed": "", + "disallowedAction": "", + "failed": "", + "loading": "", + "outdated": "", + "success": "" + }, + "submit": "", + "title": "" + }, + "proxy": { + "back": "", + "explainer": "", + "input": { + "errorConnection": "", + "errorInvalidUrl": "", + "errorNotProxy": "", + "label": "", + "placeholder": "" + }, + "link": "", + "submit": "", + "title": "" + }, + "start": { + "explainer": "", + "options": { + "default": { + "text": "" + }, + "extension": { + "action": "", + "description": "", + "quality": "", + "title": "" + }, + "proxy": { + "action": "", + "description": "", + "quality": "", + "title": "" + } + }, + "title": "" + } + }, + "overlays": { + "close": "" + }, "player": { "back": { "default": "Quay lại trang chính", "short": "Quay lại" }, + "casting": { + "enabled": "" + }, "menus": { + "downloads": { + "disclaimer": "", + "downloadPlaylist": "", + "downloadSubtitle": "", + "downloadVideo": "", + "hlsDisclaimer": "", + "onAndroid": { + "1": "", + "shortTitle": "", + "title": "" + }, + "onIos": { + "1": "", + "shortTitle": "", + "title": "" + }, + "onPc": { + "1": "", + "shortTitle": "", + "title": "" + }, + "title": "" + }, "episodes": { "button": "Tập", + "emptyState": "", + "episodeBadge": "", + "loadingError": "", "loadingList": "Đang tải...", - "loadingTitle": "Đang tải..." + "loadingTitle": "Đang tải...", + "unairedEpisodes": "" + }, + "playback": { + "speedLabel": "", + "title": "" + }, + "quality": { + "automaticLabel": "", + "hint": "", + "iosNoQuality": "", + "title": "" + }, + "settings": { + "downloadItem": "", + "enableSubtitles": "", + "experienceSection": "", + "playbackItem": "", + "qualityItem": "", + "sourceItem": "", + "subtitleItem": "", + "videoSection": "" }, "sources": { - "title": "Nguồn" + "failed": { + "text": "", + "title": "" + }, + "noEmbeds": { + "text": "", + "title": "" + }, + "noStream": { + "text": "", + "title": "" + }, + "title": "Nguồn", + "unknownOption": "" + }, + "subtitles": { + "customChoice": "", + "customizeLabel": "", + "offChoice": "", + "settings": { + "backlink": "", + "delay": "", + "fixCapitals": "" + }, + "title": "", + "unknownLanguage": "" } }, "metadata": { + "api": { + "text": "", + "title": "" + }, + "dmca": { + "badge": "", + "text": "", + "title": "" + }, + "extensionPermission": { + "badge": "", + "button": "", + "text": "", + "title": "" + }, + "failed": { + "badge": "", + "homeButton": "", + "text": "", + "title": "" + }, "notFound": { "badge": "Không tìm thấy", "homeButton": "Quay lại trang chính", @@ -153,8 +347,187 @@ "title": "Không thể tìm thấy nội dung." } }, + "nextEpisode": { + "cancel": "", + "next": "" + }, "playbackError": { + "badge": "", + "errors": { + "errorAborted": "", + "errorDecode": "", + "errorGenericMedia": "", + "errorNetwork": "", + "errorNotSupported": "" + }, + "homeButton": "", + "text": "", "title": "Rất tiếc, đã hỏng!" + }, + "scraping": { + "items": { + "failure": "", + "notFound": "", + "pending": "" + }, + "notFound": { + "badge": "", + "detailsButton": "", + "homeButton": "", + "text": "", + "title": "" + } + }, + "time": { + "regular": "", + "remaining": "", + "shortRegular": "", + "shortRemaining": "" + }, + "turnstile": { + "description": "", + "error": "", + "title": "", + "verifyingHumanity": "" } + }, + "screens": { + "dmca": { + "text": "", + "title": "" + }, + "loadingApp": "", + "loadingUser": "", + "loadingUserError": { + "logout": "", + "reset": "", + "text": "", + "textWithReset": "" + }, + "migration": { + "failed": "", + "inProgress": "" + } + }, + "settings": { + "account": { + "accountDetails": { + "deviceNameLabel": "", + "deviceNamePlaceholder": "", + "editProfile": "", + "logoutButton": "" + }, + "actions": { + "delete": { + "button": "", + "confirmButton": "", + "confirmDescription": "", + "confirmTitle": "", + "text": "", + "title": "" + }, + "title": "" + }, + "devices": { + "deviceNameLabel": "", + "failed": "", + "removeDevice": "", + "title": "" + }, + "profile": { + "finish": "", + "firstColor": "", + "secondColor": "", + "title": "", + "userIcon": "" + }, + "register": { + "cta": "", + "text": "", + "title": "" + }, + "title": "" + }, + "appearance": { + "activeTheme": "", + "themes": { + "blue": "", + "default": "", + "gray": "", + "red": "", + "teal": "" + }, + "title": "" + }, + "connections": { + "server": { + "description": "", + "label": "", + "urlLabel": "" + }, + "setup": { + "doSetup": "", + "errorStatus": { + "description": "", + "title": "" + }, + "itemError": "", + "items": { + "default": "", + "extension": "", + "proxy": "" + }, + "redoSetup": "", + "successStatus": { + "description": "", + "title": "" + }, + "unsetStatus": { + "description": "", + "title": "" + } + }, + "title": "", + "workers": { + "addButton": "", + "description": "", + "emptyState": "", + "label": "", + "urlLabel": "", + "urlPlaceholder": "" + } + }, + "preferences": { + "language": "", + "languageDescription": "", + "thumbnail": "", + "thumbnailDescription": "", + "thumbnailLabel": "", + "title": "" + }, + "reset": "", + "save": "", + "sidebar": { + "info": { + "appVersion": "", + "backendUrl": "", + "backendVersion": "", + "hostname": "", + "insecure": "", + "notLoggedIn": "", + "secure": "", + "title": "", + "unknownVersion": "", + "userId": "" + } + }, + "subtitles": { + "backgroundLabel": "", + "colorLabel": "", + "previewQuote": "", + "textSizeLabel": "", + "title": "" + }, + "unsaved": "" } } From 2ee5f0bbab7f5c667336081939c5b3ae859e6329 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Sun, 21 Jan 2024 20:53:28 +0000 Subject: [PATCH 104/151] Translated using Weblate (Thai) Currently translated at 94.4% (240 of 254 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/th/ Author: Anonymous --- src/assets/locales/th.json | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/assets/locales/th.json b/src/assets/locales/th.json index 7f0f4943..0c379317 100644 --- a/src/assets/locales/th.json +++ b/src/assets/locales/th.json @@ -120,7 +120,10 @@ }, "titles": { "day": { - "default": "คุณอยากดูเรื่องอะไรในช่วงบ่ายนี้?" + "default": "คุณอยากดูเรื่องอะไรในช่วงบ่ายนี้?", + "extra": [ + "" + ] }, "morning": { "default": "คุณอยากดูอะไรเช้านี้?", @@ -203,7 +206,8 @@ "episodeBadge": "ตอนที่ {{episode}}", "loadingError": "การโหลดภาคผิดพลาด", "loadingList": "กำลังโหลด…", - "loadingTitle": "กำลังโหลด…" + "loadingTitle": "กำลังโหลด…", + "unairedEpisodes": "" }, "playback": { "speedLabel": "ความเร็วในการเล่น", @@ -247,13 +251,18 @@ "offChoice": "ปิด", "settings": { "backlink": "คำบรรยายแบบกำหนดเอง", - "delay": "เวลาดีเลย์คำบรรยาย" + "delay": "เวลาดีเลย์คำบรรยาย", + "fixCapitals": "" }, "title": "คำบรรยาย", "unknownLanguage": "ไม่ทราบ" } }, "metadata": { + "api": { + "text": "", + "title": "" + }, "failed": { "badge": "ล้มเหลว", "homeButton": "กลับหน้าหลัก", @@ -303,6 +312,12 @@ "remaining": "{{timeLeft}} หมดเวลา • สิ้นสุดใน {{timeFinished, datetime}}", "shortRegular": "{{timeWatched}}", "shortRemaining": "-{{timeLeft}}" + }, + "turnstile": { + "description": "", + "error": "", + "title": "", + "verifyingHumanity": "" } }, "screens": { From f786b087e5ecd4c5c022128a06d1eff91f921571 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Sun, 21 Jan 2024 20:53:30 +0000 Subject: [PATCH 105/151] Translated using Weblate (Swedish) Currently translated at 88.5% (225 of 254 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/sv/ Author: Anonymous --- src/assets/locales/sv.json | 43 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/sv.json b/src/assets/locales/sv.json index 94263b93..70f6fcd0 100644 --- a/src/assets/locales/sv.json +++ b/src/assets/locales/sv.json @@ -27,6 +27,7 @@ "generate": { "description": "Ditt lösenord fungerar som ditt användarnamn och lösenord. Se till att hålla det säkert eftersom du behöver ange det för att logga in på ditt konto", "next": "Jag har sparat mitt lösenord", + "passphraseFrameLabel": "", "title": "Ditt lösenord" }, "hasAccount": "Har redan ett konto? <0>Logga in här.", @@ -119,7 +120,10 @@ }, "titles": { "day": { - "default": "Vad vill du titta på i eftermiddag?" + "default": "Vad vill du titta på i eftermiddag?", + "extra": [ + "" + ] }, "morning": { "default": "Vad vill du titta på den här morgonen?", @@ -175,7 +179,10 @@ "menus": { "downloads": { "disclaimer": "Nedladdningar görs direkt från leverantören. movie-web har ingen kontroll över hur nedladdningarna tillhandahålls.", + "downloadPlaylist": "", + "downloadSubtitle": "", "downloadVideo": "Ladda ner video", + "hlsDisclaimer": "", "onAndroid": { "1": "För att ladda ner på Android, klicka på nedladdningsknappen och på den nya sidan trycker och håller på videon, välj sedan spara.", "shortTitle": "Ladda ner / Android", @@ -199,7 +206,8 @@ "episodeBadge": "E{{episode}}", "loadingError": "Fel vid laddning av säsong", "loadingList": "Laddar...", - "loadingTitle": "Laddar..." + "loadingTitle": "Laddar...", + "unairedEpisodes": "" }, "playback": { "speedLabel": "Uppspelningshastighet", @@ -213,10 +221,12 @@ }, "settings": { "downloadItem": "Ladda ner", + "enableSubtitles": "", "experienceSection": "Visningsupplevelse", "playbackItem": "Uppspelningsinställningar", "qualityItem": "Kvalitet", "sourceItem": "Videokällor", + "subtitleItem": "", "videoSection": "Videoinställningar" }, "sources": { @@ -234,9 +244,25 @@ }, "title": "Källor", "unknownOption": "Okänd" + }, + "subtitles": { + "customChoice": "", + "customizeLabel": "", + "offChoice": "", + "settings": { + "backlink": "", + "delay": "", + "fixCapitals": "" + }, + "title": "", + "unknownLanguage": "" } }, "metadata": { + "api": { + "text": "", + "title": "" + }, "failed": { "badge": "Misslyckades", "homeButton": "Till startsidan", @@ -286,6 +312,12 @@ "remaining": "{{timeLeft}} kvar • Slutar kl {{timeFinished, datetime}}", "shortRegular": "{{timeWatched}}", "shortRemaining": "-{{timeLeft}}" + }, + "turnstile": { + "description": "", + "error": "", + "title": "", + "verifyingHumanity": "" } }, "screens": { @@ -388,6 +420,13 @@ "userId": "Användar-ID" } }, + "subtitles": { + "backgroundLabel": "", + "colorLabel": "", + "previewQuote": "", + "textSizeLabel": "", + "title": "" + }, "unsaved": "Du har osparade ändringar" } } From ca3d655725967da880b84ddc113227b4aeb4eb58 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Sun, 21 Jan 2024 20:53:31 +0000 Subject: [PATCH 106/151] Translated using Weblate (Latvian) Currently translated at 88.5% (225 of 254 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/lv/ Author: Anonymous --- src/assets/locales/lv.json | 43 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/lv.json b/src/assets/locales/lv.json index 0d5b3c99..e650d5c8 100644 --- a/src/assets/locales/lv.json +++ b/src/assets/locales/lv.json @@ -27,6 +27,7 @@ "generate": { "description": "Tava paroles frāze ir kā vārds un parole. Esi drošs ka turi to drošibā jo tev vajadzēs to izmantot lai ieietu kontā", "next": "Esmu saglabājis paroles frāzi", + "passphraseFrameLabel": "", "title": "Tava paroles frāze" }, "hasAccount": "Tev jau ir konts> <0>Ienāc šeit.", @@ -119,7 +120,10 @@ }, "titles": { "day": { - "default": "Ko jūs vēlētos noskatīties šajā pēcpusdienā?" + "default": "Ko jūs vēlētos noskatīties šajā pēcpusdienā?", + "extra": [ + "" + ] }, "morning": { "default": "Ko tu gribētu šorīt noskatīties?", @@ -175,7 +179,10 @@ "menus": { "downloads": { "disclaimer": "Lejupielādes tiek ņemtas tieši no pakalpojumu sniedzēja. Movie-web nevar kontrolēt, kā tiek nodrošinātas lejupielādes.", + "downloadPlaylist": "", + "downloadSubtitle": "", "downloadVideo": "Lejupielādēt video", + "hlsDisclaimer": "", "onAndroid": { "1": "Lai lejupielādētu operētājsistēmā Android, noklikšķiniet uz lejupielādes pogas, pēc tam jaunajā lapā pieskarieties videoklipam un turiet to, pēc tam atlasiet saglabāt.", "shortTitle": "Lejupielādēt / Android", @@ -199,7 +206,8 @@ "episodeBadge": "E{{episode}}", "loadingError": "Kļūda ladējot sezonu", "loadingList": "Lādejas...", - "loadingTitle": "Lādejas..." + "loadingTitle": "Lādejas...", + "unairedEpisodes": "" }, "playback": { "speedLabel": "Atskaņošana ātrums", @@ -213,10 +221,12 @@ }, "settings": { "downloadItem": "Lejupladēt", + "enableSubtitles": "", "experienceSection": "Skatīšanās pieredze", "playbackItem": "Atskaņošana iestādijumi", "qualityItem": "Kvalitāte", "sourceItem": "Video avoti", + "subtitleItem": "", "videoSection": "Video iestādijumi" }, "sources": { @@ -234,9 +244,25 @@ }, "title": "Avoti", "unknownOption": "Nezināms" + }, + "subtitles": { + "customChoice": "", + "customizeLabel": "", + "offChoice": "", + "settings": { + "backlink": "", + "delay": "", + "fixCapitals": "" + }, + "title": "", + "unknownLanguage": "" } }, "metadata": { + "api": { + "text": "", + "title": "" + }, "failed": { "badge": "Neizdevās", "homeButton": "iet uz majām", @@ -286,6 +312,12 @@ "remaining": "{{timeLeft}} beidza • pabeidza {{timeFinished, datetime}}", "shortRegular": "{{timeWatched}}", "shortRemaining": "-{{timeLeft}}" + }, + "turnstile": { + "description": "", + "error": "", + "title": "", + "verifyingHumanity": "" } }, "screens": { @@ -388,6 +420,13 @@ "userId": "Lietotāja ID" } }, + "subtitles": { + "backgroundLabel": "", + "colorLabel": "", + "previewQuote": "", + "textSizeLabel": "", + "title": "" + }, "unsaved": "Jums ir nesaglabātas izmaiņas" } } From c23f9407044c644da19d52ff8cc296b3fef52253 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 15 Jan 2024 20:04:33 +0000 Subject: [PATCH 107/151] Translated using Weblate (Arabic) Currently translated at 96.8% (246 of 254 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ar/ Author: Anonymous --- src/assets/locales/ar.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/assets/locales/ar.json b/src/assets/locales/ar.json index 6138644c..bfc21e70 100644 --- a/src/assets/locales/ar.json +++ b/src/assets/locales/ar.json @@ -259,6 +259,10 @@ } }, "metadata": { + "api": { + "text": "", + "title": "" + }, "failed": { "badge": "فشل", "homeButton": "عُدْ للصفحة الرئيسية", @@ -308,6 +312,12 @@ "remaining": "باقٍ {{timeLeft}} • سينتهي مع {{timeFinished, datetime}}", "shortRegular": "{{timeWatched}}", "shortRemaining": "-{{timeLeft}}" + }, + "turnstile": { + "description": "", + "error": "", + "title": "", + "verifyingHumanity": "" } }, "screens": { From 9d9a0f1cbef097cb390408bfc5696bd414530ee5 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Sun, 21 Jan 2024 20:53:34 +0000 Subject: [PATCH 108/151] Translated using Weblate (Toki Pona) Currently translated at 89.3% (227 of 254 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/tok/ Author: Anonymous --- src/assets/locales/tok.json | 42 ++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/src/assets/locales/tok.json b/src/assets/locales/tok.json index 5fa05c9a..ac59f2b4 100644 --- a/src/assets/locales/tok.json +++ b/src/assets/locales/tok.json @@ -79,7 +79,8 @@ }, "footer": { "legal": { - "disclaimer": "o sona e ni:" + "disclaimer": "o sona e ni:", + "disclaimerText": "" }, "links": { "discord": "kulupu Siko", @@ -205,7 +206,8 @@ "episodeBadge": "E{{episode}}", "loadingError": "alasa li pakala", "loadingList": "alasa...", - "loadingTitle": "alasa..." + "loadingTitle": "alasa...", + "unairedEpisodes": "" }, "playback": { "speedLabel": "tenpo lukin", @@ -257,6 +259,10 @@ } }, "metadata": { + "api": { + "text": "", + "title": "" + }, "failed": { "badge": "pakala", "homeButton": "o tawa weka", @@ -306,10 +312,17 @@ "remaining": "tenpo {{timeLeft}} la o awen • tenpo {{timeFinished, datetime}} la ona li pini", "shortRegular": "{{timeWatched}}", "shortRemaining": "-{{timeLeft}}" + }, + "turnstile": { + "description": "", + "error": "", + "title": "", + "verifyingHumanity": "" } }, "screens": { "dmca": { + "text": "", "title": "DMCA" }, "loadingApp": "mi alasa e ilo", @@ -321,6 +334,7 @@ "textWithReset": "alasa tan lawa ilo sina li pakala. sina wile e lawa ilo mi anu seme?" }, "migration": { + "failed": "", "inProgress": "o awen lili. mi alasa tawa e sona sina" } }, @@ -380,10 +394,32 @@ "label": "lawa ante", "urlLabel": "nimi pi lawa ante" }, - "title": "kulupu" + "title": "kulupu", + "workers": { + "addButton": "", + "description": "", + "emptyState": "", + "label": "", + "urlLabel": "", + "urlPlaceholder": "" + } }, "reset": "o weka e ante", "save": "o ante", + "sidebar": { + "info": { + "appVersion": "", + "backendUrl": "", + "backendVersion": "", + "hostname": "", + "insecure": "", + "notLoggedIn": "", + "secure": "", + "title": "", + "unknownVersion": "", + "userId": "" + } + }, "subtitles": { "backgroundLabel": "kon", "colorLabel": "kule", From 56495bd653fbef6136d696379398f905741124a0 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Sun, 21 Jan 2024 20:53:35 +0000 Subject: [PATCH 109/151] Translated using Weblate (Russian) Currently translated at 67.3% (171 of 254 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ru/ Author: Anonymous --- src/assets/locales/ru.json | 133 ++++++++++++++++++++++++++++++++++--- 1 file changed, 125 insertions(+), 8 deletions(-) diff --git a/src/assets/locales/ru.json b/src/assets/locales/ru.json index c547bba2..66fdcae5 100644 --- a/src/assets/locales/ru.json +++ b/src/assets/locales/ru.json @@ -71,6 +71,7 @@ } }, "errors": { + "badge": "", "details": "Подробности ошибки", "reloadPage": "Перезагрузить страницу", "showError": "Показать сведения об ошибке", @@ -93,7 +94,9 @@ "pages": { "about": "О", "dmca": "DMCA", + "login": "", "pagetitle": "{{title}} - movie-web", + "register": "", "settings": "Настройки" } }, @@ -109,8 +112,31 @@ }, "search": { "allResults": "Это все, что у нас есть!", + "failed": "", "loading": "Загрузка...", + "noResults": "", + "placeholder": "", "sectionTitle": "Результаты поиска" + }, + "titles": { + "day": { + "default": "", + "extra": [ + "" + ] + }, + "morning": { + "default": "", + "extra": [ + "" + ] + }, + "night": { + "default": "", + "extra": [ + "" + ] + } } }, "media": { @@ -128,11 +154,15 @@ "about": "О нас", "donation": "Пожертвовать", "logout": "Выйти", + "register": "", "settings": "Настройки", "support": "Поддержка" } }, "notFound": { + "badge": "", + "goHome": "", + "message": "", "title": "Не удалось найти эту страницу" }, "overlays": { @@ -140,11 +170,34 @@ }, "player": { "back": { - "default": "Вернуться на главную" + "default": "Вернуться на главную", + "short": "" + }, + "casting": { + "enabled": "" }, "menus": { "downloads": { + "disclaimer": "", + "downloadPlaylist": "", "downloadSubtitle": "Скачать текущие субтитры", + "downloadVideo": "", + "hlsDisclaimer": "", + "onAndroid": { + "1": "", + "shortTitle": "", + "title": "" + }, + "onIos": { + "1": "", + "shortTitle": "", + "title": "" + }, + "onPc": { + "1": "", + "shortTitle": "", + "title": "" + }, "title": "Скачать" }, "episodes": { @@ -153,18 +206,23 @@ "episodeBadge": "Э{{episode}}", "loadingError": "Ошибка при загрузке сезона", "loadingList": "Загрузка...", - "loadingTitle": "Загрузка..." + "loadingTitle": "Загрузка...", + "unairedEpisodes": "" }, "playback": { "speedLabel": "Скорость воспроизведения", "title": "Настройки воспроизведения" }, "quality": { - "automaticLabel": "Автоматическое качество" + "automaticLabel": "Автоматическое качество", + "hint": "", + "iosNoQuality": "", + "title": "" }, "settings": { "downloadItem": "Скачать", "enableSubtitles": "Включить субтитры", + "experienceSection": "", "playbackItem": "Настройки воспроизведения", "qualityItem": "Качество", "sourceItem": "Видео источники", @@ -173,7 +231,8 @@ }, "sources": { "failed": { - "text": "При попытке найти видео произошла ошибка, пожалуйста, попробуйте использовать другой источник." + "text": "При попытке найти видео произошла ошибка, пожалуйста, попробуйте использовать другой источник.", + "title": "" }, "noEmbeds": { "text": "Мы не смогли найти ни одной вставки, пожалуйста, попробуйте использовать другой источник.", @@ -188,11 +247,33 @@ }, "subtitles": { "customChoice": "Выбрать субтитры из файла", + "customizeLabel": "", "offChoice": "Выключить", "settings": { - "backlink": "Пользовательские субтитры" + "backlink": "Пользовательские субтитры", + "delay": "", + "fixCapitals": "" }, - "title": "Субтитры" + "title": "Субтитры", + "unknownLanguage": "" + } + }, + "metadata": { + "api": { + "text": "", + "title": "" + }, + "failed": { + "badge": "", + "homeButton": "", + "text": "", + "title": "" + }, + "notFound": { + "badge": "", + "homeButton": "", + "text": "", + "title": "" } }, "nextEpisode": { @@ -202,30 +283,66 @@ "playbackError": { "badge": "Ошибка воспроизведения", "errors": { - "errorDecode": "Несмотря на то, что ранее этот медиаресурс был пригодным для использования, при попытке его декодирования произошла ошибка." + "errorAborted": "", + "errorDecode": "Несмотря на то, что ранее этот медиаресурс был пригодным для использования, при попытке его декодирования произошла ошибка.", + "errorGenericMedia": "", + "errorNetwork": "", + "errorNotSupported": "" }, + "homeButton": "", "text": "При попытке воспроизвести медиа файл произошла ошибка. Пожалуйста, попробуйте ещё раз.", "title": "Не удалось воспроизвести видео!" }, "scraping": { + "items": { + "failure": "", + "notFound": "", + "pending": "" + }, "notFound": { + "badge": "", "detailsButton": "Показать детали", + "homeButton": "", + "text": "", "title": "Мы не смогли найти" } }, "time": { - "regular": "{{timeWatched}} / {{duration}}" + "regular": "{{timeWatched}} / {{duration}}", + "remaining": "", + "shortRegular": "", + "shortRemaining": "" + }, + "turnstile": { + "description": "", + "error": "", + "title": "", + "verifyingHumanity": "" } }, "screens": { "dmca": { + "text": "", "title": "DMCA" + }, + "loadingApp": "", + "loadingUser": "", + "loadingUserError": { + "logout": "", + "reset": "", + "text": "", + "textWithReset": "" + }, + "migration": { + "failed": "", + "inProgress": "" } }, "settings": { "account": { "accountDetails": { "deviceNameLabel": "Имя устройства", + "deviceNamePlaceholder": "", "editProfile": "Редактировать", "logoutButton": "Выйти" }, From d5454b4976e4e7ab4f9ea909b8bd642ccafd419b Mon Sep 17 00:00:00 2001 From: Anonymous Date: Sun, 21 Jan 2024 20:53:36 +0000 Subject: [PATCH 110/151] Translated using Weblate (Khmer (Central)) Currently translated at 6.3% (20 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/km/ Author: Anonymous --- src/assets/locales/km.json | 497 ++++++++++++++++++++++++++++++++++++- 1 file changed, 496 insertions(+), 1 deletion(-) diff --git a/src/assets/locales/km.json b/src/assets/locales/km.json index 121b32e8..0a82e14e 100644 --- a/src/assets/locales/km.json +++ b/src/assets/locales/km.json @@ -7,6 +7,7 @@ "title": "តើមាតិកាបានមកពីណា?" }, "q2": { + "body": "", "title": "តើខ្ញុំអាចស្នើសុំកម្មវិធី ឬ ភាពយន្តបាននៅឯណា?" }, "q3": { @@ -32,7 +33,501 @@ "hasAccount": "មានគណនីរួចហើយ? <0>ចូលទីនេះ", "login": { "description": "សូមបញ្ចូលឃ្លាសម្ងាត់របស់អ្នក ដើម្បីចូលគណនីរបស់អ្នក", - "deviceLengthError": "សូមបញ្ចូលឈ្មោះឧបករណ៍" + "deviceLengthError": "សូមបញ្ចូលឈ្មោះឧបករណ៍", + "passphraseLabel": "", + "passphrasePlaceholder": "", + "submit": "", + "title": "", + "validationError": "" + }, + "register": { + "information": { + "color1": "", + "color2": "", + "header": "", + "icon": "", + "next": "", + "title": "" + } + }, + "trust": { + "failed": { + "text": "", + "title": "" + }, + "host": "", + "no": "", + "title": "", + "yes": "" + }, + "verify": { + "description": "", + "invalidData": "", + "noMatch": "", + "passphraseLabel": "", + "recaptchaFailed": "", + "register": "", + "title": "" } + }, + "errors": { + "badge": "", + "details": "", + "reloadPage": "", + "showError": "", + "title": "" + }, + "footer": { + "legal": { + "disclaimer": "", + "disclaimerText": "" + }, + "links": { + "discord": "", + "dmca": "", + "github": "" + }, + "tagline": "" + }, + "global": { + "name": "", + "pages": { + "about": "", + "dmca": "", + "login": "", + "onboarding": "", + "pagetitle": "", + "register": "", + "settings": "" + } + }, + "home": { + "bookmarks": { + "sectionTitle": "" + }, + "continueWatching": { + "sectionTitle": "" + }, + "mediaList": { + "stopEditing": "" + }, + "search": { + "allResults": "", + "failed": "", + "loading": "", + "noResults": "", + "placeholder": "", + "sectionTitle": "" + }, + "titles": { + "day": { + "default": "", + "extra": [ + "" + ] + }, + "morning": { + "default": "", + "extra": [ + "" + ] + }, + "night": { + "default": "", + "extra": [ + "" + ] + } + } + }, + "media": { + "episodeDisplay": "", + "types": { + "movie": "", + "show": "" + } + }, + "navigation": { + "banner": { + "offline": "" + }, + "menu": { + "about": "", + "donation": "", + "logout": "", + "register": "", + "settings": "", + "support": "" + } + }, + "notFound": { + "badge": "", + "goHome": "", + "message": "", + "title": "" + }, + "onboarding": { + "defaultConfirm": { + "cancel": "", + "confirm": "", + "description": "", + "title": "" + }, + "extension": { + "back": "", + "explainer": "", + "extensionHelp": "", + "link": "", + "status": { + "disallowed": "", + "disallowedAction": "", + "failed": "", + "loading": "", + "outdated": "", + "success": "" + }, + "submit": "", + "title": "" + }, + "proxy": { + "back": "", + "explainer": "", + "input": { + "errorConnection": "", + "errorInvalidUrl": "", + "errorNotProxy": "", + "label": "", + "placeholder": "" + }, + "link": "", + "submit": "", + "title": "" + }, + "start": { + "explainer": "", + "options": { + "default": { + "text": "" + }, + "extension": { + "action": "", + "description": "", + "quality": "", + "title": "" + }, + "proxy": { + "action": "", + "description": "", + "quality": "", + "title": "" + } + }, + "title": "" + } + }, + "overlays": { + "close": "" + }, + "player": { + "back": { + "default": "", + "short": "" + }, + "casting": { + "enabled": "" + }, + "menus": { + "downloads": { + "disclaimer": "", + "downloadPlaylist": "", + "downloadSubtitle": "", + "downloadVideo": "", + "hlsDisclaimer": "", + "onAndroid": { + "1": "", + "shortTitle": "", + "title": "" + }, + "onIos": { + "1": "", + "shortTitle": "", + "title": "" + }, + "onPc": { + "1": "", + "shortTitle": "", + "title": "" + }, + "title": "" + }, + "episodes": { + "button": "", + "emptyState": "", + "episodeBadge": "", + "loadingError": "", + "loadingList": "", + "loadingTitle": "", + "unairedEpisodes": "" + }, + "playback": { + "speedLabel": "", + "title": "" + }, + "quality": { + "automaticLabel": "", + "hint": "", + "iosNoQuality": "", + "title": "" + }, + "settings": { + "downloadItem": "", + "enableSubtitles": "", + "experienceSection": "", + "playbackItem": "", + "qualityItem": "", + "sourceItem": "", + "subtitleItem": "", + "videoSection": "" + }, + "sources": { + "failed": { + "text": "", + "title": "" + }, + "noEmbeds": { + "text": "", + "title": "" + }, + "noStream": { + "text": "", + "title": "" + }, + "title": "", + "unknownOption": "" + }, + "subtitles": { + "customChoice": "", + "customizeLabel": "", + "offChoice": "", + "settings": { + "backlink": "", + "delay": "", + "fixCapitals": "" + }, + "title": "", + "unknownLanguage": "" + } + }, + "metadata": { + "api": { + "text": "", + "title": "" + }, + "dmca": { + "badge": "", + "text": "", + "title": "" + }, + "extensionPermission": { + "badge": "", + "button": "", + "text": "", + "title": "" + }, + "failed": { + "badge": "", + "homeButton": "", + "text": "", + "title": "" + }, + "notFound": { + "badge": "", + "homeButton": "", + "text": "", + "title": "" + } + }, + "nextEpisode": { + "cancel": "", + "next": "" + }, + "playbackError": { + "badge": "", + "errors": { + "errorAborted": "", + "errorDecode": "", + "errorGenericMedia": "", + "errorNetwork": "", + "errorNotSupported": "" + }, + "homeButton": "", + "text": "", + "title": "" + }, + "scraping": { + "items": { + "failure": "", + "notFound": "", + "pending": "" + }, + "notFound": { + "badge": "", + "detailsButton": "", + "homeButton": "", + "text": "", + "title": "" + } + }, + "time": { + "regular": "", + "remaining": "", + "shortRegular": "", + "shortRemaining": "" + }, + "turnstile": { + "description": "", + "error": "", + "title": "", + "verifyingHumanity": "" + } + }, + "screens": { + "dmca": { + "text": "", + "title": "" + }, + "loadingApp": "", + "loadingUser": "", + "loadingUserError": { + "logout": "", + "reset": "", + "text": "", + "textWithReset": "" + }, + "migration": { + "failed": "", + "inProgress": "" + } + }, + "settings": { + "account": { + "accountDetails": { + "deviceNameLabel": "", + "deviceNamePlaceholder": "", + "editProfile": "", + "logoutButton": "" + }, + "actions": { + "delete": { + "button": "", + "confirmButton": "", + "confirmDescription": "", + "confirmTitle": "", + "text": "", + "title": "" + }, + "title": "" + }, + "devices": { + "deviceNameLabel": "", + "failed": "", + "removeDevice": "", + "title": "" + }, + "profile": { + "finish": "", + "firstColor": "", + "secondColor": "", + "title": "", + "userIcon": "" + }, + "register": { + "cta": "", + "text": "", + "title": "" + }, + "title": "" + }, + "appearance": { + "activeTheme": "", + "themes": { + "blue": "", + "default": "", + "gray": "", + "red": "", + "teal": "" + }, + "title": "" + }, + "connections": { + "server": { + "description": "", + "label": "", + "urlLabel": "" + }, + "setup": { + "doSetup": "", + "errorStatus": { + "description": "", + "title": "" + }, + "itemError": "", + "items": { + "default": "", + "extension": "", + "proxy": "" + }, + "redoSetup": "", + "successStatus": { + "description": "", + "title": "" + }, + "unsetStatus": { + "description": "", + "title": "" + } + }, + "title": "", + "workers": { + "addButton": "", + "description": "", + "emptyState": "", + "label": "", + "urlLabel": "", + "urlPlaceholder": "" + } + }, + "preferences": { + "language": "", + "languageDescription": "", + "thumbnail": "", + "thumbnailDescription": "", + "thumbnailLabel": "", + "title": "" + }, + "reset": "", + "save": "", + "sidebar": { + "info": { + "appVersion": "", + "backendUrl": "", + "backendVersion": "", + "hostname": "", + "insecure": "", + "notLoggedIn": "", + "secure": "", + "title": "", + "unknownVersion": "", + "userId": "" + } + }, + "subtitles": { + "backgroundLabel": "", + "colorLabel": "", + "previewQuote": "", + "textSizeLabel": "", + "title": "" + }, + "unsaved": "" } } From 5468d98089e3c039b5e16bdab62427f6121fecee Mon Sep 17 00:00:00 2001 From: TFAM_IS_LUV Date: Tue, 2 Jan 2024 11:09:00 +0000 Subject: [PATCH 111/151] Translated using Weblate (Korean) Currently translated at 91.3% (232 of 254 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ko/ Author: TFAM_IS_LUV --- src/assets/locales/ko.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/assets/locales/ko.json b/src/assets/locales/ko.json index 459ad986..dddc164c 100644 --- a/src/assets/locales/ko.json +++ b/src/assets/locales/ko.json @@ -82,12 +82,20 @@ "disclaimer": "면책 조항", "disclaimerText": "movie-web은 어떠한 파일도 호스팅하지 않으며, 제3자 서비스에 대한 링크만 제공합니다. 법적 문제는 파일 호스트 및 제공업체와 해결해야 합니다. 동영상 제공업체가 표시하는 미디어 파일에 대해 movie-web은 책임을 지지 않습니다." }, + "links": { + "discord": "", + "dmca": "", + "github": "" + }, "tagline": "이 오픈 소스 스트리밍 앱으로 좋아하는 프로그램과 영화를 시청하세요." }, "global": { + "name": "", "pages": { "about": "소개", + "dmca": "", "login": "로그인", + "pagetitle": "", "register": "회원가입", "settings": "설정" } From 429e40ac58e4ef7e0d22024dac5c1b2ac81b9bc8 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Sun, 21 Jan 2024 20:53:38 +0000 Subject: [PATCH 112/151] Translated using Weblate (Korean) Currently translated at 91.3% (232 of 254 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ko/ Author: Anonymous --- src/assets/locales/ko.json | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/assets/locales/ko.json b/src/assets/locales/ko.json index dddc164c..e23ed1fc 100644 --- a/src/assets/locales/ko.json +++ b/src/assets/locales/ko.json @@ -140,6 +140,7 @@ } }, "media": { + "episodeDisplay": "", "types": { "movie": "영화", "show": "쇼" @@ -202,9 +203,11 @@ "episodes": { "button": "회차", "emptyState": "이번 시즌에는 에피소드가 없으니 나중에 다시 확인하세요!", + "episodeBadge": "", "loadingError": "시즌 로딩중 에러 발생", "loadingList": "로딩...", - "loadingTitle": "로딩..." + "loadingTitle": "로딩...", + "unairedEpisodes": "" }, "playback": { "speedLabel": "재생 속도", @@ -256,6 +259,10 @@ } }, "metadata": { + "api": { + "text": "", + "title": "" + }, "failed": { "badge": "실패함", "homeButton": "메인으로 돌아가기", @@ -301,12 +308,22 @@ } }, "time": { - "remaining": "{{timeLeft}} 남음 • {{timeFinished, datetime}}에 종료" + "regular": "", + "remaining": "{{timeLeft}} 남음 • {{timeFinished, datetime}}에 종료", + "shortRegular": "", + "shortRemaining": "" + }, + "turnstile": { + "description": "", + "error": "", + "title": "", + "verifyingHumanity": "" } }, "screens": { "dmca": { - "text": "movie-web의 DMCA 문의 페이지에 오신 것을 환영합니다! 당사는 지적 재산권을 존중하며 저작권 관련 문제를 신속하게 해결하고자 합니다. 귀하의 저작권이 있는 저작물이 당사 플랫폼에서 부적절하게 사용되었다고 생각되는 경우, 아래 이메일로 자세한 DMCA 통지를 보내주시기 바랍니다. 저작권이 있는 자료에 대한 설명, 연락처 정보, 선의의 신념을 담은 진술서를 포함하시기 바랍니다. 당사는 이러한 문제를 신속하게 해결하기 위해 최선을 다하고 있으며, movie-web을 창의성과 저작권을 존중하는 공간으로 유지하는 데 협조해 주셔서 감사합니다." + "text": "movie-web의 DMCA 문의 페이지에 오신 것을 환영합니다! 당사는 지적 재산권을 존중하며 저작권 관련 문제를 신속하게 해결하고자 합니다. 귀하의 저작권이 있는 저작물이 당사 플랫폼에서 부적절하게 사용되었다고 생각되는 경우, 아래 이메일로 자세한 DMCA 통지를 보내주시기 바랍니다. 저작권이 있는 자료에 대한 설명, 연락처 정보, 선의의 신념을 담은 진술서를 포함하시기 바랍니다. 당사는 이러한 문제를 신속하게 해결하기 위해 최선을 다하고 있으며, movie-web을 창의성과 저작권을 존중하는 공간으로 유지하는 데 협조해 주셔서 감사합니다.", + "title": "" }, "loadingApp": "애플리케이션 로딩 중", "loadingUser": "프로필 로 중", @@ -383,7 +400,8 @@ "description": "애플리케이션이 작동하도록 하기 위해 모든 트래픽은 프록시를 통해 라우팅됩니다. 직접 워커를 사용하려면 이 옵션을 사용 설정하세요.", "emptyState": "아직 워커가 없는 경우 아래에서 워커를 추가하세요", "label": "사용자 지정 프록시 워커 사용", - "urlLabel": "워커 URL" + "urlLabel": "워커 URL", + "urlPlaceholder": "" } }, "reset": "초기화", From f62f13eb815d28ca7ccc7ff75b7d733238823579 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Sun, 21 Jan 2024 20:53:38 +0000 Subject: [PATCH 113/151] Translated using Weblate (Chinese (Traditional)) Currently translated at 10.7% (34 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/zh_Hant/ Author: Anonymous --- src/assets/locales/zh-Hant.json | 453 +++++++++++++++++++++++++++++++- 1 file changed, 442 insertions(+), 11 deletions(-) diff --git a/src/assets/locales/zh-Hant.json b/src/assets/locales/zh-Hant.json index ad03d9ef..4c5abbb8 100644 --- a/src/assets/locales/zh-Hant.json +++ b/src/assets/locales/zh-Hant.json @@ -5,17 +5,99 @@ "q1": { "body": "movie-web 不託管任何內容。您點選觀看內容時,系統均從互聯網搜尋(在加載提示頁和“視頻源”選項卡中,您可以看到正在使用的源)。媒體從未在 movie-web 中上傳,所有內容均通過搜索機制而得。", "title": "內容來自哪裡?" - } + }, + "q2": { + "body": "", + "title": "" + }, + "q3": { + "body": "", + "title": "" + }, + "title": "" + }, + "actions": { + "copied": "", + "copy": "" }, "auth": { + "createAccount": "", + "deviceNameLabel": "", + "deviceNamePlaceholder": "", + "generate": { + "description": "", + "next": "", + "passphraseFrameLabel": "", + "title": "" + }, + "hasAccount": "", "login": { - "submit": "登入" + "description": "", + "deviceLengthError": "", + "passphraseLabel": "", + "passphrasePlaceholder": "", + "submit": "登入", + "title": "", + "validationError": "" + }, + "register": { + "information": { + "color1": "", + "color2": "", + "header": "", + "icon": "", + "next": "", + "title": "" + } + }, + "trust": { + "failed": { + "text": "", + "title": "" + }, + "host": "", + "no": "", + "title": "", + "yes": "" + }, + "verify": { + "description": "", + "invalidData": "", + "noMatch": "", + "passphraseLabel": "", + "recaptchaFailed": "", + "register": "", + "title": "" } }, + "errors": { + "badge": "", + "details": "", + "reloadPage": "", + "showError": "", + "title": "" + }, + "footer": { + "legal": { + "disclaimer": "", + "disclaimerText": "" + }, + "links": { + "discord": "", + "dmca": "", + "github": "" + }, + "tagline": "" + }, "global": { + "name": "", "pages": { "about": "關於", + "dmca": "", "login": "登入", + "onboarding": "", + "pagetitle": "", + "register": "", "settings": "設定" } }, @@ -23,80 +105,429 @@ "bookmarks": { "sectionTitle": "書籤" }, + "continueWatching": { + "sectionTitle": "" + }, + "mediaList": { + "stopEditing": "" + }, "search": { - "loading": "載入中..." + "allResults": "", + "failed": "", + "loading": "載入中...", + "noResults": "", + "placeholder": "", + "sectionTitle": "" + }, + "titles": { + "day": { + "default": "", + "extra": [ + "" + ] + }, + "morning": { + "default": "", + "extra": [ + "" + ] + }, + "night": { + "default": "", + "extra": [ + "" + ] + } } }, "media": { + "episodeDisplay": "", "types": { "movie": "電影", "show": "節目" } }, "navigation": { + "banner": { + "offline": "" + }, "menu": { + "about": "", "donation": "捐", + "logout": "", + "register": "", "settings": "設定", "support": "支援" } }, + "notFound": { + "badge": "", + "goHome": "", + "message": "", + "title": "" + }, + "onboarding": { + "defaultConfirm": { + "cancel": "", + "confirm": "", + "description": "", + "title": "" + }, + "extension": { + "back": "", + "explainer": "", + "extensionHelp": "", + "link": "", + "status": { + "disallowed": "", + "disallowedAction": "", + "failed": "", + "loading": "", + "outdated": "", + "success": "" + }, + "submit": "", + "title": "" + }, + "proxy": { + "back": "", + "explainer": "", + "input": { + "errorConnection": "", + "errorInvalidUrl": "", + "errorNotProxy": "", + "label": "", + "placeholder": "" + }, + "link": "", + "submit": "", + "title": "" + }, + "start": { + "explainer": "", + "options": { + "default": { + "text": "" + }, + "extension": { + "action": "", + "description": "", + "quality": "", + "title": "" + }, + "proxy": { + "action": "", + "description": "", + "quality": "", + "title": "" + } + }, + "title": "" + } + }, "overlays": { "close": "關閉" }, "player": { "back": { + "default": "", "short": "後退" }, + "casting": { + "enabled": "" + }, "menus": { "downloads": { + "disclaimer": "", + "downloadPlaylist": "", + "downloadSubtitle": "", + "downloadVideo": "", + "hlsDisclaimer": "", + "onAndroid": { + "1": "", + "shortTitle": "", + "title": "" + }, + "onIos": { + "1": "", + "shortTitle": "", + "title": "" + }, + "onPc": { + "1": "", + "shortTitle": "", + "title": "" + }, "title": "下載" }, "episodes": { + "button": "", + "emptyState": "", + "episodeBadge": "", + "loadingError": "", "loadingList": "載入中...", - "loadingTitle": "載入中..." + "loadingTitle": "載入中...", + "unairedEpisodes": "" + }, + "playback": { + "speedLabel": "", + "title": "" + }, + "quality": { + "automaticLabel": "", + "hint": "", + "iosNoQuality": "", + "title": "" }, "settings": { - "downloadItem": "下載" + "downloadItem": "下載", + "enableSubtitles": "", + "experienceSection": "", + "playbackItem": "", + "qualityItem": "", + "sourceItem": "", + "subtitleItem": "", + "videoSection": "" + }, + "sources": { + "failed": { + "text": "", + "title": "" + }, + "noEmbeds": { + "text": "", + "title": "" + }, + "noStream": { + "text": "", + "title": "" + }, + "title": "", + "unknownOption": "" }, "subtitles": { - "title": "字幕" + "customChoice": "", + "customizeLabel": "", + "offChoice": "", + "settings": { + "backlink": "", + "delay": "", + "fixCapitals": "" + }, + "title": "字幕", + "unknownLanguage": "" } }, "metadata": { + "api": { + "text": "", + "title": "" + }, + "dmca": { + "badge": "", + "text": "", + "title": "" + }, + "extensionPermission": { + "badge": "", + "button": "", + "text": "", + "title": "" + }, "failed": { - "badge": "失敗" + "badge": "失敗", + "homeButton": "", + "text": "", + "title": "" + }, + "notFound": { + "badge": "", + "homeButton": "", + "text": "", + "title": "" } }, "nextEpisode": { - "cancel": "取消" + "cancel": "取消", + "next": "" + }, + "playbackError": { + "badge": "", + "errors": { + "errorAborted": "", + "errorDecode": "", + "errorGenericMedia": "", + "errorNetwork": "", + "errorNotSupported": "" + }, + "homeButton": "", + "text": "", + "title": "" + }, + "scraping": { + "items": { + "failure": "", + "notFound": "", + "pending": "" + }, + "notFound": { + "badge": "", + "detailsButton": "", + "homeButton": "", + "text": "", + "title": "" + } + }, + "time": { + "regular": "", + "remaining": "", + "shortRegular": "", + "shortRemaining": "" + }, + "turnstile": { + "description": "", + "error": "", + "title": "", + "verifyingHumanity": "" } }, "screens": { + "dmca": { + "text": "", + "title": "" + }, + "loadingApp": "", + "loadingUser": "", "loadingUserError": { - "logout": "登出" + "logout": "登出", + "reset": "", + "text": "", + "textWithReset": "" + }, + "migration": { + "failed": "", + "inProgress": "" } }, "settings": { "account": { + "accountDetails": { + "deviceNameLabel": "", + "deviceNamePlaceholder": "", + "editProfile": "", + "logoutButton": "" + }, + "actions": { + "delete": { + "button": "", + "confirmButton": "", + "confirmDescription": "", + "confirmTitle": "", + "text": "", + "title": "" + }, + "title": "" + }, + "devices": { + "deviceNameLabel": "", + "failed": "", + "removeDevice": "", + "title": "" + }, + "profile": { + "finish": "", + "firstColor": "", + "secondColor": "", + "title": "", + "userIcon": "" + }, + "register": { + "cta": "", + "text": "", + "title": "" + }, "title": "帳戶" }, "appearance": { + "activeTheme": "", "themes": { "blue": "藍色", + "default": "", "gray": "灰色", "red": "紅色", "teal": "青色" + }, + "title": "" + }, + "connections": { + "server": { + "description": "", + "label": "", + "urlLabel": "" + }, + "setup": { + "doSetup": "", + "errorStatus": { + "description": "", + "title": "" + }, + "itemError": "", + "items": { + "default": "", + "extension": "", + "proxy": "" + }, + "redoSetup": "", + "successStatus": { + "description": "", + "title": "" + }, + "unsetStatus": { + "description": "", + "title": "" + } + }, + "title": "", + "workers": { + "addButton": "", + "description": "", + "emptyState": "", + "label": "", + "urlLabel": "", + "urlPlaceholder": "" } }, + "preferences": { + "language": "", + "languageDescription": "", + "thumbnail": "", + "thumbnailDescription": "", + "thumbnailLabel": "", + "title": "" + }, + "reset": "", + "save": "", "sidebar": { "info": { + "appVersion": "", + "backendUrl": "", + "backendVersion": "", + "hostname": "", "insecure": "不安全", - "secure": "安全" + "notLoggedIn": "", + "secure": "安全", + "title": "", + "unknownVersion": "", + "userId": "" } }, "subtitles": { + "backgroundLabel": "", "colorLabel": "顏色", + "previewQuote": "", + "textSizeLabel": "", "title": "字幕" - } + }, + "unsaved": "" } } From 58582a42f1b4f90f41a6c98ccd04bf194004e5cd Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 15 Jan 2024 20:04:36 +0000 Subject: [PATCH 114/151] Translated using Weblate (Indonesian) Currently translated at 96.4% (245 of 254 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/id/ Author: Anonymous --- src/assets/locales/id.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/assets/locales/id.json b/src/assets/locales/id.json index e542c475..5ef60682 100644 --- a/src/assets/locales/id.json +++ b/src/assets/locales/id.json @@ -206,7 +206,8 @@ "episodeBadge": "E{{episode}}", "loadingError": "Eror memuat season", "loadingList": "Memuat...", - "loadingTitle": "Memuat..." + "loadingTitle": "Memuat...", + "unairedEpisodes": "" }, "playback": { "speedLabel": "Kecepatan pemutar", @@ -258,6 +259,10 @@ } }, "metadata": { + "api": { + "text": "", + "title": "" + }, "failed": { "badge": "Gagal", "homeButton": "Kembali", @@ -307,6 +312,12 @@ "remaining": "{{timeLeft}} tersisa • Selesai pada pukul {{timeFinished, datetime}}", "shortRegular": "{{timeWatched}}", "shortRemaining": "-{{timeLeft}}" + }, + "turnstile": { + "description": "", + "error": "", + "title": "", + "verifyingHumanity": "" } }, "screens": { From 50c399bf1cedd9c11d372289a3e0747d5175c0e9 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Sun, 21 Jan 2024 20:53:41 +0000 Subject: [PATCH 115/151] Translated using Weblate (Tamil) Currently translated at 9.7% (31 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ta/ Author: Anonymous --- src/assets/locales/ta.json | 470 ++++++++++++++++++++++++++++++++++++- 1 file changed, 468 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/ta.json b/src/assets/locales/ta.json index 6c1dfd43..552bdf52 100644 --- a/src/assets/locales/ta.json +++ b/src/assets/locales/ta.json @@ -1,6 +1,19 @@ { "about": { + "description": "", "faqTitle": "பொதுவான கேள்விகள்", + "q1": { + "body": "", + "title": "" + }, + "q2": { + "body": "", + "title": "" + }, + "q3": { + "body": "", + "title": "" + }, "title": "movie-web பற்றி" }, "actions": { @@ -29,39 +42,492 @@ }, "register": { "information": { + "color1": "", + "color2": "", + "header": "", "icon": "பயனர் குறிப்படம்", "next": "அடுத்து", "title": "கணக்கு விவரம்" } }, "trust": { - "no": "பின்செல்" + "failed": { + "text": "", + "title": "" + }, + "host": "", + "no": "பின்செல்", + "title": "", + "yes": "" }, "verify": { + "description": "", + "invalidData": "", + "noMatch": "", + "passphraseLabel": "", + "recaptchaFailed": "", "register": "கணக்கை உருவாக்கு", "title": "கடவுச்சொற்றொடரை உறுதி செய்க" } }, + "errors": { + "badge": "", + "details": "", + "reloadPage": "", + "showError": "", + "title": "" + }, + "footer": { + "legal": { + "disclaimer": "", + "disclaimerText": "" + }, + "links": { + "discord": "", + "dmca": "", + "github": "" + }, + "tagline": "" + }, "global": { + "name": "", "pages": { + "about": "", + "dmca": "", "login": "புகுபதிகை", + "onboarding": "", + "pagetitle": "", + "register": "", "settings": "அமைப்புகள்" } }, "home": { + "bookmarks": { + "sectionTitle": "" + }, + "continueWatching": { + "sectionTitle": "" + }, + "mediaList": { + "stopEditing": "" + }, "search": { + "allResults": "", + "failed": "", + "loading": "", + "noResults": "", + "placeholder": "", "sectionTitle": "தேடல் முடிவுகள்" + }, + "titles": { + "day": { + "default": "", + "extra": [ + "" + ] + }, + "morning": { + "default": "", + "extra": [ + "" + ] + }, + "night": { + "default": "", + "extra": [ + "" + ] + } } }, "media": { + "episodeDisplay": "", "types": { "movie": "திரைப்படம்", "show": "காட்சி" } }, "navigation": { + "banner": { + "offline": "" + }, "menu": { - "settings": "அமைப்புகள்" + "about": "", + "donation": "", + "logout": "", + "register": "", + "settings": "அமைப்புகள்", + "support": "" } + }, + "notFound": { + "badge": "", + "goHome": "", + "message": "", + "title": "" + }, + "onboarding": { + "defaultConfirm": { + "cancel": "", + "confirm": "", + "description": "", + "title": "" + }, + "extension": { + "back": "", + "explainer": "", + "extensionHelp": "", + "link": "", + "status": { + "disallowed": "", + "disallowedAction": "", + "failed": "", + "loading": "", + "outdated": "", + "success": "" + }, + "submit": "", + "title": "" + }, + "proxy": { + "back": "", + "explainer": "", + "input": { + "errorConnection": "", + "errorInvalidUrl": "", + "errorNotProxy": "", + "label": "", + "placeholder": "" + }, + "link": "", + "submit": "", + "title": "" + }, + "start": { + "explainer": "", + "options": { + "default": { + "text": "" + }, + "extension": { + "action": "", + "description": "", + "quality": "", + "title": "" + }, + "proxy": { + "action": "", + "description": "", + "quality": "", + "title": "" + } + }, + "title": "" + } + }, + "overlays": { + "close": "" + }, + "player": { + "back": { + "default": "", + "short": "" + }, + "casting": { + "enabled": "" + }, + "menus": { + "downloads": { + "disclaimer": "", + "downloadPlaylist": "", + "downloadSubtitle": "", + "downloadVideo": "", + "hlsDisclaimer": "", + "onAndroid": { + "1": "", + "shortTitle": "", + "title": "" + }, + "onIos": { + "1": "", + "shortTitle": "", + "title": "" + }, + "onPc": { + "1": "", + "shortTitle": "", + "title": "" + }, + "title": "" + }, + "episodes": { + "button": "", + "emptyState": "", + "episodeBadge": "", + "loadingError": "", + "loadingList": "", + "loadingTitle": "", + "unairedEpisodes": "" + }, + "playback": { + "speedLabel": "", + "title": "" + }, + "quality": { + "automaticLabel": "", + "hint": "", + "iosNoQuality": "", + "title": "" + }, + "settings": { + "downloadItem": "", + "enableSubtitles": "", + "experienceSection": "", + "playbackItem": "", + "qualityItem": "", + "sourceItem": "", + "subtitleItem": "", + "videoSection": "" + }, + "sources": { + "failed": { + "text": "", + "title": "" + }, + "noEmbeds": { + "text": "", + "title": "" + }, + "noStream": { + "text": "", + "title": "" + }, + "title": "", + "unknownOption": "" + }, + "subtitles": { + "customChoice": "", + "customizeLabel": "", + "offChoice": "", + "settings": { + "backlink": "", + "delay": "", + "fixCapitals": "" + }, + "title": "", + "unknownLanguage": "" + } + }, + "metadata": { + "api": { + "text": "", + "title": "" + }, + "dmca": { + "badge": "", + "text": "", + "title": "" + }, + "extensionPermission": { + "badge": "", + "button": "", + "text": "", + "title": "" + }, + "failed": { + "badge": "", + "homeButton": "", + "text": "", + "title": "" + }, + "notFound": { + "badge": "", + "homeButton": "", + "text": "", + "title": "" + } + }, + "nextEpisode": { + "cancel": "", + "next": "" + }, + "playbackError": { + "badge": "", + "errors": { + "errorAborted": "", + "errorDecode": "", + "errorGenericMedia": "", + "errorNetwork": "", + "errorNotSupported": "" + }, + "homeButton": "", + "text": "", + "title": "" + }, + "scraping": { + "items": { + "failure": "", + "notFound": "", + "pending": "" + }, + "notFound": { + "badge": "", + "detailsButton": "", + "homeButton": "", + "text": "", + "title": "" + } + }, + "time": { + "regular": "", + "remaining": "", + "shortRegular": "", + "shortRemaining": "" + }, + "turnstile": { + "description": "", + "error": "", + "title": "", + "verifyingHumanity": "" + } + }, + "screens": { + "dmca": { + "text": "", + "title": "" + }, + "loadingApp": "", + "loadingUser": "", + "loadingUserError": { + "logout": "", + "reset": "", + "text": "", + "textWithReset": "" + }, + "migration": { + "failed": "", + "inProgress": "" + } + }, + "settings": { + "account": { + "accountDetails": { + "deviceNameLabel": "", + "deviceNamePlaceholder": "", + "editProfile": "", + "logoutButton": "" + }, + "actions": { + "delete": { + "button": "", + "confirmButton": "", + "confirmDescription": "", + "confirmTitle": "", + "text": "", + "title": "" + }, + "title": "" + }, + "devices": { + "deviceNameLabel": "", + "failed": "", + "removeDevice": "", + "title": "" + }, + "profile": { + "finish": "", + "firstColor": "", + "secondColor": "", + "title": "", + "userIcon": "" + }, + "register": { + "cta": "", + "text": "", + "title": "" + }, + "title": "" + }, + "appearance": { + "activeTheme": "", + "themes": { + "blue": "", + "default": "", + "gray": "", + "red": "", + "teal": "" + }, + "title": "" + }, + "connections": { + "server": { + "description": "", + "label": "", + "urlLabel": "" + }, + "setup": { + "doSetup": "", + "errorStatus": { + "description": "", + "title": "" + }, + "itemError": "", + "items": { + "default": "", + "extension": "", + "proxy": "" + }, + "redoSetup": "", + "successStatus": { + "description": "", + "title": "" + }, + "unsetStatus": { + "description": "", + "title": "" + } + }, + "title": "", + "workers": { + "addButton": "", + "description": "", + "emptyState": "", + "label": "", + "urlLabel": "", + "urlPlaceholder": "" + } + }, + "preferences": { + "language": "", + "languageDescription": "", + "thumbnail": "", + "thumbnailDescription": "", + "thumbnailLabel": "", + "title": "" + }, + "reset": "", + "save": "", + "sidebar": { + "info": { + "appVersion": "", + "backendUrl": "", + "backendVersion": "", + "hostname": "", + "insecure": "", + "notLoggedIn": "", + "secure": "", + "title": "", + "unknownVersion": "", + "userId": "" + } + }, + "subtitles": { + "backgroundLabel": "", + "colorLabel": "", + "previewQuote": "", + "textSizeLabel": "", + "title": "" + }, + "unsaved": "" } } From a2ce26e7150011f8c8282d5b8f6bd0ae8da824d5 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Sun, 21 Jan 2024 20:53:41 +0000 Subject: [PATCH 116/151] Translated using Weblate (Japanese) Currently translated at 14.1% (45 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ja/ Author: Anonymous --- src/assets/locales/ja.json | 442 ++++++++++++++++++++++++++++++++++++- 1 file changed, 433 insertions(+), 9 deletions(-) diff --git a/src/assets/locales/ja.json b/src/assets/locales/ja.json index 95f53b4f..287ebf5f 100644 --- a/src/assets/locales/ja.json +++ b/src/assets/locales/ja.json @@ -25,30 +25,95 @@ "deviceNameLabel": "デバイス名", "deviceNamePlaceholder": "個人用の電話", "generate": { - "description": "パスフレーズはユーザー名とパスワードとして機能します。アカウントにログインする際には必ず入力する必要があるため、安全に保管してください。" + "description": "パスフレーズはユーザー名とパスワードとして機能します。アカウントにログインする際には必ず入力する必要があるため、安全に保管してください。", + "next": "", + "passphraseFrameLabel": "", + "title": "" }, + "hasAccount": "", "login": { + "description": "", + "deviceLengthError": "", + "passphraseLabel": "", + "passphrasePlaceholder": "", "submit": "ログイン", - "title": "自分の口座にログインする" + "title": "自分の口座にログインする", + "validationError": "" + }, + "register": { + "information": { + "color1": "", + "color2": "", + "header": "", + "icon": "", + "next": "", + "title": "" + } + }, + "trust": { + "failed": { + "text": "", + "title": "" + }, + "host": "", + "no": "", + "title": "", + "yes": "" + }, + "verify": { + "description": "", + "invalidData": "", + "noMatch": "", + "passphraseLabel": "", + "recaptchaFailed": "", + "register": "", + "title": "" } }, + "errors": { + "badge": "", + "details": "", + "reloadPage": "", + "showError": "", + "title": "" + }, "footer": { + "legal": { + "disclaimer": "", + "disclaimerText": "" + }, + "links": { + "discord": "", + "dmca": "", + "github": "" + }, "tagline": "あなたのお気に入りの番組や映画を、このオープンソースのストリーミングアプリで視聴してください。" }, "global": { "name": "映画ウェブ", "pages": { "about": "概要", + "dmca": "", "login": "ログイン", + "onboarding": "", + "pagetitle": "", + "register": "", "settings": "設定" } }, "home": { + "bookmarks": { + "sectionTitle": "" + }, "continueWatching": { "sectionTitle": "視聴を続ける" }, + "mediaList": { + "stopEditing": "" + }, "search": { "allResults": "それがすべてです!", + "failed": "", "loading": "読み込み中...", "noResults": "見つかりませんでした!", "placeholder": "どんな映画を見たい?", @@ -56,54 +121,413 @@ }, "titles": { "day": { - "default": "今日の午後はどんな映画を見たい?" + "default": "今日の午後はどんな映画を見たい?", + "extra": [ + "" + ] }, "morning": { - "default": "今朝はどんな映画を見たい?" + "default": "今朝はどんな映画を見たい?", + "extra": [ + "" + ] }, "night": { - "default": "今夜はどんな映画を見たい?" + "default": "今夜はどんな映画を見たい?", + "extra": [ + "" + ] } } }, "media": { + "episodeDisplay": "", "types": { "movie": "映画", "show": "テレビ番組" } }, "navigation": { + "banner": { + "offline": "" + }, "menu": { "about": "会社概要", "donation": "寄付", "logout": "退室", "register": "クラウドに同期して", - "settings": "設定" + "settings": "設定", + "support": "" } }, + "notFound": { + "badge": "", + "goHome": "", + "message": "", + "title": "" + }, + "onboarding": { + "defaultConfirm": { + "cancel": "", + "confirm": "", + "description": "", + "title": "" + }, + "extension": { + "back": "", + "explainer": "", + "extensionHelp": "", + "link": "", + "status": { + "disallowed": "", + "disallowedAction": "", + "failed": "", + "loading": "", + "outdated": "", + "success": "" + }, + "submit": "", + "title": "" + }, + "proxy": { + "back": "", + "explainer": "", + "input": { + "errorConnection": "", + "errorInvalidUrl": "", + "errorNotProxy": "", + "label": "", + "placeholder": "" + }, + "link": "", + "submit": "", + "title": "" + }, + "start": { + "explainer": "", + "options": { + "default": { + "text": "" + }, + "extension": { + "action": "", + "description": "", + "quality": "", + "title": "" + }, + "proxy": { + "action": "", + "description": "", + "quality": "", + "title": "" + } + }, + "title": "" + } + }, + "overlays": { + "close": "" + }, "player": { + "back": { + "default": "", + "short": "" + }, + "casting": { + "enabled": "" + }, "menus": { + "downloads": { + "disclaimer": "", + "downloadPlaylist": "", + "downloadSubtitle": "", + "downloadVideo": "", + "hlsDisclaimer": "", + "onAndroid": { + "1": "", + "shortTitle": "", + "title": "" + }, + "onIos": { + "1": "", + "shortTitle": "", + "title": "" + }, + "onPc": { + "1": "", + "shortTitle": "", + "title": "" + }, + "title": "" + }, "episodes": { + "button": "", + "emptyState": "", + "episodeBadge": "", + "loadingError": "", "loadingList": "読み込み中...", - "loadingTitle": "読み込み中..." + "loadingTitle": "読み込み中...", + "unairedEpisodes": "" + }, + "playback": { + "speedLabel": "", + "title": "" + }, + "quality": { + "automaticLabel": "", + "hint": "", + "iosNoQuality": "", + "title": "" + }, + "settings": { + "downloadItem": "", + "enableSubtitles": "", + "experienceSection": "", + "playbackItem": "", + "qualityItem": "", + "sourceItem": "", + "subtitleItem": "", + "videoSection": "" + }, + "sources": { + "failed": { + "text": "", + "title": "" + }, + "noEmbeds": { + "text": "", + "title": "" + }, + "noStream": { + "text": "", + "title": "" + }, + "title": "", + "unknownOption": "" + }, + "subtitles": { + "customChoice": "", + "customizeLabel": "", + "offChoice": "", + "settings": { + "backlink": "", + "delay": "", + "fixCapitals": "" + }, + "title": "", + "unknownLanguage": "" } + }, + "metadata": { + "api": { + "text": "", + "title": "" + }, + "dmca": { + "badge": "", + "text": "", + "title": "" + }, + "extensionPermission": { + "badge": "", + "button": "", + "text": "", + "title": "" + }, + "failed": { + "badge": "", + "homeButton": "", + "text": "", + "title": "" + }, + "notFound": { + "badge": "", + "homeButton": "", + "text": "", + "title": "" + } + }, + "nextEpisode": { + "cancel": "", + "next": "" + }, + "playbackError": { + "badge": "", + "errors": { + "errorAborted": "", + "errorDecode": "", + "errorGenericMedia": "", + "errorNetwork": "", + "errorNotSupported": "" + }, + "homeButton": "", + "text": "", + "title": "" + }, + "scraping": { + "items": { + "failure": "", + "notFound": "", + "pending": "" + }, + "notFound": { + "badge": "", + "detailsButton": "", + "homeButton": "", + "text": "", + "title": "" + } + }, + "time": { + "regular": "", + "remaining": "", + "shortRegular": "", + "shortRemaining": "" + }, + "turnstile": { + "description": "", + "error": "", + "title": "", + "verifyingHumanity": "" } }, "screens": { + "dmca": { + "text": "", + "title": "" + }, "loadingApp": "申込の読み込み", "loadingUser": "プロフィールの読み込み", "loadingUserError": { - "logout": "退出" + "logout": "退出", + "reset": "", + "text": "", + "textWithReset": "" + }, + "migration": { + "failed": "", + "inProgress": "" } }, "settings": { "account": { "accountDetails": { + "deviceNameLabel": "", + "deviceNamePlaceholder": "", + "editProfile": "", "logoutButton": "退室" }, + "actions": { + "delete": { + "button": "", + "confirmButton": "", + "confirmDescription": "", + "confirmTitle": "", + "text": "", + "title": "" + }, + "title": "" + }, + "devices": { + "deviceNameLabel": "", + "failed": "", + "removeDevice": "", + "title": "" + }, + "profile": { + "finish": "", + "firstColor": "", + "secondColor": "", + "title": "", + "userIcon": "" + }, "register": { + "cta": "", + "text": "", "title": "クラウドに同期して" + }, + "title": "" + }, + "appearance": { + "activeTheme": "", + "themes": { + "blue": "", + "default": "", + "gray": "", + "red": "", + "teal": "" + }, + "title": "" + }, + "connections": { + "server": { + "description": "", + "label": "", + "urlLabel": "" + }, + "setup": { + "doSetup": "", + "errorStatus": { + "description": "", + "title": "" + }, + "itemError": "", + "items": { + "default": "", + "extension": "", + "proxy": "" + }, + "redoSetup": "", + "successStatus": { + "description": "", + "title": "" + }, + "unsetStatus": { + "description": "", + "title": "" + } + }, + "title": "", + "workers": { + "addButton": "", + "description": "", + "emptyState": "", + "label": "", + "urlLabel": "", + "urlPlaceholder": "" } - } + }, + "preferences": { + "language": "", + "languageDescription": "", + "thumbnail": "", + "thumbnailDescription": "", + "thumbnailLabel": "", + "title": "" + }, + "reset": "", + "save": "", + "sidebar": { + "info": { + "appVersion": "", + "backendUrl": "", + "backendVersion": "", + "hostname": "", + "insecure": "", + "notLoggedIn": "", + "secure": "", + "title": "", + "unknownVersion": "", + "userId": "" + } + }, + "subtitles": { + "backgroundLabel": "", + "colorLabel": "", + "previewQuote": "", + "textSizeLabel": "", + "title": "" + }, + "unsaved": "" } } From 1cbba83335ef9e4b5bb3f8dd7a38f701c74ea077 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Mon, 15 Jan 2024 20:04:40 +0000 Subject: [PATCH 117/151] Translated using Weblate (Slovenian) Currently translated at 96.4% (245 of 254 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/sl/ Author: Anonymous --- src/assets/locales/sl.json | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/assets/locales/sl.json b/src/assets/locales/sl.json index 2c2f6657..26c96e59 100644 --- a/src/assets/locales/sl.json +++ b/src/assets/locales/sl.json @@ -206,7 +206,8 @@ "episodeBadge": "E{{episode}}", "loadingError": "Napaka pri nalaganju sezone", "loadingList": "Nalaganje...", - "loadingTitle": "Nalaganje..." + "loadingTitle": "Nalaganje...", + "unairedEpisodes": "" }, "playback": { "speedLabel": "Hitrost predvajanja", @@ -258,6 +259,10 @@ } }, "metadata": { + "api": { + "text": "", + "title": "" + }, "failed": { "badge": "Neuspešno", "homeButton": "Domov", @@ -307,6 +312,12 @@ "remaining": "{{timeLeft}} do konca • Konča ob {{timeFinished, datetime}}", "shortRegular": "{{timeWatched}}", "shortRemaining": "-{{timeLeft}}" + }, + "turnstile": { + "description": "", + "error": "", + "title": "", + "verifyingHumanity": "" } }, "screens": { From 77c5b607349b109601c61d9327e4304f199915b9 Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 23 Jan 2024 20:12:54 +0000 Subject: [PATCH 118/151] Bump ze version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4468753e..f614cdf7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "movie-web", - "version": "4.2.5", + "version": "4.2.6", "private": true, "homepage": "https://movie-web.app", "scripts": { From dc3fdb5fdd3cabf5c46bd8246577a4fb6956ec3b Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 23 Jan 2024 20:17:35 +0000 Subject: [PATCH 119/151] Actually bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f614cdf7..131fbfa2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "movie-web", - "version": "4.2.6", + "version": "4.3.0", "private": true, "homepage": "https://movie-web.app", "scripts": { From f1d12e1eeec88d869490e6bb837f71c820d1b4ba Mon Sep 17 00:00:00 2001 From: William Oldham Date: Tue, 23 Jan 2024 20:45:27 +0000 Subject: [PATCH 120/151] Add Portuguese Portugal into imports --- src/assets/languages.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/assets/languages.ts b/src/assets/languages.ts index 53765046..3f047fca 100644 --- a/src/assets/languages.ts +++ b/src/assets/languages.ts @@ -26,6 +26,7 @@ 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 +65,7 @@ export const locales = { tok, hi, "pt-BR": ptbr, + "pt-PT": ptpt, uk, bg, bn, From 487239b0fead1be4d5da966aa4f42d8c6678360f Mon Sep 17 00:00:00 2001 From: Weblate Date: Tue, 23 Jan 2024 20:13:02 +0000 Subject: [PATCH 121/151] Update translation files Updated by "Remove blank strings" hook in Weblate. Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/ --- src/assets/locales/ar.json | 10 - src/assets/locales/id.json | 13 +- src/assets/locales/ja.json | 442 +--------------------------- src/assets/locales/km.json | 497 +------------------------------- src/assets/locales/ko.json | 34 +-- src/assets/locales/lv.json | 43 +-- src/assets/locales/pirate.json | 42 +-- src/assets/locales/ru.json | 133 +-------- src/assets/locales/sl.json | 13 +- src/assets/locales/sv.json | 43 +-- src/assets/locales/ta.json | 470 +----------------------------- src/assets/locales/th.json | 21 +- src/assets/locales/tok.json | 42 +-- src/assets/locales/vi.json | 379 +----------------------- src/assets/locales/zh-Hant.json | 457 +---------------------------- 15 files changed, 55 insertions(+), 2584 deletions(-) diff --git a/src/assets/locales/ar.json b/src/assets/locales/ar.json index bfc21e70..6138644c 100644 --- a/src/assets/locales/ar.json +++ b/src/assets/locales/ar.json @@ -259,10 +259,6 @@ } }, "metadata": { - "api": { - "text": "", - "title": "" - }, "failed": { "badge": "فشل", "homeButton": "عُدْ للصفحة الرئيسية", @@ -312,12 +308,6 @@ "remaining": "باقٍ {{timeLeft}} • سينتهي مع {{timeFinished, datetime}}", "shortRegular": "{{timeWatched}}", "shortRemaining": "-{{timeLeft}}" - }, - "turnstile": { - "description": "", - "error": "", - "title": "", - "verifyingHumanity": "" } }, "screens": { diff --git a/src/assets/locales/id.json b/src/assets/locales/id.json index 5ef60682..e542c475 100644 --- a/src/assets/locales/id.json +++ b/src/assets/locales/id.json @@ -206,8 +206,7 @@ "episodeBadge": "E{{episode}}", "loadingError": "Eror memuat season", "loadingList": "Memuat...", - "loadingTitle": "Memuat...", - "unairedEpisodes": "" + "loadingTitle": "Memuat..." }, "playback": { "speedLabel": "Kecepatan pemutar", @@ -259,10 +258,6 @@ } }, "metadata": { - "api": { - "text": "", - "title": "" - }, "failed": { "badge": "Gagal", "homeButton": "Kembali", @@ -312,12 +307,6 @@ "remaining": "{{timeLeft}} tersisa • Selesai pada pukul {{timeFinished, datetime}}", "shortRegular": "{{timeWatched}}", "shortRemaining": "-{{timeLeft}}" - }, - "turnstile": { - "description": "", - "error": "", - "title": "", - "verifyingHumanity": "" } }, "screens": { diff --git a/src/assets/locales/ja.json b/src/assets/locales/ja.json index 287ebf5f..95f53b4f 100644 --- a/src/assets/locales/ja.json +++ b/src/assets/locales/ja.json @@ -25,95 +25,30 @@ "deviceNameLabel": "デバイス名", "deviceNamePlaceholder": "個人用の電話", "generate": { - "description": "パスフレーズはユーザー名とパスワードとして機能します。アカウントにログインする際には必ず入力する必要があるため、安全に保管してください。", - "next": "", - "passphraseFrameLabel": "", - "title": "" + "description": "パスフレーズはユーザー名とパスワードとして機能します。アカウントにログインする際には必ず入力する必要があるため、安全に保管してください。" }, - "hasAccount": "", "login": { - "description": "", - "deviceLengthError": "", - "passphraseLabel": "", - "passphrasePlaceholder": "", "submit": "ログイン", - "title": "自分の口座にログインする", - "validationError": "" - }, - "register": { - "information": { - "color1": "", - "color2": "", - "header": "", - "icon": "", - "next": "", - "title": "" - } - }, - "trust": { - "failed": { - "text": "", - "title": "" - }, - "host": "", - "no": "", - "title": "", - "yes": "" - }, - "verify": { - "description": "", - "invalidData": "", - "noMatch": "", - "passphraseLabel": "", - "recaptchaFailed": "", - "register": "", - "title": "" + "title": "自分の口座にログインする" } }, - "errors": { - "badge": "", - "details": "", - "reloadPage": "", - "showError": "", - "title": "" - }, "footer": { - "legal": { - "disclaimer": "", - "disclaimerText": "" - }, - "links": { - "discord": "", - "dmca": "", - "github": "" - }, "tagline": "あなたのお気に入りの番組や映画を、このオープンソースのストリーミングアプリで視聴してください。" }, "global": { "name": "映画ウェブ", "pages": { "about": "概要", - "dmca": "", "login": "ログイン", - "onboarding": "", - "pagetitle": "", - "register": "", "settings": "設定" } }, "home": { - "bookmarks": { - "sectionTitle": "" - }, "continueWatching": { "sectionTitle": "視聴を続ける" }, - "mediaList": { - "stopEditing": "" - }, "search": { "allResults": "それがすべてです!", - "failed": "", "loading": "読み込み中...", "noResults": "見つかりませんでした!", "placeholder": "どんな映画を見たい?", @@ -121,413 +56,54 @@ }, "titles": { "day": { - "default": "今日の午後はどんな映画を見たい?", - "extra": [ - "" - ] + "default": "今日の午後はどんな映画を見たい?" }, "morning": { - "default": "今朝はどんな映画を見たい?", - "extra": [ - "" - ] + "default": "今朝はどんな映画を見たい?" }, "night": { - "default": "今夜はどんな映画を見たい?", - "extra": [ - "" - ] + "default": "今夜はどんな映画を見たい?" } } }, "media": { - "episodeDisplay": "", "types": { "movie": "映画", "show": "テレビ番組" } }, "navigation": { - "banner": { - "offline": "" - }, "menu": { "about": "会社概要", "donation": "寄付", "logout": "退室", "register": "クラウドに同期して", - "settings": "設定", - "support": "" + "settings": "設定" } }, - "notFound": { - "badge": "", - "goHome": "", - "message": "", - "title": "" - }, - "onboarding": { - "defaultConfirm": { - "cancel": "", - "confirm": "", - "description": "", - "title": "" - }, - "extension": { - "back": "", - "explainer": "", - "extensionHelp": "", - "link": "", - "status": { - "disallowed": "", - "disallowedAction": "", - "failed": "", - "loading": "", - "outdated": "", - "success": "" - }, - "submit": "", - "title": "" - }, - "proxy": { - "back": "", - "explainer": "", - "input": { - "errorConnection": "", - "errorInvalidUrl": "", - "errorNotProxy": "", - "label": "", - "placeholder": "" - }, - "link": "", - "submit": "", - "title": "" - }, - "start": { - "explainer": "", - "options": { - "default": { - "text": "" - }, - "extension": { - "action": "", - "description": "", - "quality": "", - "title": "" - }, - "proxy": { - "action": "", - "description": "", - "quality": "", - "title": "" - } - }, - "title": "" - } - }, - "overlays": { - "close": "" - }, "player": { - "back": { - "default": "", - "short": "" - }, - "casting": { - "enabled": "" - }, "menus": { - "downloads": { - "disclaimer": "", - "downloadPlaylist": "", - "downloadSubtitle": "", - "downloadVideo": "", - "hlsDisclaimer": "", - "onAndroid": { - "1": "", - "shortTitle": "", - "title": "" - }, - "onIos": { - "1": "", - "shortTitle": "", - "title": "" - }, - "onPc": { - "1": "", - "shortTitle": "", - "title": "" - }, - "title": "" - }, "episodes": { - "button": "", - "emptyState": "", - "episodeBadge": "", - "loadingError": "", "loadingList": "読み込み中...", - "loadingTitle": "読み込み中...", - "unairedEpisodes": "" - }, - "playback": { - "speedLabel": "", - "title": "" - }, - "quality": { - "automaticLabel": "", - "hint": "", - "iosNoQuality": "", - "title": "" - }, - "settings": { - "downloadItem": "", - "enableSubtitles": "", - "experienceSection": "", - "playbackItem": "", - "qualityItem": "", - "sourceItem": "", - "subtitleItem": "", - "videoSection": "" - }, - "sources": { - "failed": { - "text": "", - "title": "" - }, - "noEmbeds": { - "text": "", - "title": "" - }, - "noStream": { - "text": "", - "title": "" - }, - "title": "", - "unknownOption": "" - }, - "subtitles": { - "customChoice": "", - "customizeLabel": "", - "offChoice": "", - "settings": { - "backlink": "", - "delay": "", - "fixCapitals": "" - }, - "title": "", - "unknownLanguage": "" + "loadingTitle": "読み込み中..." } - }, - "metadata": { - "api": { - "text": "", - "title": "" - }, - "dmca": { - "badge": "", - "text": "", - "title": "" - }, - "extensionPermission": { - "badge": "", - "button": "", - "text": "", - "title": "" - }, - "failed": { - "badge": "", - "homeButton": "", - "text": "", - "title": "" - }, - "notFound": { - "badge": "", - "homeButton": "", - "text": "", - "title": "" - } - }, - "nextEpisode": { - "cancel": "", - "next": "" - }, - "playbackError": { - "badge": "", - "errors": { - "errorAborted": "", - "errorDecode": "", - "errorGenericMedia": "", - "errorNetwork": "", - "errorNotSupported": "" - }, - "homeButton": "", - "text": "", - "title": "" - }, - "scraping": { - "items": { - "failure": "", - "notFound": "", - "pending": "" - }, - "notFound": { - "badge": "", - "detailsButton": "", - "homeButton": "", - "text": "", - "title": "" - } - }, - "time": { - "regular": "", - "remaining": "", - "shortRegular": "", - "shortRemaining": "" - }, - "turnstile": { - "description": "", - "error": "", - "title": "", - "verifyingHumanity": "" } }, "screens": { - "dmca": { - "text": "", - "title": "" - }, "loadingApp": "申込の読み込み", "loadingUser": "プロフィールの読み込み", "loadingUserError": { - "logout": "退出", - "reset": "", - "text": "", - "textWithReset": "" - }, - "migration": { - "failed": "", - "inProgress": "" + "logout": "退出" } }, "settings": { "account": { "accountDetails": { - "deviceNameLabel": "", - "deviceNamePlaceholder": "", - "editProfile": "", "logoutButton": "退室" }, - "actions": { - "delete": { - "button": "", - "confirmButton": "", - "confirmDescription": "", - "confirmTitle": "", - "text": "", - "title": "" - }, - "title": "" - }, - "devices": { - "deviceNameLabel": "", - "failed": "", - "removeDevice": "", - "title": "" - }, - "profile": { - "finish": "", - "firstColor": "", - "secondColor": "", - "title": "", - "userIcon": "" - }, "register": { - "cta": "", - "text": "", "title": "クラウドに同期して" - }, - "title": "" - }, - "appearance": { - "activeTheme": "", - "themes": { - "blue": "", - "default": "", - "gray": "", - "red": "", - "teal": "" - }, - "title": "" - }, - "connections": { - "server": { - "description": "", - "label": "", - "urlLabel": "" - }, - "setup": { - "doSetup": "", - "errorStatus": { - "description": "", - "title": "" - }, - "itemError": "", - "items": { - "default": "", - "extension": "", - "proxy": "" - }, - "redoSetup": "", - "successStatus": { - "description": "", - "title": "" - }, - "unsetStatus": { - "description": "", - "title": "" - } - }, - "title": "", - "workers": { - "addButton": "", - "description": "", - "emptyState": "", - "label": "", - "urlLabel": "", - "urlPlaceholder": "" } - }, - "preferences": { - "language": "", - "languageDescription": "", - "thumbnail": "", - "thumbnailDescription": "", - "thumbnailLabel": "", - "title": "" - }, - "reset": "", - "save": "", - "sidebar": { - "info": { - "appVersion": "", - "backendUrl": "", - "backendVersion": "", - "hostname": "", - "insecure": "", - "notLoggedIn": "", - "secure": "", - "title": "", - "unknownVersion": "", - "userId": "" - } - }, - "subtitles": { - "backgroundLabel": "", - "colorLabel": "", - "previewQuote": "", - "textSizeLabel": "", - "title": "" - }, - "unsaved": "" + } } } diff --git a/src/assets/locales/km.json b/src/assets/locales/km.json index 0a82e14e..121b32e8 100644 --- a/src/assets/locales/km.json +++ b/src/assets/locales/km.json @@ -7,7 +7,6 @@ "title": "តើមាតិកាបានមកពីណា?" }, "q2": { - "body": "", "title": "តើខ្ញុំអាចស្នើសុំកម្មវិធី ឬ ភាពយន្តបាននៅឯណា?" }, "q3": { @@ -33,501 +32,7 @@ "hasAccount": "មានគណនីរួចហើយ? <0>ចូលទីនេះ", "login": { "description": "សូមបញ្ចូលឃ្លាសម្ងាត់របស់អ្នក ដើម្បីចូលគណនីរបស់អ្នក", - "deviceLengthError": "សូមបញ្ចូលឈ្មោះឧបករណ៍", - "passphraseLabel": "", - "passphrasePlaceholder": "", - "submit": "", - "title": "", - "validationError": "" - }, - "register": { - "information": { - "color1": "", - "color2": "", - "header": "", - "icon": "", - "next": "", - "title": "" - } - }, - "trust": { - "failed": { - "text": "", - "title": "" - }, - "host": "", - "no": "", - "title": "", - "yes": "" - }, - "verify": { - "description": "", - "invalidData": "", - "noMatch": "", - "passphraseLabel": "", - "recaptchaFailed": "", - "register": "", - "title": "" + "deviceLengthError": "សូមបញ្ចូលឈ្មោះឧបករណ៍" } - }, - "errors": { - "badge": "", - "details": "", - "reloadPage": "", - "showError": "", - "title": "" - }, - "footer": { - "legal": { - "disclaimer": "", - "disclaimerText": "" - }, - "links": { - "discord": "", - "dmca": "", - "github": "" - }, - "tagline": "" - }, - "global": { - "name": "", - "pages": { - "about": "", - "dmca": "", - "login": "", - "onboarding": "", - "pagetitle": "", - "register": "", - "settings": "" - } - }, - "home": { - "bookmarks": { - "sectionTitle": "" - }, - "continueWatching": { - "sectionTitle": "" - }, - "mediaList": { - "stopEditing": "" - }, - "search": { - "allResults": "", - "failed": "", - "loading": "", - "noResults": "", - "placeholder": "", - "sectionTitle": "" - }, - "titles": { - "day": { - "default": "", - "extra": [ - "" - ] - }, - "morning": { - "default": "", - "extra": [ - "" - ] - }, - "night": { - "default": "", - "extra": [ - "" - ] - } - } - }, - "media": { - "episodeDisplay": "", - "types": { - "movie": "", - "show": "" - } - }, - "navigation": { - "banner": { - "offline": "" - }, - "menu": { - "about": "", - "donation": "", - "logout": "", - "register": "", - "settings": "", - "support": "" - } - }, - "notFound": { - "badge": "", - "goHome": "", - "message": "", - "title": "" - }, - "onboarding": { - "defaultConfirm": { - "cancel": "", - "confirm": "", - "description": "", - "title": "" - }, - "extension": { - "back": "", - "explainer": "", - "extensionHelp": "", - "link": "", - "status": { - "disallowed": "", - "disallowedAction": "", - "failed": "", - "loading": "", - "outdated": "", - "success": "" - }, - "submit": "", - "title": "" - }, - "proxy": { - "back": "", - "explainer": "", - "input": { - "errorConnection": "", - "errorInvalidUrl": "", - "errorNotProxy": "", - "label": "", - "placeholder": "" - }, - "link": "", - "submit": "", - "title": "" - }, - "start": { - "explainer": "", - "options": { - "default": { - "text": "" - }, - "extension": { - "action": "", - "description": "", - "quality": "", - "title": "" - }, - "proxy": { - "action": "", - "description": "", - "quality": "", - "title": "" - } - }, - "title": "" - } - }, - "overlays": { - "close": "" - }, - "player": { - "back": { - "default": "", - "short": "" - }, - "casting": { - "enabled": "" - }, - "menus": { - "downloads": { - "disclaimer": "", - "downloadPlaylist": "", - "downloadSubtitle": "", - "downloadVideo": "", - "hlsDisclaimer": "", - "onAndroid": { - "1": "", - "shortTitle": "", - "title": "" - }, - "onIos": { - "1": "", - "shortTitle": "", - "title": "" - }, - "onPc": { - "1": "", - "shortTitle": "", - "title": "" - }, - "title": "" - }, - "episodes": { - "button": "", - "emptyState": "", - "episodeBadge": "", - "loadingError": "", - "loadingList": "", - "loadingTitle": "", - "unairedEpisodes": "" - }, - "playback": { - "speedLabel": "", - "title": "" - }, - "quality": { - "automaticLabel": "", - "hint": "", - "iosNoQuality": "", - "title": "" - }, - "settings": { - "downloadItem": "", - "enableSubtitles": "", - "experienceSection": "", - "playbackItem": "", - "qualityItem": "", - "sourceItem": "", - "subtitleItem": "", - "videoSection": "" - }, - "sources": { - "failed": { - "text": "", - "title": "" - }, - "noEmbeds": { - "text": "", - "title": "" - }, - "noStream": { - "text": "", - "title": "" - }, - "title": "", - "unknownOption": "" - }, - "subtitles": { - "customChoice": "", - "customizeLabel": "", - "offChoice": "", - "settings": { - "backlink": "", - "delay": "", - "fixCapitals": "" - }, - "title": "", - "unknownLanguage": "" - } - }, - "metadata": { - "api": { - "text": "", - "title": "" - }, - "dmca": { - "badge": "", - "text": "", - "title": "" - }, - "extensionPermission": { - "badge": "", - "button": "", - "text": "", - "title": "" - }, - "failed": { - "badge": "", - "homeButton": "", - "text": "", - "title": "" - }, - "notFound": { - "badge": "", - "homeButton": "", - "text": "", - "title": "" - } - }, - "nextEpisode": { - "cancel": "", - "next": "" - }, - "playbackError": { - "badge": "", - "errors": { - "errorAborted": "", - "errorDecode": "", - "errorGenericMedia": "", - "errorNetwork": "", - "errorNotSupported": "" - }, - "homeButton": "", - "text": "", - "title": "" - }, - "scraping": { - "items": { - "failure": "", - "notFound": "", - "pending": "" - }, - "notFound": { - "badge": "", - "detailsButton": "", - "homeButton": "", - "text": "", - "title": "" - } - }, - "time": { - "regular": "", - "remaining": "", - "shortRegular": "", - "shortRemaining": "" - }, - "turnstile": { - "description": "", - "error": "", - "title": "", - "verifyingHumanity": "" - } - }, - "screens": { - "dmca": { - "text": "", - "title": "" - }, - "loadingApp": "", - "loadingUser": "", - "loadingUserError": { - "logout": "", - "reset": "", - "text": "", - "textWithReset": "" - }, - "migration": { - "failed": "", - "inProgress": "" - } - }, - "settings": { - "account": { - "accountDetails": { - "deviceNameLabel": "", - "deviceNamePlaceholder": "", - "editProfile": "", - "logoutButton": "" - }, - "actions": { - "delete": { - "button": "", - "confirmButton": "", - "confirmDescription": "", - "confirmTitle": "", - "text": "", - "title": "" - }, - "title": "" - }, - "devices": { - "deviceNameLabel": "", - "failed": "", - "removeDevice": "", - "title": "" - }, - "profile": { - "finish": "", - "firstColor": "", - "secondColor": "", - "title": "", - "userIcon": "" - }, - "register": { - "cta": "", - "text": "", - "title": "" - }, - "title": "" - }, - "appearance": { - "activeTheme": "", - "themes": { - "blue": "", - "default": "", - "gray": "", - "red": "", - "teal": "" - }, - "title": "" - }, - "connections": { - "server": { - "description": "", - "label": "", - "urlLabel": "" - }, - "setup": { - "doSetup": "", - "errorStatus": { - "description": "", - "title": "" - }, - "itemError": "", - "items": { - "default": "", - "extension": "", - "proxy": "" - }, - "redoSetup": "", - "successStatus": { - "description": "", - "title": "" - }, - "unsetStatus": { - "description": "", - "title": "" - } - }, - "title": "", - "workers": { - "addButton": "", - "description": "", - "emptyState": "", - "label": "", - "urlLabel": "", - "urlPlaceholder": "" - } - }, - "preferences": { - "language": "", - "languageDescription": "", - "thumbnail": "", - "thumbnailDescription": "", - "thumbnailLabel": "", - "title": "" - }, - "reset": "", - "save": "", - "sidebar": { - "info": { - "appVersion": "", - "backendUrl": "", - "backendVersion": "", - "hostname": "", - "insecure": "", - "notLoggedIn": "", - "secure": "", - "title": "", - "unknownVersion": "", - "userId": "" - } - }, - "subtitles": { - "backgroundLabel": "", - "colorLabel": "", - "previewQuote": "", - "textSizeLabel": "", - "title": "" - }, - "unsaved": "" } } diff --git a/src/assets/locales/ko.json b/src/assets/locales/ko.json index e23ed1fc..459ad986 100644 --- a/src/assets/locales/ko.json +++ b/src/assets/locales/ko.json @@ -82,20 +82,12 @@ "disclaimer": "면책 조항", "disclaimerText": "movie-web은 어떠한 파일도 호스팅하지 않으며, 제3자 서비스에 대한 링크만 제공합니다. 법적 문제는 파일 호스트 및 제공업체와 해결해야 합니다. 동영상 제공업체가 표시하는 미디어 파일에 대해 movie-web은 책임을 지지 않습니다." }, - "links": { - "discord": "", - "dmca": "", - "github": "" - }, "tagline": "이 오픈 소스 스트리밍 앱으로 좋아하는 프로그램과 영화를 시청하세요." }, "global": { - "name": "", "pages": { "about": "소개", - "dmca": "", "login": "로그인", - "pagetitle": "", "register": "회원가입", "settings": "설정" } @@ -140,7 +132,6 @@ } }, "media": { - "episodeDisplay": "", "types": { "movie": "영화", "show": "쇼" @@ -203,11 +194,9 @@ "episodes": { "button": "회차", "emptyState": "이번 시즌에는 에피소드가 없으니 나중에 다시 확인하세요!", - "episodeBadge": "", "loadingError": "시즌 로딩중 에러 발생", "loadingList": "로딩...", - "loadingTitle": "로딩...", - "unairedEpisodes": "" + "loadingTitle": "로딩..." }, "playback": { "speedLabel": "재생 속도", @@ -259,10 +248,6 @@ } }, "metadata": { - "api": { - "text": "", - "title": "" - }, "failed": { "badge": "실패함", "homeButton": "메인으로 돌아가기", @@ -308,22 +293,12 @@ } }, "time": { - "regular": "", - "remaining": "{{timeLeft}} 남음 • {{timeFinished, datetime}}에 종료", - "shortRegular": "", - "shortRemaining": "" - }, - "turnstile": { - "description": "", - "error": "", - "title": "", - "verifyingHumanity": "" + "remaining": "{{timeLeft}} 남음 • {{timeFinished, datetime}}에 종료" } }, "screens": { "dmca": { - "text": "movie-web의 DMCA 문의 페이지에 오신 것을 환영합니다! 당사는 지적 재산권을 존중하며 저작권 관련 문제를 신속하게 해결하고자 합니다. 귀하의 저작권이 있는 저작물이 당사 플랫폼에서 부적절하게 사용되었다고 생각되는 경우, 아래 이메일로 자세한 DMCA 통지를 보내주시기 바랍니다. 저작권이 있는 자료에 대한 설명, 연락처 정보, 선의의 신념을 담은 진술서를 포함하시기 바랍니다. 당사는 이러한 문제를 신속하게 해결하기 위해 최선을 다하고 있으며, movie-web을 창의성과 저작권을 존중하는 공간으로 유지하는 데 협조해 주셔서 감사합니다.", - "title": "" + "text": "movie-web의 DMCA 문의 페이지에 오신 것을 환영합니다! 당사는 지적 재산권을 존중하며 저작권 관련 문제를 신속하게 해결하고자 합니다. 귀하의 저작권이 있는 저작물이 당사 플랫폼에서 부적절하게 사용되었다고 생각되는 경우, 아래 이메일로 자세한 DMCA 통지를 보내주시기 바랍니다. 저작권이 있는 자료에 대한 설명, 연락처 정보, 선의의 신념을 담은 진술서를 포함하시기 바랍니다. 당사는 이러한 문제를 신속하게 해결하기 위해 최선을 다하고 있으며, movie-web을 창의성과 저작권을 존중하는 공간으로 유지하는 데 협조해 주셔서 감사합니다." }, "loadingApp": "애플리케이션 로딩 중", "loadingUser": "프로필 로 중", @@ -400,8 +375,7 @@ "description": "애플리케이션이 작동하도록 하기 위해 모든 트래픽은 프록시를 통해 라우팅됩니다. 직접 워커를 사용하려면 이 옵션을 사용 설정하세요.", "emptyState": "아직 워커가 없는 경우 아래에서 워커를 추가하세요", "label": "사용자 지정 프록시 워커 사용", - "urlLabel": "워커 URL", - "urlPlaceholder": "" + "urlLabel": "워커 URL" } }, "reset": "초기화", diff --git a/src/assets/locales/lv.json b/src/assets/locales/lv.json index e650d5c8..0d5b3c99 100644 --- a/src/assets/locales/lv.json +++ b/src/assets/locales/lv.json @@ -27,7 +27,6 @@ "generate": { "description": "Tava paroles frāze ir kā vārds un parole. Esi drošs ka turi to drošibā jo tev vajadzēs to izmantot lai ieietu kontā", "next": "Esmu saglabājis paroles frāzi", - "passphraseFrameLabel": "", "title": "Tava paroles frāze" }, "hasAccount": "Tev jau ir konts> <0>Ienāc šeit.", @@ -120,10 +119,7 @@ }, "titles": { "day": { - "default": "Ko jūs vēlētos noskatīties šajā pēcpusdienā?", - "extra": [ - "" - ] + "default": "Ko jūs vēlētos noskatīties šajā pēcpusdienā?" }, "morning": { "default": "Ko tu gribētu šorīt noskatīties?", @@ -179,10 +175,7 @@ "menus": { "downloads": { "disclaimer": "Lejupielādes tiek ņemtas tieši no pakalpojumu sniedzēja. Movie-web nevar kontrolēt, kā tiek nodrošinātas lejupielādes.", - "downloadPlaylist": "", - "downloadSubtitle": "", "downloadVideo": "Lejupielādēt video", - "hlsDisclaimer": "", "onAndroid": { "1": "Lai lejupielādētu operētājsistēmā Android, noklikšķiniet uz lejupielādes pogas, pēc tam jaunajā lapā pieskarieties videoklipam un turiet to, pēc tam atlasiet saglabāt.", "shortTitle": "Lejupielādēt / Android", @@ -206,8 +199,7 @@ "episodeBadge": "E{{episode}}", "loadingError": "Kļūda ladējot sezonu", "loadingList": "Lādejas...", - "loadingTitle": "Lādejas...", - "unairedEpisodes": "" + "loadingTitle": "Lādejas..." }, "playback": { "speedLabel": "Atskaņošana ātrums", @@ -221,12 +213,10 @@ }, "settings": { "downloadItem": "Lejupladēt", - "enableSubtitles": "", "experienceSection": "Skatīšanās pieredze", "playbackItem": "Atskaņošana iestādijumi", "qualityItem": "Kvalitāte", "sourceItem": "Video avoti", - "subtitleItem": "", "videoSection": "Video iestādijumi" }, "sources": { @@ -244,25 +234,9 @@ }, "title": "Avoti", "unknownOption": "Nezināms" - }, - "subtitles": { - "customChoice": "", - "customizeLabel": "", - "offChoice": "", - "settings": { - "backlink": "", - "delay": "", - "fixCapitals": "" - }, - "title": "", - "unknownLanguage": "" } }, "metadata": { - "api": { - "text": "", - "title": "" - }, "failed": { "badge": "Neizdevās", "homeButton": "iet uz majām", @@ -312,12 +286,6 @@ "remaining": "{{timeLeft}} beidza • pabeidza {{timeFinished, datetime}}", "shortRegular": "{{timeWatched}}", "shortRemaining": "-{{timeLeft}}" - }, - "turnstile": { - "description": "", - "error": "", - "title": "", - "verifyingHumanity": "" } }, "screens": { @@ -420,13 +388,6 @@ "userId": "Lietotāja ID" } }, - "subtitles": { - "backgroundLabel": "", - "colorLabel": "", - "previewQuote": "", - "textSizeLabel": "", - "title": "" - }, "unsaved": "Jums ir nesaglabātas izmaiņas" } } diff --git a/src/assets/locales/pirate.json b/src/assets/locales/pirate.json index adfb6a84..c6868b03 100644 --- a/src/assets/locales/pirate.json +++ b/src/assets/locales/pirate.json @@ -120,10 +120,7 @@ }, "titles": { "day": { - "default": "What be yer fancy for this fine afternoon's viewing, me heartie?", - "extra": [ - "" - ] + "default": "What be yer fancy for this fine afternoon's viewing, me heartie?" }, "morning": { "default": "What be yer fancy for this mornin's viewing, me heartie?", @@ -179,10 +176,7 @@ "menus": { "downloads": { "disclaimer": "Downloads be taken directly from the provider. movie-web does not have control over how the downloads be provided.", - "downloadPlaylist": "", - "downloadSubtitle": "", "downloadVideo": "Download film", - "hlsDisclaimer": "", "onAndroid": { "1": "To download on Android, tap and hold on the film, then select save.", "shortTitle": "Download / Android", @@ -206,8 +200,7 @@ "episodeBadge": "E{{episode}}", "loadingError": "Error loadin' season", "loadingList": "Loading...", - "loadingTitle": "Loading...", - "unairedEpisodes": "" + "loadingTitle": "Loading..." }, "playback": { "speedLabel": "Playback speed", @@ -246,23 +239,13 @@ "unknownOption": "Unknown" }, "subtitles": { - "customChoice": "", "customizeLabel": "Tailor it to yer liking", - "offChoice": "", "settings": { - "backlink": "", - "delay": "", "fixCapitals": "Mend the capital letters" - }, - "title": "", - "unknownLanguage": "" + } } }, "metadata": { - "api": { - "text": "", - "title": "" - }, "failed": { "badge": "Failed", "homeButton": "Go home port", @@ -301,7 +284,6 @@ }, "notFound": { "badge": "Not found", - "detailsButton": "", "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" @@ -312,23 +294,12 @@ "remaining": "{{timeLeft}} left • Finish at {{timeFinished, datetime}}", "shortRegular": "{{timeWatched}}", "shortRemaining": "-{{timeLeft}}" - }, - "turnstile": { - "description": "", - "error": "", - "title": "", - "verifyingHumanity": "" } }, "screens": { - "dmca": { - "text": "", - "title": "" - }, "loadingApp": "Loadin' application", "loadingUser": "Loadin' yer pirate profile", "loadingUserError": { - "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?" @@ -420,13 +391,6 @@ "userId": "Pirate ID" } }, - "subtitles": { - "backgroundLabel": "", - "colorLabel": "", - "previewQuote": "", - "textSizeLabel": "", - "title": "" - }, "unsaved": "Ye have unsaved changes" } } diff --git a/src/assets/locales/ru.json b/src/assets/locales/ru.json index 66fdcae5..c547bba2 100644 --- a/src/assets/locales/ru.json +++ b/src/assets/locales/ru.json @@ -71,7 +71,6 @@ } }, "errors": { - "badge": "", "details": "Подробности ошибки", "reloadPage": "Перезагрузить страницу", "showError": "Показать сведения об ошибке", @@ -94,9 +93,7 @@ "pages": { "about": "О", "dmca": "DMCA", - "login": "", "pagetitle": "{{title}} - movie-web", - "register": "", "settings": "Настройки" } }, @@ -112,31 +109,8 @@ }, "search": { "allResults": "Это все, что у нас есть!", - "failed": "", "loading": "Загрузка...", - "noResults": "", - "placeholder": "", "sectionTitle": "Результаты поиска" - }, - "titles": { - "day": { - "default": "", - "extra": [ - "" - ] - }, - "morning": { - "default": "", - "extra": [ - "" - ] - }, - "night": { - "default": "", - "extra": [ - "" - ] - } } }, "media": { @@ -154,15 +128,11 @@ "about": "О нас", "donation": "Пожертвовать", "logout": "Выйти", - "register": "", "settings": "Настройки", "support": "Поддержка" } }, "notFound": { - "badge": "", - "goHome": "", - "message": "", "title": "Не удалось найти эту страницу" }, "overlays": { @@ -170,34 +140,11 @@ }, "player": { "back": { - "default": "Вернуться на главную", - "short": "" - }, - "casting": { - "enabled": "" + "default": "Вернуться на главную" }, "menus": { "downloads": { - "disclaimer": "", - "downloadPlaylist": "", "downloadSubtitle": "Скачать текущие субтитры", - "downloadVideo": "", - "hlsDisclaimer": "", - "onAndroid": { - "1": "", - "shortTitle": "", - "title": "" - }, - "onIos": { - "1": "", - "shortTitle": "", - "title": "" - }, - "onPc": { - "1": "", - "shortTitle": "", - "title": "" - }, "title": "Скачать" }, "episodes": { @@ -206,23 +153,18 @@ "episodeBadge": "Э{{episode}}", "loadingError": "Ошибка при загрузке сезона", "loadingList": "Загрузка...", - "loadingTitle": "Загрузка...", - "unairedEpisodes": "" + "loadingTitle": "Загрузка..." }, "playback": { "speedLabel": "Скорость воспроизведения", "title": "Настройки воспроизведения" }, "quality": { - "automaticLabel": "Автоматическое качество", - "hint": "", - "iosNoQuality": "", - "title": "" + "automaticLabel": "Автоматическое качество" }, "settings": { "downloadItem": "Скачать", "enableSubtitles": "Включить субтитры", - "experienceSection": "", "playbackItem": "Настройки воспроизведения", "qualityItem": "Качество", "sourceItem": "Видео источники", @@ -231,8 +173,7 @@ }, "sources": { "failed": { - "text": "При попытке найти видео произошла ошибка, пожалуйста, попробуйте использовать другой источник.", - "title": "" + "text": "При попытке найти видео произошла ошибка, пожалуйста, попробуйте использовать другой источник." }, "noEmbeds": { "text": "Мы не смогли найти ни одной вставки, пожалуйста, попробуйте использовать другой источник.", @@ -247,33 +188,11 @@ }, "subtitles": { "customChoice": "Выбрать субтитры из файла", - "customizeLabel": "", "offChoice": "Выключить", "settings": { - "backlink": "Пользовательские субтитры", - "delay": "", - "fixCapitals": "" + "backlink": "Пользовательские субтитры" }, - "title": "Субтитры", - "unknownLanguage": "" - } - }, - "metadata": { - "api": { - "text": "", - "title": "" - }, - "failed": { - "badge": "", - "homeButton": "", - "text": "", - "title": "" - }, - "notFound": { - "badge": "", - "homeButton": "", - "text": "", - "title": "" + "title": "Субтитры" } }, "nextEpisode": { @@ -283,66 +202,30 @@ "playbackError": { "badge": "Ошибка воспроизведения", "errors": { - "errorAborted": "", - "errorDecode": "Несмотря на то, что ранее этот медиаресурс был пригодным для использования, при попытке его декодирования произошла ошибка.", - "errorGenericMedia": "", - "errorNetwork": "", - "errorNotSupported": "" + "errorDecode": "Несмотря на то, что ранее этот медиаресурс был пригодным для использования, при попытке его декодирования произошла ошибка." }, - "homeButton": "", "text": "При попытке воспроизвести медиа файл произошла ошибка. Пожалуйста, попробуйте ещё раз.", "title": "Не удалось воспроизвести видео!" }, "scraping": { - "items": { - "failure": "", - "notFound": "", - "pending": "" - }, "notFound": { - "badge": "", "detailsButton": "Показать детали", - "homeButton": "", - "text": "", "title": "Мы не смогли найти" } }, "time": { - "regular": "{{timeWatched}} / {{duration}}", - "remaining": "", - "shortRegular": "", - "shortRemaining": "" - }, - "turnstile": { - "description": "", - "error": "", - "title": "", - "verifyingHumanity": "" + "regular": "{{timeWatched}} / {{duration}}" } }, "screens": { "dmca": { - "text": "", "title": "DMCA" - }, - "loadingApp": "", - "loadingUser": "", - "loadingUserError": { - "logout": "", - "reset": "", - "text": "", - "textWithReset": "" - }, - "migration": { - "failed": "", - "inProgress": "" } }, "settings": { "account": { "accountDetails": { "deviceNameLabel": "Имя устройства", - "deviceNamePlaceholder": "", "editProfile": "Редактировать", "logoutButton": "Выйти" }, diff --git a/src/assets/locales/sl.json b/src/assets/locales/sl.json index 26c96e59..2c2f6657 100644 --- a/src/assets/locales/sl.json +++ b/src/assets/locales/sl.json @@ -206,8 +206,7 @@ "episodeBadge": "E{{episode}}", "loadingError": "Napaka pri nalaganju sezone", "loadingList": "Nalaganje...", - "loadingTitle": "Nalaganje...", - "unairedEpisodes": "" + "loadingTitle": "Nalaganje..." }, "playback": { "speedLabel": "Hitrost predvajanja", @@ -259,10 +258,6 @@ } }, "metadata": { - "api": { - "text": "", - "title": "" - }, "failed": { "badge": "Neuspešno", "homeButton": "Domov", @@ -312,12 +307,6 @@ "remaining": "{{timeLeft}} do konca • Konča ob {{timeFinished, datetime}}", "shortRegular": "{{timeWatched}}", "shortRemaining": "-{{timeLeft}}" - }, - "turnstile": { - "description": "", - "error": "", - "title": "", - "verifyingHumanity": "" } }, "screens": { diff --git a/src/assets/locales/sv.json b/src/assets/locales/sv.json index 70f6fcd0..94263b93 100644 --- a/src/assets/locales/sv.json +++ b/src/assets/locales/sv.json @@ -27,7 +27,6 @@ "generate": { "description": "Ditt lösenord fungerar som ditt användarnamn och lösenord. Se till att hålla det säkert eftersom du behöver ange det för att logga in på ditt konto", "next": "Jag har sparat mitt lösenord", - "passphraseFrameLabel": "", "title": "Ditt lösenord" }, "hasAccount": "Har redan ett konto? <0>Logga in här.", @@ -120,10 +119,7 @@ }, "titles": { "day": { - "default": "Vad vill du titta på i eftermiddag?", - "extra": [ - "" - ] + "default": "Vad vill du titta på i eftermiddag?" }, "morning": { "default": "Vad vill du titta på den här morgonen?", @@ -179,10 +175,7 @@ "menus": { "downloads": { "disclaimer": "Nedladdningar görs direkt från leverantören. movie-web har ingen kontroll över hur nedladdningarna tillhandahålls.", - "downloadPlaylist": "", - "downloadSubtitle": "", "downloadVideo": "Ladda ner video", - "hlsDisclaimer": "", "onAndroid": { "1": "För att ladda ner på Android, klicka på nedladdningsknappen och på den nya sidan trycker och håller på videon, välj sedan spara.", "shortTitle": "Ladda ner / Android", @@ -206,8 +199,7 @@ "episodeBadge": "E{{episode}}", "loadingError": "Fel vid laddning av säsong", "loadingList": "Laddar...", - "loadingTitle": "Laddar...", - "unairedEpisodes": "" + "loadingTitle": "Laddar..." }, "playback": { "speedLabel": "Uppspelningshastighet", @@ -221,12 +213,10 @@ }, "settings": { "downloadItem": "Ladda ner", - "enableSubtitles": "", "experienceSection": "Visningsupplevelse", "playbackItem": "Uppspelningsinställningar", "qualityItem": "Kvalitet", "sourceItem": "Videokällor", - "subtitleItem": "", "videoSection": "Videoinställningar" }, "sources": { @@ -244,25 +234,9 @@ }, "title": "Källor", "unknownOption": "Okänd" - }, - "subtitles": { - "customChoice": "", - "customizeLabel": "", - "offChoice": "", - "settings": { - "backlink": "", - "delay": "", - "fixCapitals": "" - }, - "title": "", - "unknownLanguage": "" } }, "metadata": { - "api": { - "text": "", - "title": "" - }, "failed": { "badge": "Misslyckades", "homeButton": "Till startsidan", @@ -312,12 +286,6 @@ "remaining": "{{timeLeft}} kvar • Slutar kl {{timeFinished, datetime}}", "shortRegular": "{{timeWatched}}", "shortRemaining": "-{{timeLeft}}" - }, - "turnstile": { - "description": "", - "error": "", - "title": "", - "verifyingHumanity": "" } }, "screens": { @@ -420,13 +388,6 @@ "userId": "Användar-ID" } }, - "subtitles": { - "backgroundLabel": "", - "colorLabel": "", - "previewQuote": "", - "textSizeLabel": "", - "title": "" - }, "unsaved": "Du har osparade ändringar" } } diff --git a/src/assets/locales/ta.json b/src/assets/locales/ta.json index 552bdf52..6c1dfd43 100644 --- a/src/assets/locales/ta.json +++ b/src/assets/locales/ta.json @@ -1,19 +1,6 @@ { "about": { - "description": "", "faqTitle": "பொதுவான கேள்விகள்", - "q1": { - "body": "", - "title": "" - }, - "q2": { - "body": "", - "title": "" - }, - "q3": { - "body": "", - "title": "" - }, "title": "movie-web பற்றி" }, "actions": { @@ -42,492 +29,39 @@ }, "register": { "information": { - "color1": "", - "color2": "", - "header": "", "icon": "பயனர் குறிப்படம்", "next": "அடுத்து", "title": "கணக்கு விவரம்" } }, "trust": { - "failed": { - "text": "", - "title": "" - }, - "host": "", - "no": "பின்செல்", - "title": "", - "yes": "" + "no": "பின்செல்" }, "verify": { - "description": "", - "invalidData": "", - "noMatch": "", - "passphraseLabel": "", - "recaptchaFailed": "", "register": "கணக்கை உருவாக்கு", "title": "கடவுச்சொற்றொடரை உறுதி செய்க" } }, - "errors": { - "badge": "", - "details": "", - "reloadPage": "", - "showError": "", - "title": "" - }, - "footer": { - "legal": { - "disclaimer": "", - "disclaimerText": "" - }, - "links": { - "discord": "", - "dmca": "", - "github": "" - }, - "tagline": "" - }, "global": { - "name": "", "pages": { - "about": "", - "dmca": "", "login": "புகுபதிகை", - "onboarding": "", - "pagetitle": "", - "register": "", "settings": "அமைப்புகள்" } }, "home": { - "bookmarks": { - "sectionTitle": "" - }, - "continueWatching": { - "sectionTitle": "" - }, - "mediaList": { - "stopEditing": "" - }, "search": { - "allResults": "", - "failed": "", - "loading": "", - "noResults": "", - "placeholder": "", "sectionTitle": "தேடல் முடிவுகள்" - }, - "titles": { - "day": { - "default": "", - "extra": [ - "" - ] - }, - "morning": { - "default": "", - "extra": [ - "" - ] - }, - "night": { - "default": "", - "extra": [ - "" - ] - } } }, "media": { - "episodeDisplay": "", "types": { "movie": "திரைப்படம்", "show": "காட்சி" } }, "navigation": { - "banner": { - "offline": "" - }, "menu": { - "about": "", - "donation": "", - "logout": "", - "register": "", - "settings": "அமைப்புகள்", - "support": "" + "settings": "அமைப்புகள்" } - }, - "notFound": { - "badge": "", - "goHome": "", - "message": "", - "title": "" - }, - "onboarding": { - "defaultConfirm": { - "cancel": "", - "confirm": "", - "description": "", - "title": "" - }, - "extension": { - "back": "", - "explainer": "", - "extensionHelp": "", - "link": "", - "status": { - "disallowed": "", - "disallowedAction": "", - "failed": "", - "loading": "", - "outdated": "", - "success": "" - }, - "submit": "", - "title": "" - }, - "proxy": { - "back": "", - "explainer": "", - "input": { - "errorConnection": "", - "errorInvalidUrl": "", - "errorNotProxy": "", - "label": "", - "placeholder": "" - }, - "link": "", - "submit": "", - "title": "" - }, - "start": { - "explainer": "", - "options": { - "default": { - "text": "" - }, - "extension": { - "action": "", - "description": "", - "quality": "", - "title": "" - }, - "proxy": { - "action": "", - "description": "", - "quality": "", - "title": "" - } - }, - "title": "" - } - }, - "overlays": { - "close": "" - }, - "player": { - "back": { - "default": "", - "short": "" - }, - "casting": { - "enabled": "" - }, - "menus": { - "downloads": { - "disclaimer": "", - "downloadPlaylist": "", - "downloadSubtitle": "", - "downloadVideo": "", - "hlsDisclaimer": "", - "onAndroid": { - "1": "", - "shortTitle": "", - "title": "" - }, - "onIos": { - "1": "", - "shortTitle": "", - "title": "" - }, - "onPc": { - "1": "", - "shortTitle": "", - "title": "" - }, - "title": "" - }, - "episodes": { - "button": "", - "emptyState": "", - "episodeBadge": "", - "loadingError": "", - "loadingList": "", - "loadingTitle": "", - "unairedEpisodes": "" - }, - "playback": { - "speedLabel": "", - "title": "" - }, - "quality": { - "automaticLabel": "", - "hint": "", - "iosNoQuality": "", - "title": "" - }, - "settings": { - "downloadItem": "", - "enableSubtitles": "", - "experienceSection": "", - "playbackItem": "", - "qualityItem": "", - "sourceItem": "", - "subtitleItem": "", - "videoSection": "" - }, - "sources": { - "failed": { - "text": "", - "title": "" - }, - "noEmbeds": { - "text": "", - "title": "" - }, - "noStream": { - "text": "", - "title": "" - }, - "title": "", - "unknownOption": "" - }, - "subtitles": { - "customChoice": "", - "customizeLabel": "", - "offChoice": "", - "settings": { - "backlink": "", - "delay": "", - "fixCapitals": "" - }, - "title": "", - "unknownLanguage": "" - } - }, - "metadata": { - "api": { - "text": "", - "title": "" - }, - "dmca": { - "badge": "", - "text": "", - "title": "" - }, - "extensionPermission": { - "badge": "", - "button": "", - "text": "", - "title": "" - }, - "failed": { - "badge": "", - "homeButton": "", - "text": "", - "title": "" - }, - "notFound": { - "badge": "", - "homeButton": "", - "text": "", - "title": "" - } - }, - "nextEpisode": { - "cancel": "", - "next": "" - }, - "playbackError": { - "badge": "", - "errors": { - "errorAborted": "", - "errorDecode": "", - "errorGenericMedia": "", - "errorNetwork": "", - "errorNotSupported": "" - }, - "homeButton": "", - "text": "", - "title": "" - }, - "scraping": { - "items": { - "failure": "", - "notFound": "", - "pending": "" - }, - "notFound": { - "badge": "", - "detailsButton": "", - "homeButton": "", - "text": "", - "title": "" - } - }, - "time": { - "regular": "", - "remaining": "", - "shortRegular": "", - "shortRemaining": "" - }, - "turnstile": { - "description": "", - "error": "", - "title": "", - "verifyingHumanity": "" - } - }, - "screens": { - "dmca": { - "text": "", - "title": "" - }, - "loadingApp": "", - "loadingUser": "", - "loadingUserError": { - "logout": "", - "reset": "", - "text": "", - "textWithReset": "" - }, - "migration": { - "failed": "", - "inProgress": "" - } - }, - "settings": { - "account": { - "accountDetails": { - "deviceNameLabel": "", - "deviceNamePlaceholder": "", - "editProfile": "", - "logoutButton": "" - }, - "actions": { - "delete": { - "button": "", - "confirmButton": "", - "confirmDescription": "", - "confirmTitle": "", - "text": "", - "title": "" - }, - "title": "" - }, - "devices": { - "deviceNameLabel": "", - "failed": "", - "removeDevice": "", - "title": "" - }, - "profile": { - "finish": "", - "firstColor": "", - "secondColor": "", - "title": "", - "userIcon": "" - }, - "register": { - "cta": "", - "text": "", - "title": "" - }, - "title": "" - }, - "appearance": { - "activeTheme": "", - "themes": { - "blue": "", - "default": "", - "gray": "", - "red": "", - "teal": "" - }, - "title": "" - }, - "connections": { - "server": { - "description": "", - "label": "", - "urlLabel": "" - }, - "setup": { - "doSetup": "", - "errorStatus": { - "description": "", - "title": "" - }, - "itemError": "", - "items": { - "default": "", - "extension": "", - "proxy": "" - }, - "redoSetup": "", - "successStatus": { - "description": "", - "title": "" - }, - "unsetStatus": { - "description": "", - "title": "" - } - }, - "title": "", - "workers": { - "addButton": "", - "description": "", - "emptyState": "", - "label": "", - "urlLabel": "", - "urlPlaceholder": "" - } - }, - "preferences": { - "language": "", - "languageDescription": "", - "thumbnail": "", - "thumbnailDescription": "", - "thumbnailLabel": "", - "title": "" - }, - "reset": "", - "save": "", - "sidebar": { - "info": { - "appVersion": "", - "backendUrl": "", - "backendVersion": "", - "hostname": "", - "insecure": "", - "notLoggedIn": "", - "secure": "", - "title": "", - "unknownVersion": "", - "userId": "" - } - }, - "subtitles": { - "backgroundLabel": "", - "colorLabel": "", - "previewQuote": "", - "textSizeLabel": "", - "title": "" - }, - "unsaved": "" } } diff --git a/src/assets/locales/th.json b/src/assets/locales/th.json index 0c379317..7f0f4943 100644 --- a/src/assets/locales/th.json +++ b/src/assets/locales/th.json @@ -120,10 +120,7 @@ }, "titles": { "day": { - "default": "คุณอยากดูเรื่องอะไรในช่วงบ่ายนี้?", - "extra": [ - "" - ] + "default": "คุณอยากดูเรื่องอะไรในช่วงบ่ายนี้?" }, "morning": { "default": "คุณอยากดูอะไรเช้านี้?", @@ -206,8 +203,7 @@ "episodeBadge": "ตอนที่ {{episode}}", "loadingError": "การโหลดภาคผิดพลาด", "loadingList": "กำลังโหลด…", - "loadingTitle": "กำลังโหลด…", - "unairedEpisodes": "" + "loadingTitle": "กำลังโหลด…" }, "playback": { "speedLabel": "ความเร็วในการเล่น", @@ -251,18 +247,13 @@ "offChoice": "ปิด", "settings": { "backlink": "คำบรรยายแบบกำหนดเอง", - "delay": "เวลาดีเลย์คำบรรยาย", - "fixCapitals": "" + "delay": "เวลาดีเลย์คำบรรยาย" }, "title": "คำบรรยาย", "unknownLanguage": "ไม่ทราบ" } }, "metadata": { - "api": { - "text": "", - "title": "" - }, "failed": { "badge": "ล้มเหลว", "homeButton": "กลับหน้าหลัก", @@ -312,12 +303,6 @@ "remaining": "{{timeLeft}} หมดเวลา • สิ้นสุดใน {{timeFinished, datetime}}", "shortRegular": "{{timeWatched}}", "shortRemaining": "-{{timeLeft}}" - }, - "turnstile": { - "description": "", - "error": "", - "title": "", - "verifyingHumanity": "" } }, "screens": { diff --git a/src/assets/locales/tok.json b/src/assets/locales/tok.json index ac59f2b4..5fa05c9a 100644 --- a/src/assets/locales/tok.json +++ b/src/assets/locales/tok.json @@ -79,8 +79,7 @@ }, "footer": { "legal": { - "disclaimer": "o sona e ni:", - "disclaimerText": "" + "disclaimer": "o sona e ni:" }, "links": { "discord": "kulupu Siko", @@ -206,8 +205,7 @@ "episodeBadge": "E{{episode}}", "loadingError": "alasa li pakala", "loadingList": "alasa...", - "loadingTitle": "alasa...", - "unairedEpisodes": "" + "loadingTitle": "alasa..." }, "playback": { "speedLabel": "tenpo lukin", @@ -259,10 +257,6 @@ } }, "metadata": { - "api": { - "text": "", - "title": "" - }, "failed": { "badge": "pakala", "homeButton": "o tawa weka", @@ -312,17 +306,10 @@ "remaining": "tenpo {{timeLeft}} la o awen • tenpo {{timeFinished, datetime}} la ona li pini", "shortRegular": "{{timeWatched}}", "shortRemaining": "-{{timeLeft}}" - }, - "turnstile": { - "description": "", - "error": "", - "title": "", - "verifyingHumanity": "" } }, "screens": { "dmca": { - "text": "", "title": "DMCA" }, "loadingApp": "mi alasa e ilo", @@ -334,7 +321,6 @@ "textWithReset": "alasa tan lawa ilo sina li pakala. sina wile e lawa ilo mi anu seme?" }, "migration": { - "failed": "", "inProgress": "o awen lili. mi alasa tawa e sona sina" } }, @@ -394,32 +380,10 @@ "label": "lawa ante", "urlLabel": "nimi pi lawa ante" }, - "title": "kulupu", - "workers": { - "addButton": "", - "description": "", - "emptyState": "", - "label": "", - "urlLabel": "", - "urlPlaceholder": "" - } + "title": "kulupu" }, "reset": "o weka e ante", "save": "o ante", - "sidebar": { - "info": { - "appVersion": "", - "backendUrl": "", - "backendVersion": "", - "hostname": "", - "insecure": "", - "notLoggedIn": "", - "secure": "", - "title": "", - "unknownVersion": "", - "userId": "" - } - }, "subtitles": { "backgroundLabel": "kon", "colorLabel": "kule", diff --git a/src/assets/locales/vi.json b/src/assets/locales/vi.json index 35a58031..098a100d 100644 --- a/src/assets/locales/vi.json +++ b/src/assets/locales/vi.json @@ -92,13 +92,8 @@ "global": { "name": "movie-web", "pages": { - "about": "", - "dmca": "", - "login": "", - "onboarding": "", "pagetitle": "{{title}} - movie-web", - "register": "Đăng ký", - "settings": "" + "register": "Đăng ký" } }, "home": { @@ -108,9 +103,6 @@ "continueWatching": { "sectionTitle": "Tiếp tục xem" }, - "mediaList": { - "stopEditing": "" - }, "search": { "allResults": "Đó là tất cả chúng tôi có!", "failed": "Không thể tìm thấy nội dung, hãy thử lại!", @@ -118,26 +110,6 @@ "noResults": "Chúng tôi không thể tìm thấy gì!", "placeholder": "Bạn muốn xem gì?", "sectionTitle": "Kết quả tìm kiếm" - }, - "titles": { - "day": { - "default": "", - "extra": [ - "" - ] - }, - "morning": { - "default": "", - "extra": [ - "" - ] - }, - "night": { - "default": "", - "extra": [ - "" - ] - } } }, "media": { @@ -150,14 +122,6 @@ "navigation": { "banner": { "offline": "Hãy kiểm tra kết nối Internet của bạn" - }, - "menu": { - "about": "", - "donation": "", - "logout": "", - "register": "", - "settings": "", - "support": "" } }, "notFound": { @@ -166,180 +130,22 @@ "message": "Chúng tôi đã tìm kiếm khắp nơi: dưới thùng rác, trong tủ quần áo, đằng sau máy chủ proxy nhưng vẫn không thể tìm thấy trang bạn đang tìm kiếm.", "title": "Không thể tìm thấy trang" }, - "onboarding": { - "defaultConfirm": { - "cancel": "", - "confirm": "", - "description": "", - "title": "" - }, - "extension": { - "back": "", - "explainer": "", - "extensionHelp": "", - "link": "", - "status": { - "disallowed": "", - "disallowedAction": "", - "failed": "", - "loading": "", - "outdated": "", - "success": "" - }, - "submit": "", - "title": "" - }, - "proxy": { - "back": "", - "explainer": "", - "input": { - "errorConnection": "", - "errorInvalidUrl": "", - "errorNotProxy": "", - "label": "", - "placeholder": "" - }, - "link": "", - "submit": "", - "title": "" - }, - "start": { - "explainer": "", - "options": { - "default": { - "text": "" - }, - "extension": { - "action": "", - "description": "", - "quality": "", - "title": "" - }, - "proxy": { - "action": "", - "description": "", - "quality": "", - "title": "" - } - }, - "title": "" - } - }, - "overlays": { - "close": "" - }, "player": { "back": { "default": "Quay lại trang chính", "short": "Quay lại" }, - "casting": { - "enabled": "" - }, "menus": { - "downloads": { - "disclaimer": "", - "downloadPlaylist": "", - "downloadSubtitle": "", - "downloadVideo": "", - "hlsDisclaimer": "", - "onAndroid": { - "1": "", - "shortTitle": "", - "title": "" - }, - "onIos": { - "1": "", - "shortTitle": "", - "title": "" - }, - "onPc": { - "1": "", - "shortTitle": "", - "title": "" - }, - "title": "" - }, "episodes": { "button": "Tập", - "emptyState": "", - "episodeBadge": "", - "loadingError": "", "loadingList": "Đang tải...", - "loadingTitle": "Đang tải...", - "unairedEpisodes": "" - }, - "playback": { - "speedLabel": "", - "title": "" - }, - "quality": { - "automaticLabel": "", - "hint": "", - "iosNoQuality": "", - "title": "" - }, - "settings": { - "downloadItem": "", - "enableSubtitles": "", - "experienceSection": "", - "playbackItem": "", - "qualityItem": "", - "sourceItem": "", - "subtitleItem": "", - "videoSection": "" + "loadingTitle": "Đang tải..." }, "sources": { - "failed": { - "text": "", - "title": "" - }, - "noEmbeds": { - "text": "", - "title": "" - }, - "noStream": { - "text": "", - "title": "" - }, - "title": "Nguồn", - "unknownOption": "" - }, - "subtitles": { - "customChoice": "", - "customizeLabel": "", - "offChoice": "", - "settings": { - "backlink": "", - "delay": "", - "fixCapitals": "" - }, - "title": "", - "unknownLanguage": "" + "title": "Nguồn" } }, "metadata": { - "api": { - "text": "", - "title": "" - }, - "dmca": { - "badge": "", - "text": "", - "title": "" - }, - "extensionPermission": { - "badge": "", - "button": "", - "text": "", - "title": "" - }, - "failed": { - "badge": "", - "homeButton": "", - "text": "", - "title": "" - }, "notFound": { "badge": "Không tìm thấy", "homeButton": "Quay lại trang chính", @@ -347,187 +153,8 @@ "title": "Không thể tìm thấy nội dung." } }, - "nextEpisode": { - "cancel": "", - "next": "" - }, "playbackError": { - "badge": "", - "errors": { - "errorAborted": "", - "errorDecode": "", - "errorGenericMedia": "", - "errorNetwork": "", - "errorNotSupported": "" - }, - "homeButton": "", - "text": "", "title": "Rất tiếc, đã hỏng!" - }, - "scraping": { - "items": { - "failure": "", - "notFound": "", - "pending": "" - }, - "notFound": { - "badge": "", - "detailsButton": "", - "homeButton": "", - "text": "", - "title": "" - } - }, - "time": { - "regular": "", - "remaining": "", - "shortRegular": "", - "shortRemaining": "" - }, - "turnstile": { - "description": "", - "error": "", - "title": "", - "verifyingHumanity": "" } - }, - "screens": { - "dmca": { - "text": "", - "title": "" - }, - "loadingApp": "", - "loadingUser": "", - "loadingUserError": { - "logout": "", - "reset": "", - "text": "", - "textWithReset": "" - }, - "migration": { - "failed": "", - "inProgress": "" - } - }, - "settings": { - "account": { - "accountDetails": { - "deviceNameLabel": "", - "deviceNamePlaceholder": "", - "editProfile": "", - "logoutButton": "" - }, - "actions": { - "delete": { - "button": "", - "confirmButton": "", - "confirmDescription": "", - "confirmTitle": "", - "text": "", - "title": "" - }, - "title": "" - }, - "devices": { - "deviceNameLabel": "", - "failed": "", - "removeDevice": "", - "title": "" - }, - "profile": { - "finish": "", - "firstColor": "", - "secondColor": "", - "title": "", - "userIcon": "" - }, - "register": { - "cta": "", - "text": "", - "title": "" - }, - "title": "" - }, - "appearance": { - "activeTheme": "", - "themes": { - "blue": "", - "default": "", - "gray": "", - "red": "", - "teal": "" - }, - "title": "" - }, - "connections": { - "server": { - "description": "", - "label": "", - "urlLabel": "" - }, - "setup": { - "doSetup": "", - "errorStatus": { - "description": "", - "title": "" - }, - "itemError": "", - "items": { - "default": "", - "extension": "", - "proxy": "" - }, - "redoSetup": "", - "successStatus": { - "description": "", - "title": "" - }, - "unsetStatus": { - "description": "", - "title": "" - } - }, - "title": "", - "workers": { - "addButton": "", - "description": "", - "emptyState": "", - "label": "", - "urlLabel": "", - "urlPlaceholder": "" - } - }, - "preferences": { - "language": "", - "languageDescription": "", - "thumbnail": "", - "thumbnailDescription": "", - "thumbnailLabel": "", - "title": "" - }, - "reset": "", - "save": "", - "sidebar": { - "info": { - "appVersion": "", - "backendUrl": "", - "backendVersion": "", - "hostname": "", - "insecure": "", - "notLoggedIn": "", - "secure": "", - "title": "", - "unknownVersion": "", - "userId": "" - } - }, - "subtitles": { - "backgroundLabel": "", - "colorLabel": "", - "previewQuote": "", - "textSizeLabel": "", - "title": "" - }, - "unsaved": "" } } diff --git a/src/assets/locales/zh-Hant.json b/src/assets/locales/zh-Hant.json index 4c5abbb8..ad03d9ef 100644 --- a/src/assets/locales/zh-Hant.json +++ b/src/assets/locales/zh-Hant.json @@ -5,99 +5,17 @@ "q1": { "body": "movie-web 不託管任何內容。您點選觀看內容時,系統均從互聯網搜尋(在加載提示頁和“視頻源”選項卡中,您可以看到正在使用的源)。媒體從未在 movie-web 中上傳,所有內容均通過搜索機制而得。", "title": "內容來自哪裡?" - }, - "q2": { - "body": "", - "title": "" - }, - "q3": { - "body": "", - "title": "" - }, - "title": "" - }, - "actions": { - "copied": "", - "copy": "" - }, - "auth": { - "createAccount": "", - "deviceNameLabel": "", - "deviceNamePlaceholder": "", - "generate": { - "description": "", - "next": "", - "passphraseFrameLabel": "", - "title": "" - }, - "hasAccount": "", - "login": { - "description": "", - "deviceLengthError": "", - "passphraseLabel": "", - "passphrasePlaceholder": "", - "submit": "登入", - "title": "", - "validationError": "" - }, - "register": { - "information": { - "color1": "", - "color2": "", - "header": "", - "icon": "", - "next": "", - "title": "" - } - }, - "trust": { - "failed": { - "text": "", - "title": "" - }, - "host": "", - "no": "", - "title": "", - "yes": "" - }, - "verify": { - "description": "", - "invalidData": "", - "noMatch": "", - "passphraseLabel": "", - "recaptchaFailed": "", - "register": "", - "title": "" } }, - "errors": { - "badge": "", - "details": "", - "reloadPage": "", - "showError": "", - "title": "" - }, - "footer": { - "legal": { - "disclaimer": "", - "disclaimerText": "" - }, - "links": { - "discord": "", - "dmca": "", - "github": "" - }, - "tagline": "" + "auth": { + "login": { + "submit": "登入" + } }, "global": { - "name": "", "pages": { "about": "關於", - "dmca": "", "login": "登入", - "onboarding": "", - "pagetitle": "", - "register": "", "settings": "設定" } }, @@ -105,429 +23,80 @@ "bookmarks": { "sectionTitle": "書籤" }, - "continueWatching": { - "sectionTitle": "" - }, - "mediaList": { - "stopEditing": "" - }, "search": { - "allResults": "", - "failed": "", - "loading": "載入中...", - "noResults": "", - "placeholder": "", - "sectionTitle": "" - }, - "titles": { - "day": { - "default": "", - "extra": [ - "" - ] - }, - "morning": { - "default": "", - "extra": [ - "" - ] - }, - "night": { - "default": "", - "extra": [ - "" - ] - } + "loading": "載入中..." } }, "media": { - "episodeDisplay": "", "types": { "movie": "電影", "show": "節目" } }, "navigation": { - "banner": { - "offline": "" - }, "menu": { - "about": "", "donation": "捐", - "logout": "", - "register": "", "settings": "設定", "support": "支援" } }, - "notFound": { - "badge": "", - "goHome": "", - "message": "", - "title": "" - }, - "onboarding": { - "defaultConfirm": { - "cancel": "", - "confirm": "", - "description": "", - "title": "" - }, - "extension": { - "back": "", - "explainer": "", - "extensionHelp": "", - "link": "", - "status": { - "disallowed": "", - "disallowedAction": "", - "failed": "", - "loading": "", - "outdated": "", - "success": "" - }, - "submit": "", - "title": "" - }, - "proxy": { - "back": "", - "explainer": "", - "input": { - "errorConnection": "", - "errorInvalidUrl": "", - "errorNotProxy": "", - "label": "", - "placeholder": "" - }, - "link": "", - "submit": "", - "title": "" - }, - "start": { - "explainer": "", - "options": { - "default": { - "text": "" - }, - "extension": { - "action": "", - "description": "", - "quality": "", - "title": "" - }, - "proxy": { - "action": "", - "description": "", - "quality": "", - "title": "" - } - }, - "title": "" - } - }, "overlays": { "close": "關閉" }, "player": { "back": { - "default": "", "short": "後退" }, - "casting": { - "enabled": "" - }, "menus": { "downloads": { - "disclaimer": "", - "downloadPlaylist": "", - "downloadSubtitle": "", - "downloadVideo": "", - "hlsDisclaimer": "", - "onAndroid": { - "1": "", - "shortTitle": "", - "title": "" - }, - "onIos": { - "1": "", - "shortTitle": "", - "title": "" - }, - "onPc": { - "1": "", - "shortTitle": "", - "title": "" - }, "title": "下載" }, "episodes": { - "button": "", - "emptyState": "", - "episodeBadge": "", - "loadingError": "", "loadingList": "載入中...", - "loadingTitle": "載入中...", - "unairedEpisodes": "" - }, - "playback": { - "speedLabel": "", - "title": "" - }, - "quality": { - "automaticLabel": "", - "hint": "", - "iosNoQuality": "", - "title": "" + "loadingTitle": "載入中..." }, "settings": { - "downloadItem": "下載", - "enableSubtitles": "", - "experienceSection": "", - "playbackItem": "", - "qualityItem": "", - "sourceItem": "", - "subtitleItem": "", - "videoSection": "" - }, - "sources": { - "failed": { - "text": "", - "title": "" - }, - "noEmbeds": { - "text": "", - "title": "" - }, - "noStream": { - "text": "", - "title": "" - }, - "title": "", - "unknownOption": "" + "downloadItem": "下載" }, "subtitles": { - "customChoice": "", - "customizeLabel": "", - "offChoice": "", - "settings": { - "backlink": "", - "delay": "", - "fixCapitals": "" - }, - "title": "字幕", - "unknownLanguage": "" + "title": "字幕" } }, "metadata": { - "api": { - "text": "", - "title": "" - }, - "dmca": { - "badge": "", - "text": "", - "title": "" - }, - "extensionPermission": { - "badge": "", - "button": "", - "text": "", - "title": "" - }, "failed": { - "badge": "失敗", - "homeButton": "", - "text": "", - "title": "" - }, - "notFound": { - "badge": "", - "homeButton": "", - "text": "", - "title": "" + "badge": "失敗" } }, "nextEpisode": { - "cancel": "取消", - "next": "" - }, - "playbackError": { - "badge": "", - "errors": { - "errorAborted": "", - "errorDecode": "", - "errorGenericMedia": "", - "errorNetwork": "", - "errorNotSupported": "" - }, - "homeButton": "", - "text": "", - "title": "" - }, - "scraping": { - "items": { - "failure": "", - "notFound": "", - "pending": "" - }, - "notFound": { - "badge": "", - "detailsButton": "", - "homeButton": "", - "text": "", - "title": "" - } - }, - "time": { - "regular": "", - "remaining": "", - "shortRegular": "", - "shortRemaining": "" - }, - "turnstile": { - "description": "", - "error": "", - "title": "", - "verifyingHumanity": "" + "cancel": "取消" } }, "screens": { - "dmca": { - "text": "", - "title": "" - }, - "loadingApp": "", - "loadingUser": "", "loadingUserError": { - "logout": "登出", - "reset": "", - "text": "", - "textWithReset": "" - }, - "migration": { - "failed": "", - "inProgress": "" + "logout": "登出" } }, "settings": { "account": { - "accountDetails": { - "deviceNameLabel": "", - "deviceNamePlaceholder": "", - "editProfile": "", - "logoutButton": "" - }, - "actions": { - "delete": { - "button": "", - "confirmButton": "", - "confirmDescription": "", - "confirmTitle": "", - "text": "", - "title": "" - }, - "title": "" - }, - "devices": { - "deviceNameLabel": "", - "failed": "", - "removeDevice": "", - "title": "" - }, - "profile": { - "finish": "", - "firstColor": "", - "secondColor": "", - "title": "", - "userIcon": "" - }, - "register": { - "cta": "", - "text": "", - "title": "" - }, "title": "帳戶" }, "appearance": { - "activeTheme": "", "themes": { "blue": "藍色", - "default": "", "gray": "灰色", "red": "紅色", "teal": "青色" - }, - "title": "" - }, - "connections": { - "server": { - "description": "", - "label": "", - "urlLabel": "" - }, - "setup": { - "doSetup": "", - "errorStatus": { - "description": "", - "title": "" - }, - "itemError": "", - "items": { - "default": "", - "extension": "", - "proxy": "" - }, - "redoSetup": "", - "successStatus": { - "description": "", - "title": "" - }, - "unsetStatus": { - "description": "", - "title": "" - } - }, - "title": "", - "workers": { - "addButton": "", - "description": "", - "emptyState": "", - "label": "", - "urlLabel": "", - "urlPlaceholder": "" } }, - "preferences": { - "language": "", - "languageDescription": "", - "thumbnail": "", - "thumbnailDescription": "", - "thumbnailLabel": "", - "title": "" - }, - "reset": "", - "save": "", "sidebar": { "info": { - "appVersion": "", - "backendUrl": "", - "backendVersion": "", - "hostname": "", "insecure": "不安全", - "notLoggedIn": "", - "secure": "安全", - "title": "", - "unknownVersion": "", - "userId": "" + "secure": "安全" } }, "subtitles": { - "backgroundLabel": "", "colorLabel": "顏色", - "previewQuote": "", - "textSizeLabel": "", "title": "字幕" - }, - "unsaved": "" + } } } From 09515cd1479d058bd59a86a64af47c34b3fde3f5 Mon Sep 17 00:00:00 2001 From: Ninguart Date: Tue, 23 Jan 2024 20:11:21 +0000 Subject: [PATCH 122/151] Translated using Weblate (Czech) Currently translated at 80.4% (255 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/cs/ Author: Ninguart --- src/assets/locales/cs.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/assets/locales/cs.json b/src/assets/locales/cs.json index 54f23e05..5d94a9e5 100644 --- a/src/assets/locales/cs.json +++ b/src/assets/locales/cs.json @@ -263,6 +263,10 @@ "text": "Metadata API nelze načíst, zkontrolujte prosím vaše připojení k internetu.", "title": "Nepodařilo se načíst API metadata" }, + "extensionPermission": { + "badge": "Chybí povolení", + "title": "Konfigurace rozšíření" + }, "failed": { "badge": "Neúspěšný", "homeButton": "Jít domů", From 835a24508f1dbfd8caaf68ad07e173a36b7189cc Mon Sep 17 00:00:00 2001 From: teaishealthy Date: Tue, 23 Jan 2024 20:12:07 +0000 Subject: [PATCH 123/151] Translated using Weblate (German) Currently translated at 82.0% (260 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/de/ Author: teaishealthy --- src/assets/locales/de.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/assets/locales/de.json b/src/assets/locales/de.json index c6588f36..ec1de41b 100644 --- a/src/assets/locales/de.json +++ b/src/assets/locales/de.json @@ -263,6 +263,11 @@ "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" + }, "failed": { "badge": "Fehlgeschlagen", "homeButton": "Zurück zur Startseite", @@ -394,6 +399,16 @@ "label": "Eigener Server", "urlLabel": "Eigene Server-URL" }, + "setup": { + "doSetup": "Einrichten", + "items": { + "extension": "Erweiterung" + }, + "redoSetup": "Erneut einrichten", + "successStatus": { + "title": "Alles eingerichtet!" + } + }, "title": "Verbindung", "workers": { "addButton": "Neuen Worker hinzufügen", From c995aa86c9ed7db384065307bc1ccdfbb856cb6c Mon Sep 17 00:00:00 2001 From: Denys Savin Date: Tue, 23 Jan 2024 20:13:12 +0000 Subject: [PATCH 124/151] Translated using Weblate (Ukrainian) Currently translated at 80.7% (256 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/uk/ Author: Denys Savin --- src/assets/locales/uk.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/assets/locales/uk.json b/src/assets/locales/uk.json index 2a83b67a..286c61a3 100644 --- a/src/assets/locales/uk.json +++ b/src/assets/locales/uk.json @@ -95,6 +95,7 @@ "about": "Про", "dmca": "DMCA", "login": "Логін", + "onboarding": "Встановлення", "pagetitle": "{{title}} - movie-web", "register": "Зареєструватися", "settings": "Налаштування" @@ -263,6 +264,10 @@ "text": "Не вдалося завантажити метадані API, перевірте підключення до Інтернету.", "title": "Не вдалося завантажити метадані API" }, + "extensionPermission": { + "badge": "Дозвіл Відсутній", + "title": "Налаштуйте продовження" + }, "failed": { "badge": "Не вдалося", "homeButton": "Повернутися на головну", From fd23044e59bdfce926be3fe6c38c99533d85b42b Mon Sep 17 00:00:00 2001 From: Ninguart Date: Tue, 23 Jan 2024 20:15:06 +0000 Subject: [PATCH 125/151] Translated using Weblate (Czech) Currently translated at 82.0% (260 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/cs/ Author: Ninguart --- src/assets/locales/cs.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/assets/locales/cs.json b/src/assets/locales/cs.json index 5d94a9e5..f474d7ca 100644 --- a/src/assets/locales/cs.json +++ b/src/assets/locales/cs.json @@ -263,8 +263,14 @@ "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", + "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": { From b072794a63c8b896e1ef1617255a8411ffb5004f Mon Sep 17 00:00:00 2001 From: 5Litt <5Litt@users.noreply.weblate.movie-web.app> Date: Tue, 23 Jan 2024 20:16:23 +0000 Subject: [PATCH 126/151] Translated using Weblate (Czech) Currently translated at 82.0% (260 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/cs/ Author: 5Litt <5Litt@users.noreply.weblate.movie-web.app> --- src/assets/locales/cs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assets/locales/cs.json b/src/assets/locales/cs.json index f474d7ca..9a912e04 100644 --- a/src/assets/locales/cs.json +++ b/src/assets/locales/cs.json @@ -182,7 +182,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.

Vezměte prosím na vědomí, že stahujete HLS playlist, který není doporučen stahovat pokud nejste obeznámeni s pokročilým streamováním médií. 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 klepněte a podržte na videu a poté vyberte uložit.", "shortTitle": "Stahování / Android", From 8b9e657a04d57ac2eeca53bb505c39139de18f32 Mon Sep 17 00:00:00 2001 From: atomic Date: Tue, 23 Jan 2024 20:14:32 +0000 Subject: [PATCH 127/151] Translated using Weblate (French) Currently translated at 82.3% (261 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/fr/ Author: atomic --- src/assets/locales/fr.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/assets/locales/fr.json b/src/assets/locales/fr.json index 6234126f..352862f3 100644 --- a/src/assets/locales/fr.json +++ b/src/assets/locales/fr.json @@ -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" @@ -263,6 +264,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", From fa7ed9bd25c2ccb7bcbbab7ef15dad48540c9f86 Mon Sep 17 00:00:00 2001 From: Denys Savin Date: Tue, 23 Jan 2024 20:15:26 +0000 Subject: [PATCH 128/151] Translated using Weblate (Ukrainian) Currently translated at 83.2% (264 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/uk/ Author: Denys Savin --- src/assets/locales/uk.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/assets/locales/uk.json b/src/assets/locales/uk.json index 286c61a3..f81de1ec 100644 --- a/src/assets/locales/uk.json +++ b/src/assets/locales/uk.json @@ -264,8 +264,15 @@ "text": "Не вдалося завантажити метадані API, перевірте підключення до Інтернету.", "title": "Не вдалося завантажити метадані API" }, + "dmca": { + "badge": "Видалено", + "text": "Це медіа більше не доступне через повідомлення про видалення або позов про порушення авторських прав.", + "title": "Медіа було видалено" + }, "extensionPermission": { "badge": "Дозвіл Відсутній", + "button": "Використовувати розширення", + "text": "У вас вже є розширення для браузера, але нам потрібен ваш дозвіл, щоб почати використовувати його.", "title": "Налаштуйте продовження" }, "failed": { @@ -399,6 +406,15 @@ "label": "Власний сервер", "urlLabel": "URL сервера" }, + "setup": { + "errorStatus": { + "description": "Здається, що один або декілька пунктів у цьому налаштуванні потребують вашої уваги.", + "title": "Дещо потребує вашої уваги" + }, + "unsetStatus": { + "title": "Ви не завершили налаштування" + } + }, "title": "З'єднання", "workers": { "addButton": "Додати нового працівника", From 9bd053818bc382dbad200b35f5d363cd72c0d421 Mon Sep 17 00:00:00 2001 From: Ninguart Date: Tue, 23 Jan 2024 20:22:04 +0000 Subject: [PATCH 129/151] Translated using Weblate (Czech) Currently translated at 88.3% (280 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/cs/ Author: Ninguart --- src/assets/locales/cs.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/assets/locales/cs.json b/src/assets/locales/cs.json index 9a912e04..3fd2586b 100644 --- a/src/assets/locales/cs.json +++ b/src/assets/locales/cs.json @@ -165,6 +165,11 @@ "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": { + "start": { + "title": "Pojďme vám nastavit movie-web" + } + }, "overlays": { "close": "Zavřít" }, @@ -404,6 +409,13 @@ "label": "Vlastní server", "urlLabel": "URL adresa vlastního serveru" }, + "setup": { + "items": { + "default": "Výchozí proxy", + "extension": "Rozšíření", + "proxy": "Vlastní proxy" + } + }, "title": "Spojení", "workers": { "addButton": "Přidat nového pracovníka", @@ -414,6 +426,14 @@ "urlPlaceholder": "https://" } }, + "preferences": { + "language": "Jazyk aplikace", + "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", "sidebar": { From d93d8e54a037b40e72707fe80a615dac5cf2f264 Mon Sep 17 00:00:00 2001 From: 5Litt <5Litt@users.noreply.weblate.movie-web.app> Date: Tue, 23 Jan 2024 20:18:47 +0000 Subject: [PATCH 130/151] Translated using Weblate (Czech) Currently translated at 88.3% (280 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/cs/ Author: 5Litt <5Litt@users.noreply.weblate.movie-web.app> --- src/assets/locales/cs.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/assets/locales/cs.json b/src/assets/locales/cs.json index 3fd2586b..71696c49 100644 --- a/src/assets/locales/cs.json +++ b/src/assets/locales/cs.json @@ -270,6 +270,7 @@ }, "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": { @@ -410,10 +411,25 @@ "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í proxy", "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í", From a16295176905795c3720836e8d696cd63f3b90d5 Mon Sep 17 00:00:00 2001 From: atomic Date: Tue, 23 Jan 2024 20:17:41 +0000 Subject: [PATCH 131/151] Translated using Weblate (French) Currently translated at 91.7% (291 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/fr/ Author: atomic --- src/assets/locales/fr.json | 57 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/assets/locales/fr.json b/src/assets/locales/fr.json index 352862f3..c178d85d 100644 --- a/src/assets/locales/fr.json +++ b/src/assets/locales/fr.json @@ -166,6 +166,33 @@ "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": { + "proxy": { + "explainer": "Avec la méthode du proxy, vous pouvez obtenir des flux de bonne qualité en créant un proxy en libre-service.", + "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" + }, + "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" }, @@ -406,6 +433,28 @@ "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", @@ -416,6 +465,14 @@ "urlPlaceholder": "https://" } }, + "preferences": { + "language": "Language de l'application", + "languageDescription": "Langue appliquée à l’ensemble de l’application.", + "thumbnail": "Générer des thumbnails", + "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", "sidebar": { From 61388e26a2bf8d9fecd129ba2aa361865ef74dc4 Mon Sep 17 00:00:00 2001 From: Denys Savin Date: Tue, 23 Jan 2024 20:18:18 +0000 Subject: [PATCH 132/151] Translated using Weblate (Ukrainian) Currently translated at 90.2% (286 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/uk/ Author: Denys Savin --- src/assets/locales/uk.json | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/assets/locales/uk.json b/src/assets/locales/uk.json index f81de1ec..38ef0969 100644 --- a/src/assets/locales/uk.json +++ b/src/assets/locales/uk.json @@ -166,6 +166,23 @@ "message": "Ми шукали всюди: під смітниками, у шафі, за проксі-сервером, але зрештою не змогли знайти сторінку, яку ви шукали.", "title": "Не вдалося знайти цю сторінку" }, + "onboarding": { + "start": { + "explainer": "Щоб отримати найкращу трансляцію. Вам потрібно буде вибрати, який метод стрімінгу ви хочете використовувати.", + "options": { + "extension": { + "quality": "Найкраща якість" + }, + "proxy": { + "action": "Налаштування проксі", + "description": "Налаштуйте проксі всього за 5 хвилин і отримайте доступ до чудових джерел.", + "quality": "Гарна якість", + "title": "Користувацький проксі" + } + }, + "title": "Давайте налаштуємо вам movie-web" + } + }, "overlays": { "close": "Закрити" }, @@ -407,11 +424,24 @@ "urlLabel": "URL сервера" }, "setup": { + "doSetup": "Виконайте налаштування", "errorStatus": { "description": "Здається, що один або декілька пунктів у цьому налаштуванні потребують вашої уваги.", "title": "Дещо потребує вашої уваги" }, + "itemError": "Щось не так із цією настройкою. Пройдіть налаштування ще раз, щоб виправити це.", + "items": { + "default": "Налаштування за замовчанням", + "extension": "Розширення", + "proxy": "Користувацький проксі" + }, + "redoSetup": "Повторити налаштування", + "successStatus": { + "description": "Усе готово для того, щоб ви могли почати дивитися улюблені медіа.", + "title": "Все готово!" + }, "unsetStatus": { + "description": "Будь ласка, натисніть кнопку праворуч, щоб розпочати процес налаштування.", "title": "Ви не завершили налаштування" } }, @@ -425,6 +455,14 @@ "urlPlaceholder": "https://" } }, + "preferences": { + "language": "Мова додатку", + "languageDescription": "Мова застосована до всього додатку.", + "thumbnail": "Створити мініатюри", + "thumbnailDescription": "Часто відео не мають мініатюр. Ви можете активувати цей параметр для їх генерації під час відтворення, але це може уповільнити відтворення відео.", + "thumbnailLabel": "Сгенерувати мініатюри", + "title": "Параметри" + }, "reset": "Скинути налаштування", "save": "Зберегти", "sidebar": { From fe152425af020a7ebec33e1a5378a1838b77c7e8 Mon Sep 17 00:00:00 2001 From: Ninguart Date: Tue, 23 Jan 2024 20:28:30 +0000 Subject: [PATCH 133/151] Translated using Weblate (Czech) Currently translated at 89.5% (284 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/cs/ Author: Ninguart --- src/assets/locales/cs.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/assets/locales/cs.json b/src/assets/locales/cs.json index 71696c49..17196785 100644 --- a/src/assets/locales/cs.json +++ b/src/assets/locales/cs.json @@ -167,6 +167,13 @@ }, "onboarding": { "start": { + "explainer": "Abyste získali co nejlepší streamy. Musíte si zvolit, kterou streamovací metodu chcete použít.", + "options": { + "proxy": { + "quality": "Dobrá kvalita", + "title": "Vlastní proxy" + } + }, "title": "Pojďme vám nastavit movie-web" } }, From 294ddbd0c97fa8d14e858fa3c20963f2cf0fa22a Mon Sep 17 00:00:00 2001 From: 5Litt <5Litt@users.noreply.weblate.movie-web.app> Date: Tue, 23 Jan 2024 20:27:58 +0000 Subject: [PATCH 134/151] Translated using Weblate (Czech) Currently translated at 89.5% (284 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/cs/ Author: 5Litt <5Litt@users.noreply.weblate.movie-web.app> --- src/assets/locales/cs.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/assets/locales/cs.json b/src/assets/locales/cs.json index 17196785..6a4d93b9 100644 --- a/src/assets/locales/cs.json +++ b/src/assets/locales/cs.json @@ -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í" @@ -425,7 +426,7 @@ }, "itemError": "S tímto nastavením je něco špatně. Projděte znovu nastavením abyste to opravili.", "items": { - "default": "Výchozí proxy", + "default": "Výchozí nastavení", "extension": "Rozšíření", "proxy": "Vlastní proxy" }, From 51da00c10eadf424f15d70ac113afe0bbde66ae7 Mon Sep 17 00:00:00 2001 From: atomic Date: Tue, 23 Jan 2024 20:27:45 +0000 Subject: [PATCH 135/151] Translated using Weblate (French) Currently translated at 93.6% (297 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/fr/ Author: atomic --- src/assets/locales/fr.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/assets/locales/fr.json b/src/assets/locales/fr.json index c178d85d..ece555da 100644 --- a/src/assets/locales/fr.json +++ b/src/assets/locales/fr.json @@ -169,6 +169,14 @@ "onboarding": { "proxy": { "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", "title": "Créons un nouveau proxy" }, "start": { From f8071b4653c4e8a237e461a44374a72932b15d48 Mon Sep 17 00:00:00 2001 From: Denys Savin Date: Tue, 23 Jan 2024 20:28:04 +0000 Subject: [PATCH 136/151] Translated using Weblate (Ukrainian) Currently translated at 90.8% (288 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/uk/ Author: Denys Savin --- src/assets/locales/uk.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/assets/locales/uk.json b/src/assets/locales/uk.json index 38ef0969..c28a3945 100644 --- a/src/assets/locales/uk.json +++ b/src/assets/locales/uk.json @@ -171,7 +171,9 @@ "explainer": "Щоб отримати найкращу трансляцію. Вам потрібно буде вибрати, який метод стрімінгу ви хочете використовувати.", "options": { "extension": { - "quality": "Найкраща якість" + "description": "Встановіть розширення для браузера та отримайте доступ до найкращих джерел.", + "quality": "Найкраща якість", + "title": "Розширення браузера" }, "proxy": { "action": "Налаштування проксі", From 69b843f85acf7487e091044b66ce9ee88753fc85 Mon Sep 17 00:00:00 2001 From: 5Litt <5Litt@users.noreply.weblate.movie-web.app> Date: Tue, 23 Jan 2024 20:31:31 +0000 Subject: [PATCH 137/151] Translated using Weblate (Czech) Currently translated at 94.6% (300 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/cs/ Author: 5Litt <5Litt@users.noreply.weblate.movie-web.app> --- src/assets/locales/cs.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/assets/locales/cs.json b/src/assets/locales/cs.json index 6a4d93b9..e3e7ca21 100644 --- a/src/assets/locales/cs.json +++ b/src/assets/locales/cs.json @@ -167,10 +167,26 @@ "title": "Tuto stránku se nepodařilo najít" }, "onboarding": { + "proxy": { + "explainer": "Pomocí metody proxy můžete získat streamy ve skvělé kvalitě vytvořením proxy serveru.", + "link": "Naučit se vytvořit proxy", + "title": "Pojďme uďelat novou proxy" + }, "start": { "explainer": "Abyste získali co nejlepší streamy. Musíte si zvolit, kterou streamovací metodu chcete použít.", "options": { + "default": { + "text": "Nechci zdroje s dobrou kvalitou,<0 /> <1>použít výchozí nastavení" + }, + "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" } From 0e95e9c381d304a37f7d1d8843cc5660a4e4ba46 Mon Sep 17 00:00:00 2001 From: Ninguart Date: Tue, 23 Jan 2024 20:30:36 +0000 Subject: [PATCH 138/151] Translated using Weblate (Czech) Currently translated at 94.6% (300 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/cs/ Author: Ninguart --- src/assets/locales/cs.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/assets/locales/cs.json b/src/assets/locales/cs.json index e3e7ca21..c8374511 100644 --- a/src/assets/locales/cs.json +++ b/src/assets/locales/cs.json @@ -167,8 +167,22 @@ "title": "Tuto stránku se nepodařilo najít" }, "onboarding": { + "defaultConfirm": { + "cancel": "Zrušit" + }, + "extension": { + "status": { + "outdated": "Verze rozšíření je příliš stará.", + "success": "Rozšíření funguje podle očekávání!" + }, + "submit": "Pokračovat" + }, "proxy": { "explainer": "Pomocí metody proxy můžete získat streamy ve skvělé kvalitě vytvořením proxy serveru.", + "input": { + "label": "Proxy URL", + "placeholder": "https://" + }, "link": "Naučit se vytvořit proxy", "title": "Pojďme uďelat novou proxy" }, From 8b414fa4d40d37bba55a29b1e9d9afabe6196228 Mon Sep 17 00:00:00 2001 From: atomic Date: Tue, 23 Jan 2024 20:28:41 +0000 Subject: [PATCH 139/151] Translated using Weblate (French) Currently translated at 99.0% (314 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/fr/ Author: atomic --- src/assets/locales/fr.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/assets/locales/fr.json b/src/assets/locales/fr.json index ece555da..4ced1b85 100644 --- a/src/assets/locales/fr.json +++ b/src/assets/locales/fr.json @@ -167,7 +167,30 @@ "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.", + "extensionHelp": "Si vous avez installé l'extension mais qu'elle n'est pas détectée. Ouvrez l'extension via le menu des extensions de votre navigateur et suivez les étapes à l'écran.", + "link": "Installer l'extension", + "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", @@ -177,6 +200,7 @@ "placeholder": "https://" }, "link": "Apprenez à créer un proxy", + "submit": "Soumettre le proxy", "title": "Créons un nouveau proxy" }, "start": { From 1ee4fdb7fc9077589c7cf6355fbffe184bbc0349 Mon Sep 17 00:00:00 2001 From: Denys Savin Date: Tue, 23 Jan 2024 20:30:50 +0000 Subject: [PATCH 140/151] Translated using Weblate (Ukrainian) Currently translated at 93.6% (297 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/uk/ Author: Denys Savin --- src/assets/locales/uk.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/assets/locales/uk.json b/src/assets/locales/uk.json index c28a3945..d4ea2478 100644 --- a/src/assets/locales/uk.json +++ b/src/assets/locales/uk.json @@ -167,10 +167,25 @@ "title": "Не вдалося знайти цю сторінку" }, "onboarding": { + "proxy": { + "explainer": "З використанням проксі ви можете отримати високоякісні потоки, створивши самостійний проксі-сервіс.", + "input": { + "errorConnection": "Не вдалося підключитися до проксі", + "errorInvalidUrl": "Не валідний URL", + "label": "URL проксі", + "placeholder": "https://" + }, + "link": "Дізнайтесь як створити проксі", + "title": "Давайте створимо новий проксі" + }, "start": { "explainer": "Щоб отримати найкращу трансляцію. Вам потрібно буде вибрати, який метод стрімінгу ви хочете використовувати.", "options": { + "default": { + "text": "Мені не потрібна хороша якість потоків,<0 /> <1>використовувати налаштування за замовчуванням" + }, "extension": { + "action": "Встановити розширення", "description": "Встановіть розширення для браузера та отримайте доступ до найкращих джерел.", "quality": "Найкраща якість", "title": "Розширення браузера" From e788478f6a39e012f9bb4bf0947d9dc51c60a8f4 Mon Sep 17 00:00:00 2001 From: Ninguart Date: Tue, 23 Jan 2024 20:32:41 +0000 Subject: [PATCH 141/151] Translated using Weblate (Czech) Currently translated at 94.9% (301 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/cs/ Author: Ninguart --- src/assets/locales/cs.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/assets/locales/cs.json b/src/assets/locales/cs.json index c8374511..25665f4a 100644 --- a/src/assets/locales/cs.json +++ b/src/assets/locales/cs.json @@ -180,6 +180,7 @@ "proxy": { "explainer": "Pomocí metody proxy můžete získat streamy ve skvělé kvalitě vytvořením proxy serveru.", "input": { + "errorInvalidUrl": "Adresa URL není platná.", "label": "Proxy URL", "placeholder": "https://" }, From e81fff4e07f3ea9cba01e75fb703604bf4808554 Mon Sep 17 00:00:00 2001 From: Ninguart Date: Tue, 23 Jan 2024 20:32:49 +0000 Subject: [PATCH 142/151] Translated using Weblate (Czech) Currently translated at 96.5% (306 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/cs/ Author: Ninguart --- src/assets/locales/cs.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/assets/locales/cs.json b/src/assets/locales/cs.json index 25665f4a..e13d7baf 100644 --- a/src/assets/locales/cs.json +++ b/src/assets/locales/cs.json @@ -171,6 +171,8 @@ "cancel": "Zrušit" }, "extension": { + "back": "Zpět", + "link": "Instalovat rozšíření", "status": { "outdated": "Verze rozšíření je příliš stará.", "success": "Rozšíření funguje podle očekávání!" @@ -178,9 +180,10 @@ "submit": "Pokračovat" }, "proxy": { + "back": "Zpět", "explainer": "Pomocí metody proxy můžete získat streamy ve skvělé kvalitě vytvořením proxy serveru.", "input": { - "errorInvalidUrl": "Adresa URL není platná.", + "errorInvalidUrl": "Adresa URL není platná", "label": "Proxy URL", "placeholder": "https://" }, From ed5156809f18c808f26575b0428896aba9415868 Mon Sep 17 00:00:00 2001 From: 5Litt <5Litt@users.noreply.weblate.movie-web.app> Date: Tue, 23 Jan 2024 20:33:00 +0000 Subject: [PATCH 143/151] Translated using Weblate (Czech) Currently translated at 96.5% (306 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/cs/ Author: 5Litt <5Litt@users.noreply.weblate.movie-web.app> --- src/assets/locales/cs.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/assets/locales/cs.json b/src/assets/locales/cs.json index e13d7baf..0ade7853 100644 --- a/src/assets/locales/cs.json +++ b/src/assets/locales/cs.json @@ -183,7 +183,9 @@ "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://" }, From ff23d1b1a3d9517c1470b6cdd31f2c222561fc99 Mon Sep 17 00:00:00 2001 From: Ninguart Date: Tue, 23 Jan 2024 20:34:24 +0000 Subject: [PATCH 144/151] Translated using Weblate (Czech) Currently translated at 99.0% (314 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/cs/ Author: Ninguart --- src/assets/locales/cs.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/assets/locales/cs.json b/src/assets/locales/cs.json index 0ade7853..d6317939 100644 --- a/src/assets/locales/cs.json +++ b/src/assets/locales/cs.json @@ -168,12 +168,15 @@ }, "onboarding": { "defaultConfirm": { - "cancel": "Zrušit" + "cancel": "Zrušit", + "title": "Jste si jist?" }, "extension": { "back": "Zpět", "link": "Instalovat rozšíření", "status": { + "disallowed": "Rozšíření není pro tuto stránku povoleno", + "disallowedAction": "Povolit rozšíření", "outdated": "Verze rozšíření je příliš stará.", "success": "Rozšíření funguje podle očekávání!" }, From 7d88a435d2fb473a35d19e9153955b7ef784cb6e Mon Sep 17 00:00:00 2001 From: 5Litt <5Litt@users.noreply.weblate.movie-web.app> Date: Tue, 23 Jan 2024 20:37:32 +0000 Subject: [PATCH 145/151] Translated using Weblate (Czech) Currently translated at 99.0% (314 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/cs/ Author: 5Litt <5Litt@users.noreply.weblate.movie-web.app> --- src/assets/locales/cs.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/assets/locales/cs.json b/src/assets/locales/cs.json index d6317939..bf6b4011 100644 --- a/src/assets/locales/cs.json +++ b/src/assets/locales/cs.json @@ -173,14 +173,18 @@ }, "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. Otevřete rozšíření pomocí nabídky rozšíření ve vašem prohlížeči a postupujte podle pokynů na obrazovce.", "link": "Instalovat rozšíření", "status": { "disallowed": "Rozšíření není pro tuto stránku povoleno", "disallowedAction": "Povolit rozšíření", + "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" + "submit": "Pokračovat", + "title": "Začněme s rozšířením" }, "proxy": { "back": "Zpět", @@ -193,6 +197,7 @@ "placeholder": "https://" }, "link": "Naučit se vytvořit proxy", + "submit": "Předložit proxy", "title": "Pojďme uďelat novou proxy" }, "start": { From bc93a6b403c76475eb723340db27edd10639ad5d Mon Sep 17 00:00:00 2001 From: atomic Date: Tue, 23 Jan 2024 20:39:33 +0000 Subject: [PATCH 146/151] Translated using Weblate (French) Currently translated at 100.0% (317 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/fr/ Author: atomic --- src/assets/locales/fr.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/fr.json b/src/assets/locales/fr.json index 4ced1b85..9b321529 100644 --- a/src/assets/locales/fr.json +++ b/src/assets/locales/fr.json @@ -242,7 +242,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.

Veuillez noter que vous téléchargez une liste de lecture HLS, il n'est pas recommandé de télécharger si vous n'êtes pas familier avec les formats de streaming avancés. . 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, tapez et maintenez sur la vidéo, puis sélectionnez enregistrer.", "shortTitle": "Télécharger / Android", @@ -500,7 +500,7 @@ "preferences": { "language": "Language de l'application", "languageDescription": "Langue appliquée à l’ensemble de l’application.", - "thumbnail": "Générer des thumbnails", + "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" From eb22253a2a4d724d94e7c1c5896f158212bfe2bf Mon Sep 17 00:00:00 2001 From: Denys Savin Date: Tue, 23 Jan 2024 20:39:05 +0000 Subject: [PATCH 147/151] Translated using Weblate (Ukrainian) Currently translated at 97.4% (309 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/uk/ Author: Denys Savin --- src/assets/locales/uk.json | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/assets/locales/uk.json b/src/assets/locales/uk.json index d4ea2478..f6678af7 100644 --- a/src/assets/locales/uk.json +++ b/src/assets/locales/uk.json @@ -167,15 +167,31 @@ "title": "Не вдалося знайти цю сторінку" }, "onboarding": { + "extension": { + "back": "Повернутись назад", + "explainer": "Використовуючи розширення для браузера, ви можете отримати найякісніші трансляції, які ми можемо запропонувати. Просто встановивши його.", + "extensionHelp": "Якщо ви встановили розширення, але воно не виявлено. Відкрийте розширення в меню розширень вашого браузеру і дотримуйтеся вказівок на екрані.", + "link": "Встановити розширення", + "status": { + "disallowed": "Розширення не ввімкнено для цієї сторінки", + "disallowedAction": "Активувати розширення", + "failed": "Не вдалося отримати статус", + "loading": "Очікуємо, поки ви встановите розширення" + }, + "title": "Почати використовувати розширення" + }, "proxy": { + "back": "Повернутись назад", "explainer": "З використанням проксі ви можете отримати високоякісні потоки, створивши самостійний проксі-сервіс.", "input": { "errorConnection": "Не вдалося підключитися до проксі", "errorInvalidUrl": "Не валідний URL", + "errorNotProxy": "Очікувався проксі, але отримано вебсайт", "label": "URL проксі", "placeholder": "https://" }, "link": "Дізнайтесь як створити проксі", + "submit": "Надати проксі", "title": "Давайте створимо новий проксі" }, "start": { From 307324304b98f2105e959d6442dc9db9be8119fd Mon Sep 17 00:00:00 2001 From: 5Litt <5Litt@users.noreply.weblate.movie-web.app> Date: Tue, 23 Jan 2024 20:41:37 +0000 Subject: [PATCH 148/151] Translated using Weblate (Czech) Currently translated at 100.0% (317 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/cs/ Author: 5Litt <5Litt@users.noreply.weblate.movie-web.app> --- src/assets/locales/cs.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/assets/locales/cs.json b/src/assets/locales/cs.json index bf6b4011..4141941c 100644 --- a/src/assets/locales/cs.json +++ b/src/assets/locales/cs.json @@ -169,6 +169,8 @@ "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": { @@ -179,8 +181,9 @@ "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á.", + "outdated": "Verze rozšíření je příliš stará", "success": "Rozšíření funguje podle očekávání!" }, "submit": "Pokračovat", From 07e0d42f84f3ce1aa45e48672636fe4ab24e2ce7 Mon Sep 17 00:00:00 2001 From: Denys Savin Date: Tue, 23 Jan 2024 20:41:04 +0000 Subject: [PATCH 149/151] Translated using Weblate (Ukrainian) Currently translated at 100.0% (317 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/uk/ Author: Denys Savin --- src/assets/locales/uk.json | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/uk.json b/src/assets/locales/uk.json index f6678af7..8d8267d6 100644 --- a/src/assets/locales/uk.json +++ b/src/assets/locales/uk.json @@ -167,6 +167,12 @@ "title": "Не вдалося знайти цю сторінку" }, "onboarding": { + "defaultConfirm": { + "cancel": "Скасувати", + "confirm": "Використовувати налаштування за умовчанням", + "description": "Налаштування за замовчуванням не мають найкращих потоків і можуть бути нестерпно повільними.", + "title": "Ви впевнені?" + }, "extension": { "back": "Повернутись назад", "explainer": "Використовуючи розширення для браузера, ви можете отримати найякісніші трансляції, які ми можемо запропонувати. Просто встановивши його.", @@ -176,8 +182,11 @@ "disallowed": "Розширення не ввімкнено для цієї сторінки", "disallowedAction": "Активувати розширення", "failed": "Не вдалося отримати статус", - "loading": "Очікуємо, поки ви встановите розширення" + "loading": "Очікуємо, поки ви встановите розширення", + "outdated": "Версія розширення застаріла", + "success": "Розширення працює як очікувалося!" }, + "submit": "Продовжити", "title": "Почати використовувати розширення" }, "proxy": { @@ -233,7 +242,7 @@ "downloadPlaylist": "Завантажити плейлист", "downloadSubtitle": "Завантажити поточні субтитри", "downloadVideo": "Завантажити відео", - "hlsDisclaimer": "Завантаження виконуються безпосередньо від постачальника. У movie-web немає контролю над тим, як надаються завантаження. Будь ласка, зверніть увагу, що ви завантажуєте список відтворення HLS, він призначений для користувачів, знайомих із розширеним потоковим мультимедійним вмістом.", + "hlsDisclaimer": "Завантаження виконуються безпосередньо від постачальника. У movie-web немає контролю над тим, як надаються завантаження.

Зверніть увагу, що ви завантажуєте список відтворення HLS, його не рекомендується завантажувати, якщо ви не знайомі з розширеними форматами потокового передавання. Спробуйте різні джерела для інших форматів.", "onAndroid": { "1": "Щоб завантажити на Android, натисніть кнопку завантаження, потім на новій сторінці торкніться й утримуйте відео, а потім виберіть зберегти.", "shortTitle": "Завантажити / Android", From 2d953757501f345cf4b8e49820f22c56fe817673 Mon Sep 17 00:00:00 2001 From: Denys Savin Date: Tue, 23 Jan 2024 20:49:54 +0000 Subject: [PATCH 150/151] Translated using Weblate (Ukrainian) Currently translated at 100.0% (317 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/uk/ Author: Denys Savin --- src/assets/locales/uk.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assets/locales/uk.json b/src/assets/locales/uk.json index 8d8267d6..5124e55d 100644 --- a/src/assets/locales/uk.json +++ b/src/assets/locales/uk.json @@ -393,7 +393,7 @@ }, "screens": { "dmca": { - "text": "Вітаємо на нашій сторінці зв'язку DMCA! Ми поважаємо права інтелектуальної власності і хочемо вирішити будь-які проблеми з авторськими правами швидко. Якщо ви вважаєте, що ваші авторські права були неправильно використані на нашій платформі, будь ласка, надішліть детальне повідомлення DMCA на електронну адресу нижче. Будь ласка, вкажіть опис авторського матеріалу, ваші контактні дані та заяву про добросовісну віру. Ми зобов'язані вирішити ці питання оперативно і вдячні за вашу співпрацю в збереженні movie-web місцем, яке поважає творчість та авторські права", + "text": "Вітаємо на нашій сторінці зв'язку DMCA! Ми поважаємо права інтелектуальної власності і хочемо вирішити будь-які проблеми з авторськими правами швидко. Якщо ви вважаєте, що ваші авторські права були неправильно використані на нашій платформі, будь ласка, надішліть детальне повідомлення DMCA на електронну адресу нижче. Будь ласка, вкажіть опис авторського матеріалу, ваші контактні дані та заяву про добросовісну віру. Ми зобов'язані вирішити ці питання оперативно і вдячні за вашу співпрацю в збереженні movie-web місцем, яке поважає творчість та авторські права.", "title": "DMCA" }, "loadingApp": "Завантаження застосунку", @@ -461,7 +461,7 @@ }, "connections": { "server": { - "description": "Якщо ви хочете використовувати власний сервер, введіть його URL нижче. Якщо ви не знаєте, що це таке, ви, ймовірно, не повинні цього робити.", + "description": "Якщо ви бажаєте підключитися до користувацького сервера для зберігання даних, увімкніть це та вкажіть URL-адресу. <0>Інструкції.", "label": "Власний сервер", "urlLabel": "URL сервера" }, From 4198143b3449e26eb52b85ce7e3afb13c19f8bf3 Mon Sep 17 00:00:00 2001 From: admin Date: Tue, 23 Jan 2024 20:52:19 +0000 Subject: [PATCH 151/151] Translated using Weblate (Czech) Currently translated at 100.0% (317 of 317 strings) Translation: movie-web/website Translate-URL: https://weblate.movie-web.app/projects/movie-web/website/cs/ Author: admin --- src/assets/locales/cs.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/assets/locales/cs.json b/src/assets/locales/cs.json index 4141941c..cdd13ba3 100644 --- a/src/assets/locales/cs.json +++ b/src/assets/locales/cs.json @@ -242,7 +242,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ý není doporučen stahovat pokud nejste obeznámeni s pokročilým streamováním médií. Raději skuste jiný zdroj pro jiný formát.", + "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ý není doporučen stahovat pokud nejste obeznámeni s pokročilým streamováním médií. 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 klepněte a podržte na videu a poté vyberte uložit.", "shortTitle": "Stahování / Android", @@ -461,7 +461,7 @@ }, "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.", "label": "Vlastní server", "urlLabel": "URL adresa vlastního serveru" }, @@ -490,7 +490,7 @@ "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.", "emptyState": "Zatím žádní pracovníci, přidej jednoho dolů", "label": "Použít vlastní proxy pracovníky", "urlLabel": "URL adresy pracovníků",